Search the space
Optuna’s
TPESampler (seeded at RANDOM_STATE) proposes hyperparameter configurations from a 9-dimensional space. MedianPruner kills unpromising trials after each CV fold, keeping the search efficient even with 50 trials.The three regularisation strengths map directly to the terms in the XGBoost regularised objective:where is the leaf count and the leaf weights. All three are searched on a log scale because their effect is multiplicative a move from 0.001 to 0.01 matters as much as a move from 1.0 to 10.0.
Score on season-grouped CV
Each trial is evaluated by season-grouped
TimeSeriesSplit across five folds. The folds respect temporal ordering future seasons never inform models of past seasons and the headline metric varies by model family:- Quantile trio: mean pinball loss across folds (↓ lower is better)
- Cliff classifier: mean macro-F1 across folds (↑ higher is better)
- Stint-life regressor: mean RMSE across folds (↓ lower is better)
ml/models/{target}_best_params.json. The Optuna study is persisted to ml/models/optuna_studies/{target}_{version}.db, so it is resumable a rerun with load_if_exists=True extends the existing study rather than starting from scratch.Refit on the full training set
Once the best hyperparameters are selected, the booster is trained on the entire training set (all seasons except the holdout). Cross-validation selected the configuration; the complete dataset trains the shipped model.This is the step that produces the
.bst booster artefacts. The refit runs automatically after tuning completes make ml-tune chains into ml-train for the tuned version.Reduced v1 budget. The shipped v1 parameters used a reduced tuning budget (15 trials / 3 folds / 30,000-row search subsample) for speed during initial development. The canonical
make ml-tune (50 trials / 5 folds / full data) only improves the parameters. The beats-baseline gate holds regardless of budget.
Reproducible and resumable studies
Reproducible and resumable studies
Every study is keyed by
{target}_{version} (e.g. cliff_classifier_v5) so a fresh tuning run for a new version gets its own namespace without overwriting the existing study. The TPESampler is seeded by RANDOM_STATE = 20260528, so two runs with the same data and the same budget produce the same parameter sequence.The .db files are SQLite they can be inspected with optuna-dashboard or the scripts/inspect_trials.py utility. CI does not run ml-tune (it is too slow for pull requests); it runs ml-test against the committed .bst artefacts.Relationships
Models
The five objectives and why each model’s loss function shapes what the tuning search is optimising.
Validation
Season-grouped CV the same scheme the tuning search uses as its objective.
Model Reference
The committed best-parameter values for each model, alongside the headline metrics they produce.
Pipeline
Where
ml-tune sits in the full make ml-all DAG.