Cross-validation

core 9 minmodel-evaluationvalidation

Builds on:Bias-variance tradeoff

The idea

A single train/test split gives you one noisy measurement of generalization error — which points landed in the test fold changes the number, badly so on small data. Cross-validation buys a better estimate by recycling the data: split into kk folds, train kk models each with a different fold held out, average the kk held-out scores.

Err^CV=1k∑j=1kErrj\widehat{\text{Err}}_{CV} = \frac{1}{k}\sum_{j=1}^{k} \text{Err}_j

Averaging reduces the variance of the estimate; every observation gets validated exactly once. Two forces set kk:

Variants that matter:

The classic trap: preprocessing fit on the full dataset before splitting. Scalers, imputers, target encoders, feature selection, SMOTE — all of it must be fit inside each training fold (use a pipeline), or validation folds contaminate training and every score inflates.

Worked example

A 5-fold CV run returns accuracies:

0.81,0.79,0.84,0.80,0.830.81, \quad 0.79, \quad 0.84, \quad 0.80, \quad 0.83

Mean: aˉ=4.07/5=0.814\bar{a} = 4.07 / 5 = 0.814. Sample standard deviation: deviations (−0.004,−0.024,+0.026,−0.014,+0.016)(-0.004, -0.024, +0.026, -0.014, +0.016), squared sum 0.001720.00172, so s=0.00172/4≈0.021s = \sqrt{0.00172/4} \approx 0.021. Report 0.814 ± 0.021, not "0.84" (the best fold) and not "81.4%" with false precision.

Why the spread matters: suppose a competing model scores folds 0.83,0.84,0.81,0.85,0.820.83, 0.84, 0.81, 0.85, 0.82 — mean 0.830.83. The gap between models (0.0160.016) is smaller than the fold-to-fold noise (≈0.02\approx 0.02), so this comparison is not yet decisive; compare per-fold differences (both models on the same folds) or use repeated CV before declaring a winner. A hiring-loop favorite: "model A got 81.4, model B got 83.0 — which do you ship?" The right answer starts with "what is the variance?"

Cheat sheet

Procedure: kk folds → train on k−1k-1, validate on 1, rotate; report mean ± std of fold scores.

SituationRight protocol
Balanced classification / regressionplain k-fold, k=5k = 5 or 1010
Imbalanced / small classesstratified k-fold
Repeated measures of same entitygroup k-fold (entity in exactly one fold)
Temporal dataexpanding/rolling window, train strictly before validate
Tiny datasetLOOCV or repeated k-fold (know the variance caveat)
Hyperparameter tuning AND honest estimatenested CV, or tune-on-CV + final untouched test set