AnyLearn
All lessons
AIintermediate

Generalization: Measuring What a Model Actually Learned

Training error flatters every model. Learn how train, validation and test splits work, watch overfitting happen in computed numbers, and see how regularization, cross-validation and leak-proof pipelines give you a score you can trust on data the model has never seen.

Updated · AI-authored, review-gated · how lessons are made

Not signed in: your progress and quiz score won't be saved.
Progress1 / 10

Training error is a biased witness

A supervised model is fitted by minimising its error on the training examples (the previous lesson in this course sets this up). That makes training error the one number guaranteed to look good: the fitting procedure chose the parameters specifically to make it small.

The quantity you care about is different. Generalization error is the expected error on new examples drawn from the same process as the training data. You can never compute it exactly, because it is an average over data you do not have. You can only estimate it, and every estimate needs examples the model did not use for fitting.

Key idea: The gap between training error and generalization error is the model's optimism. A decision tree grown to full depth routinely scores 100% on its own training set. On the scikit-learn breast cancer dataset, one does exactly that, then scores 91.7% under five-fold cross-validation. Only the second number says anything about the next patient.

Full lesson text

All 10 steps on one page, for reading, reference, and search.

Show

1. Training error is a biased witness

A supervised model is fitted by minimising its error on the training examples (the previous lesson in this course sets this up). That makes training error the one number guaranteed to look good: the fitting procedure chose the parameters specifically to make it small.

The quantity you care about is different. Generalization error is the expected error on new examples drawn from the same process as the training data. You can never compute it exactly, because it is an average over data you do not have. You can only estimate it, and every estimate needs examples the model did not use for fitting.

Key idea: The gap between training error and generalization error is the model's optimism. A decision tree grown to full depth routinely scores 100% on its own training set. On the scikit-learn breast cancer dataset, one does exactly that, then scores 91.7% under five-fold cross-validation. Only the second number says anything about the next patient.

2. Three splits, three jobs

The standard protocol divides the data before anything else happens.

SplitUsed forTouched how oftenTypical share
TrainingFitting parametersConstantly60 to 80%
ValidationChoosing between models and settingsMany times10 to 20%
TestReporting the final estimateOnce10 to 20%

The validation set exists because choosing is itself a form of fitting. Try fifty settings and keep the best validation score, and part of that score is luck: you selected the setting that happened to suit those particular validation examples. The test set is the protection against this. It stays locked until every decision is made.

Gotcha: A test set consulted twice is a validation set. If you look at the test score, change something, and look again, the final number is optimistic in exactly the way the test set was meant to prevent. There is no way to un-see it; the only fix is fresh data.

3. Overfitting, in numbers

Here is overfitting measured rather than described. Twenty training points were drawn from a sine curve plus noise with standard deviation 0.3, and polynomials of rising degree were fitted to them, then scored on 1,000 fresh points.

Training and test error as polynomial degree rises
Training RMSETest RMSE
Root mean squared error (RMSE)00.20.40.60.8135912
Source: Computed for this lesson: 20 training and 1,000 test points from sin(2 pi x) plus Gaussian noise (sd 0.3), scikit-learn 1.8, seed 0

Training error falls at every step. Test error falls until degree 3, reaching 0.322, barely above the noise level of 0.3 that no model can beat, then climbs back up. Past that point the extra flexibility is spent memorising the particular noise in twenty points.

4. Push the flexibility further

The same experiment continues to degree 15: a polynomial with 16 coefficients fitted to 20 points.

Predict first

At degree 15 the training RMSE drops again, to 0.165. What do you expect the test RMSE to do?

This is the general shape to remember. Training error is almost always monotone in model flexibility. Held-out error is U-shaped, and its minimum sits wherever the data can support the flexibility, which depends on how much data you have and how noisy it is. Rerun with 2,000 training points and the degree-9 fit scores 0.301 on test data, essentially at the noise floor, because there are now far too many points to memorise.

5. Bias and variance

For squared error, the expected test error at a point decomposes into three parts:

