import argparse
from pathlib import Path
import numpy as np
import numpy.typing as npt
import toml
from sklearn.linear_model import Ridge
from scripts.optimize.utils import (
calculate_metrics,
filter_outliers,
load_dataset_with_texts,
print_metrics,
)
from skimtoken.basic import count
def extract_features(texts: list[str]) -> npt.NDArray[np.float64]:
features: list[list[float]] = []
for text in texts:
char_count, word_count, avg_word_length, space_count = count(text)
features.append([char_count, word_count, avg_word_length, space_count])
return np.array(features)
def optimize_parameters(
dataset_path: Path, val_path: Path | None = None, max_samples: int | None = None
) -> dict[str, float]:
print(f"Loading training data from {dataset_path}...")
texts, token_lens = load_dataset_with_texts(dataset_path, max_samples)
print(f"Loaded {len(texts)} text samples")
print("Extracting features...")
X_train = extract_features(texts)
print("Using pre-calculated token counts...")
y_train = np.array(token_lens)
X_train, y_train = filter_outliers(X_train, y_train, percentile=1.0)
print(f"After filtering: {len(y_train)} samples")
print("Fitting linear regression model using least squares...")
model = Ridge(alpha=1.0, fit_intercept=True, max_iter=10000)
model.fit(X_train, y_train)
char_coef, word_coef, avg_word_length_coef, space_coef = model.coef_ intercept = model.intercept_
y_train_pred = np.maximum(model.predict(X_train), 0) train_metrics = calculate_metrics(y_train, y_train_pred)
print("\nOptimized Parameters:")
print(f" char_coef: {char_coef:.6f}")
print(f" word_coef: {word_coef:.6f}")
print(f" avg_word_length_coef: {avg_word_length_coef:.6f}")
print(f" space_coef: {space_coef:.6f}")
print(f" intercept: {intercept:.6f}")
print_metrics(train_metrics, "Training Metrics:")
if val_path and val_path.exists():
print(f"\nLoading validation data from {val_path}...")
val_texts, val_token_lens = load_dataset_with_texts(val_path)
print(f"Loaded {len(val_texts)} validation samples")
X_val = extract_features(val_texts)
y_val = np.array(val_token_lens)
y_val_pred = np.maximum(model.predict(X_val), 0) val_metrics = calculate_metrics(y_val, y_val_pred)
print_metrics(val_metrics, "Validation Metrics:")
return {
"char_coef": float(char_coef), "word_coef": float(word_coef), "avg_word_length_coef": float(avg_word_length_coef), "space_coef": float(space_coef), "intercept": float(intercept), }
def main() -> None:
parser = argparse.ArgumentParser(description="Optimize BasicMethod parameters")
parser.add_argument(
"--dataset",
type=Path,
default=Path("data/cc100_samples/train.jsonl"),
help="Path to training dataset JSONL file",
)
parser.add_argument(
"--val-dataset",
type=Path,
default=Path("data/cc100_samples/val.jsonl"),
help="Path to validation dataset JSONL file",
)
parser.add_argument(
"--max-samples", type=int, default=None, help="Maximum number of samples to use"
)
parser.add_argument(
"--output", type=Path, default=Path("params/basic.toml"), help="Output path for parameters"
)
args = parser.parse_args()
params = optimize_parameters(args.dataset, args.val_dataset, args.max_samples)
args.output.parent.mkdir(parents=True, exist_ok=True)
with open(args.output, "w") as f:
toml.dump(params, f)
print(f"\nParameters saved to {args.output}")
if __name__ == "__main__":
main()