Skip to content

Intermediate: machine learning · Evaluating models · topic 32 of 62 · 30 min

Cross-validation and tuning hyperparameters

Explanation

Cross-validation splits the training data into k parts (folds), trains k times, each time testing on a different fold, and averages the scores. It gives a steadier estimate than one split. Hyperparameters are settings you choose before training, like tree depth; you tune them with cross-validation and keep the test set for the very end.

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

  1. Split the training data into k equal parts called folds (k = 5 or 10 is common).
  2. For each fold: train on the other k − 1 folds and score on this fold.
  3. 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.

python
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.704
Five folds, five F1 scores, then their mean. Numbers are illustrative; shown only.

Stratified 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.

python
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, once
GridSearchCV tries all 9 combinations with 5-fold CV each (45 fits). RandomizedSearchCV samples combinations instead, which is better when there are many. Shown only.

Keep 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

Cross-validation

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)

Task 1 · Code · Python

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].

Task 2 · Code · Python

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

Question 1

1.In 5-fold cross-validation, how many times is the model trained?

Question 2

2.Which is a hyperparameter?

Question 3

3.Several rows belong to the same customer. Which CV method avoids testing on customers seen in training?

Question 4

4.Where should the test set be used?

Question 5

5.CV scores are [0.91, 0.62, 0.88, 0.70, 0.94]. What should worry you?

Read more (free)

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.

From Train, validation and test sets

Which model does NOT need feature scaling?Related

Answer: Random forest

Trees split one feature at a time on thresholds.

From Scaling and transforming numbers

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.

From Fine-tuning, and when not to

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.

From Feature selection, leakage and pipelines

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

  1. This is the last topic of “Evaluating models”. The module exam comes next.
  2. Module 6 exam: Evaluating models · 12 questions · 25 min, without help. 6 topics of this module still to finish first.
  3. Then the next module, k-NN, decision trees and ensembles. 62 topics left in the course before the final exam.

← Previous: Overfitting, underfitting and regularisation