E[(y−f^(x))2]=(E[f^(x)]−f(x))2⏟bias2+Var⁡[f^(x)]⏟variance+σ2⏟noise\mathbb{E}\big[(y - \hat{f}(x))^2\big] = \underbrace{\big(\mathbb{E}[\hat{f}(x)] - f(x)\big)^2}_{\text{bias}^2} + \underbrace{\operatorname{Var}\big[\hat{f}(x)\big]}_{\text{variance}} + \underbrace{\sigma^2}_{\text{noise}}

The expectations run over training sets you might have drawn. Bias is how far the average fitted model sits from the truth: a straight line fitted to a sine is wrong however much data you give it. Variance is how much the fit changes from one training sample to another: the degree-15 polynomial is a different wild curve every time. Noise is the floor.

SymptomTraining errorValidation errorLikely causeTypical fix
UnderfittingHighHigh, close to trainingBiasMore flexible model, better features
OverfittingLowMuch higher than trainingVarianceMore data, regularization, simpler model

6. Regularization: paying for complexity

Instead of restricting the model family, you can keep it flexible and charge for large coefficients. Ridge regression adds a penalty on the squared size of the weights:

min⁡w  ∑i=1n(yi−w⊤xi)2+α∑jwj2\min_{w} \; \sum_{i=1}^{n}\big(y_i - w^\top x_i\big)^2 + \alpha \sum_{j} w_j^2

Lasso uses absolute values, α∑j∣wj∣\alpha \sum_j |w_j|, which pushes some weights to exactly zero and so doubles as feature selection. The strength α\alpha is a hyperparameter: it is not learned by the fit, it is chosen on validation data.

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.linear_model import RidgeCV

model = make_pipeline(
    PolynomialFeatures(degree=15),
    StandardScaler(),
    RidgeCV(alphas=[1e-4, 1e-3, 1e-2, 0.1, 1, 10]),  # picks alpha by internal cross-validation
)
model.fit(X_train, y_train)

The scaler matters: the penalty treats all weights alike, so features must be on comparable scales or the penalty falls unevenly.

7. Cross-validation: every point gets a turn

A single validation split wastes data and gives a noisy estimate, especially on small datasets. k-fold cross-validation splits the data into kk folds, trains kk times, and holds out a different fold each time.

RoundFold 1Fold 2Fold 3Fold 4Fold 5
1ValidateTrainTrainTrainTrain
2TrainValidateTrainTrainTrain
3TrainTrainValidateTrainTrain
4TrainTrainTrainValidateTrain
5TrainTrainTrainTrainValidate

Every example is used for validation exactly once, and you get kk scores instead of one. Report their mean and spread; a model at 0.96 plus or minus 0.02 is not clearly better than one at 0.95.

Gotcha: If you tune hyperparameters with cross-validation and then report that same best score, it is optimistic for the reason given earlier: selection fits the folds. Keep a separate test set, or use nested cross-validation, with an inner loop for tuning and an outer loop for scoring. For time-ordered data, shuffled folds leak the future into the past; that case has its own lesson in the financial machine learning course.

8. Where information may flow

Every step that learns from data, including scaling and feature selection, must learn from the training rows only.

flowchart TD
  A["Full dataset"] --> B["Split first"]
  B --> C["Training rows"]
  B --> D["Held-out rows"]
  C --> E["Fit scaler, selector, model"]
  E --> F["Fitted pipeline"]
  D --> G["Transform and predict only"]
  F --> G
  G --> H["Honest score"]

9. Leakage: a perfect score on pure noise

Data leakage is any path by which information from the evaluation data reaches the fitted model. scikit-learn's own documentation demonstrates it on data that contains no signal at all: 200 examples, 10,000 random features, random labels. Selecting the 25 "best" features on the full dataset, then splitting, produces a model that looks useful.

Test accuracy on random labels
Test accuracy (%)0204060807650Feature selection before splitSelection inside a pipeline
Source: scikit-learn documentation, Common pitfalls and recommended practices: data leakage example (200 samples, 10,000 random features)

