Intermediate: machine learning · Evaluating models · topic 32 of 62 · 30 min
Cross-validation and tuning hyperparameters
Explanation
Why one validation split is not enough
With a small dataset, the score on one validation split depends a lot on which rows happened to land there. Run again with a different split and the score may jump by several points. You might pick a "winning" model that only won by luck. Cross-validation averages over several splits to reduce this luck.
k-fold cross-validation
- Split the training data into k equal parts called folds (k = 5 or 10 is common).
- For each fold: train on the other k − 1 folds and score on this fold.
- Average the k scores, and look at their spread too.
Every example is used for validation exactly once and for training k − 1 times. If 10 rows are split into 3 folds, the folds get 4, 3 and 3 rows: when the rows do not divide evenly, scikit-learn gives the first n % k folds one extra row.
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier
scores = cross_val_score(DecisionTreeClassifier(max_depth=4), X_train, y_train, cv=5, scoring="f1")
print(scores.round(3), scores.mean().round(3)) # e.g. [0.71 0.68 0.74 0.70 0.69] 0.704Stratified and grouped folds
For classification, StratifiedKFold keeps the class balance in each fold (scikit-learn uses it by default for classifiers when you pass cv=5). If the same customer or patient appears in several rows, use GroupKFold so all their rows stay in one fold; otherwise the model is tested on people it has already seen. For time series, use TimeSeriesSplit, which always trains on earlier data and validates on later data.
Parameters versus hyperparameters
Parameters are learned during training: the weights of a regression, the split points of a tree. Hyperparameters are chosen by you before training: the tree's max_depth, the number of neighbours k in k-NN, the regularisation strength alpha, the learning rate. Tuning means trying hyperparameter values and keeping the best by cross-validated score.
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(
DecisionTreeClassifier(random_state=0),
param_grid={"max_depth": [3, 5, 8], "min_samples_leaf": [1, 5, 20]},
cv=5, scoring="f1",
)
grid.fit(X_train, y_train)
print(grid.best_params_, round(grid.best_score_, 3))
print(grid.score(X_test, y_test)) # final check, onceKeep the test set out of tuning
Cross-validation runs on the training data. The test set is touched once, after you have chosen the model and its hyperparameters. If you tune with cross-validation and then also choose between final candidates by their test score, you have tuned on the test set again. For research-grade estimates, nested cross-validation puts the whole tuning loop inside an outer CV loop.
Common mistakes
- Preprocessing (scaling, filling) on all data before CV, which leaks across folds. Fix: put preprocessing in a Pipeline so it is refitted inside each fold (module 8).
- Using plain k-fold for time series. Fix: TimeSeriesSplit.
- Reporting only the mean CV score. Fix: also report the spread; a mean of 0.80 with scores from 0.60 to 0.95 is unstable.
- Huge grids that take days. Fix: start coarse, then zoom in, or use randomised search.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Cross-validation and tuning hyperparameters · 1/7
One validation split can be lucky or unlucky. Cross-validation averages over several.
Prefer a video by a teacher? Find free videos on “k fold cross validation grid search hyperparameter tuning scikit-learn” on YouTube ↗
In real life: Choosing a model for a small hospital dataset
A research team has only 600 patient records to predict a complication. A single 80/20 split gave scores that changed by 8 points from run to run. They switched to stratified 10-fold cross-validation with patients grouped by hospital, tuned two hyperparameters with a small grid, and reported the mean and spread of the CV scores. The final model was checked once on records from a different year before publication.
Practice (0/2 done)
Write fold_sizes(n, k) like scikit-learn's KFold: k folds whose sizes add up to n, where the first n % k folds get one extra item. Example: fold_sizes(10, 3) returns [4, 3, 3].
Write kfold_indices(n, k) that returns a list of k pairs (train, test) for indices 0..n−1 with NO shuffling: the folds are consecutive blocks, sized as in fold_sizes (first n % k folds one bigger). For each fold, test is that block and train is every other index, both in increasing order.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Regression metrics: MAE, MSE, RMSE and R²Evaluating models · same module
- Thresholds, ROC-AUC and imbalanced classesEvaluating models · same module
- Scaling and transforming numbersClustering, dimensionality reduction and feature engineering
- Fine-tuning, and when not toBuilding with generative AI, and MLOps
- Feature selection, leakage and pipelinesClustering, dimensionality reduction and feature engineering
- Tuning profiles with tuned, and time with chronyLinux and Red Hat (RHCSA to RHCE) · Processes, services and logs
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
In 5-fold cross-validation, how many times is the model trained?
Answer: 5
Once per fold.
Which is a hyperparameter?
Answer: The maximum depth of a decision tree
You choose max_depth before training; the others are learned.
Several rows belong to the same customer. Which CV method avoids testing on customers seen in training?
Answer: GroupKFold
GroupKFold keeps each group in a single fold.
Where should the test set be used?
Answer: Once, after model and hyperparameters are chosen
Using it during tuning makes its score optimistic.
CV scores are [0.91, 0.62, 0.88, 0.70, 0.94]. What should worry you?
Answer: The large spread: performance is unstable across folds
High spread suggests the model or data is unstable; report it and investigate.
A model scores 99.8% on the test set for a hard real-world task. What should you do first?Related
Answer: Look for leakage
Scores that are too good usually mean the answer leaked into the features.
Which model does NOT need feature scaling?Related
Answer: Random forest
Trees split one feature at a time on thresholds.
Your 2,000 training examples contain many inconsistent labels. What will fine-tuning likely produce?Related
Answer: A model that copies the inconsistency
The model learns whatever patterns are in the examples, including mistakes.
What is the main benefit of a scikit-learn Pipeline in cross-validation?Related
Answer: Preprocessing is refitted on each training fold, preventing leakage
Each fold's scaler and imputer see only that fold's training data.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Evaluating models”. The module exam comes next.
- Module 6 exam: Evaluating models · 12 questions · 25 min, without help. 6 topics of this module still to finish first.
- Then the next module, k-NN, decision trees and ensembles. 62 topics left in the course before the final exam.