The 76% is fiction: the selector had already seen the test labels and chose features that happened to correlate with them. Done correctly, accuracy is 50%, which is chance for two balanced classes. The fix is structural, not a matter of care:

from sklearn.pipeline import make_pipeline
from sklearn.feature_selection import SelectKBest
from sklearn.ensemble import HistGradientBoostingClassifier

pipe = make_pipeline(SelectKBest(k=25), HistGradientBoostingClassifier())
pipe.fit(X_train, y_train)          # selector sees training rows only
print(pipe.score(X_test, y_test))   # about 0.5, the truth

10. Leakage in the wild

Leakage is not a beginner's mistake that experts outgrow. Kapoor and Narayanan's 2023 survey in Patterns collected earlier reviews across scientific fields and found leakage documented in at least 294 papers across 17 disciplines, in some cases producing wildly overoptimistic conclusions.

The common routes:

  • Preprocessing on the full data: scaling, imputation, feature selection or oversampling fitted before the split.
  • Duplicates across the split: the same patient, user or near-identical image in both training and test.
  • Target leakage: a feature that is only known because of the outcome, like "days in hospital" when predicting admission.
  • Temporal leakage: training on rows from after the period you test on, so the model effectively knows the future.

In practice: Suspect leakage whenever a score is surprisingly good. Check which features drive the predictions; a leak usually shows up as one feature that is far too informative. Then split by entity (patient, customer) or by time rather than by row whenever the deployed model will face new entities or future dates.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. Why is the test set supposed to be used only once?
    • It is too small to use repeatedly
    • Every decision made after looking at it fits the test set, making the final score optimistic
    • Scikit-learn deletes it after one use
    • Test data is noisier than training data
  2. In the polynomial experiment, training error kept falling as the degree rose. What did test error do?
    • Fell steadily alongside training error
    • Stayed flat at the noise level
    • Rose steadily from degree 1
    • Fell to a minimum near degree 3, then rose, and exploded at degree 15
  3. A model has low training error and much higher validation error. Which change is most likely to help?
    • Stronger regularization or more training data
    • A more flexible model
    • Removing the validation set
    • Reporting training error instead
  4. In scikit-learn's leakage example on random labels, feature selection before the split gave 76% test accuracy. What was the honest figure?
    • 76%, since selection does not affect the test set
    • 90%
    • 50%, chance level for two balanced classes
    • 0%
  5. You tune hyperparameters with 5-fold cross-validation and get a best mean score of 0.93. Why is reporting 0.93 as the expected performance a problem?
    • Cross-validation always underestimates performance
    • Choosing the best setting fits the folds, so 0.93 is optimistic without a separate test set or nested CV
    • Five folds are too few to compute a mean
    • The score must be reported as training error

Related lessons

AI
advanced

Validation: Measuring Anything at All

Shuffled cross-validation reports 54 percent accuracy on data containing no signal, because neighbouring samples share their futures. This lesson builds purging, embargo and sample uniqueness weights, shows the illusion scaling with label overlap and vanishing when the fix is applied, and covers why a single walk-forward path is weak evidence.

10 steps·~15 min
AI
intermediate

Decision Trees, Random Forests and Gradient Boosting

Tree ensembles remain the default for tabular data. Learn how a decision tree picks its splits, why one deep tree memorises, how random forests average away variance and gradient boosting corrects errors in sequence, and how to read feature importance without being misled.

11 steps·~17 min
AI
beginner

What Machine Learning Does: Learning a Function From Examples

Machine learning replaces hand-written rules with a function fitted to examples. Learn the supervised setup, what a loss function measures, how a linear regression is actually fitted, why a baseline comes first, and when a problem is better solved without machine learning at all.

10 steps·~15 min
AI
advanced

Why Standard Machine Learning Fails on Market Data

Machine learning practice assumes independent samples, a stable data-generating process, and an environment that does not react to you. Financial data violates all three, and the result is models that validate beautifully and lose money. This lesson establishes what is actually broken before the rest of the course fixes it.

10 steps·~15 min