TAI BUI
Back to curriculum
LearnPython

Bias-Variance Tradeoff

Every model error traces back to one of three sources: bias, variance, or noise. You only get to control two of them.

TIME: ~75 minutesPREREQUISITES: Phase 2, Lessons 01-09 (ML basics, regression, classification, evaluation)

Learning Objectives

  • Derive the bias-variance decomposition of expected prediction error and explain the role of irreducible noise
  • Diagnose whether a model suffers from high bias or high variance using training and test error patterns
  • Explain how regularization techniques (L1, L2, dropout, early stopping) trade bias for variance
  • Implement experiments that visualize the bias-variance tradeoff across models of increasing complexity

The Problem

You trained a model. It has some error on the test set. Where did that error come from?

If your model is too simple (linear regression on a curved dataset), it will consistently miss the true pattern. That's bias. If it's too complex (a degree-20 polynomial fit to 15 data points), it will nail the training data and then swing wildly on anything new. That's variance.

You can't push both down at once for a fixed model capacity: push bias down and variance climbs, push variance down and bias climbs. This tradeoff is the most useful diagnostic skill you'll build in machine learning. Once you know which one is hurting you, you know what to do next: make the model more complex or simpler, collect more data or engineer better features, regularize harder or ease off.

Warm-up0/3
1. Why is a model scored on a held-out test set rather than only on its training data?Warm-up
Ten numbered example rows split into seven rows used to fit a model, drawn in blue, and three rows kept aside, drawn with dashed orange outlines. A question mark stands for the error measured on the three kept-aside rows.
Schematic split of 10 rows (7 + 3), not real data.
2. Mean squared error is the average, across examples, of which quantity?Warm-up
A table of four examples with their true value and the model's prediction: 3 and 2, 5 and 5, 2 and 4, 4 and 4. A question mark stands for the mean squared error.
Typed toy numbers.
3. What does 5-fold cross-validation do?Warm-up
Ten numbered rows feed into a box labelled 5-fold cross-validation, which produces a row of five validation scores shown as question marks.
Schematic with 10 example rows.

The Concept

Bias: Systematic Error

Bias measures how far off your model's average prediction lands from the true value. Train the same model on many different training sets drawn from the same distribution, average the predictions, and bias is the gap between that average and the truth.

High bias means the model is too rigid to capture the real pattern. A straight line fit to a parabola will miss the curve no matter how much data you feed it. That's underfitting.

High bias (underfitting):
  Model always predicts roughly the same wrong thing.
  Training error: HIGH
  Test error: HIGH
  Gap between them: SMALL

Variance: Sensitivity to Training Data

Variance measures how much your predictions swing when you train on different subsets of the same data. Small changes to the training set that cause large changes to the fitted model mean variance is high.

High variance means the model is fitting noise instead of signal. A degree-20 polynomial threads through every training point exactly and oscillates wildly in between. That's overfitting.

High variance (overfitting):
  Model fits training data perfectly but fails on new data.
  Training error: LOW
  Test error: HIGH
  Gap between them: LARGE

The Decomposition

For any point x, expected prediction error under squared loss decomposes exactly into three terms:

Expected Error = Bias^2 + Variance + Irreducible Noise

where:
  Bias^2   = (E[f_hat(x)] - f(x))^2
  Variance = E[(f_hat(x) - E[f_hat(x)])^2]
  Noise    = E[(y - f(x))^2]             (sigma^2)
  • f(x) is the true function
  • f_hat(x) is your model's prediction
  • E[...] is the expectation over different training sets
  • y is the observed label (true function plus noise)

The noise term is irreducible: no model beats sigma^2 on noisy data. Your job is finding the right balance between bias^2 and variance.

Model Complexity vs Error

Mermaid diagram

The classic U-shaped curve:

ComplexityBiasVarianceTotal Error
Too lowHIGHLOWHIGH (underfitting)
Just rightMODERATEMODERATELOWEST
Too highLOWHIGHHIGH (overfitting)

Regularization as Bias-Variance Control

Regularization trades variance for bias on purpose: it constrains the model so it can't chase noise.

  • L2 (Ridge): Shrinks all weights toward zero. Keeps all features but reduces their influence.
  • L1 (Lasso): Pushes some weights exactly to zero. Performs feature selection.
  • Dropout: Randomly disables neurons during training. Forces redundant representations.
  • Early stopping: Stops training before the model fully fits the training data.

The regularization strength (lambda, dropout rate, number of epochs) directly controls where you sit on the bias-variance curve. More regularization means more bias, less variance.

Double Descent: The Modern Perspective

Classical theory says complexity past the sweet spot always hurts. Research since 2019 says otherwise: keep increasing model capacity far past the interpolation threshold, the point where the model has just enough parameters to fit the training data exactly, and test error can drop again.

Mermaid diagram

This "double descent" is why massively overparameterized neural networks, with far more parameters than training examples, still generalize. Classical bias-variance theory isn't wrong here, it's just incomplete once you're past the interpolation threshold.

Key observations about double descent:

  • It shows up in linear models, decision trees, and neural networks alike
  • More data can hurt in the interpolation region (sample-wise double descent)
  • More training epochs can trigger it too (epoch-wise double descent)
  • Regularization softens the peak but doesn't remove it

Why does this happen? At the interpolation threshold, the model has exactly enough capacity to fit every training point, so it gets forced into one very specific solution. Small perturbations in the data swing that solution wildly, which is why variance peaks right there. Past the threshold, many different solutions fit the data perfectly, and the learning algorithm (gradient descent with its implicit regularization, for instance) tends to land on the simplest one. That implicit bias toward simple solutions is the actual reason overparameterized models generalize.

RegimeParameters vs SamplesBehavior
Underparameterizedp << nClassical tradeoff applies
Interpolation thresholdp ~ nVariance peaks, test error spikes
Overparameterizedp >> nImplicit regularization kicks in, test error drops

Practical takeaway: if you're running neural networks or large tree ensembles, don't park at the interpolation threshold. Stay well below it with explicit regularization, or push well past it. The worst place to sit is right at the threshold.

Diagnosing Your Model

Mermaid diagram

SymptomDiagnosisFix
High train error, high test errorBiasMore features, complex model, less regularization
Low train error, high test errorVarianceMore data, regularization, simpler model, dropout
Low train error, low test errorGood fitShip it
Train error decreasing, test error increasingOverfitting in progressEarly stopping

Practical Strategies

When bias is the problem:

  • Add polynomial or interaction features
  • Use a more flexible model (tree ensemble instead of linear)
  • Reduce regularization strength
  • Train longer (if not yet converged)

When variance is the problem:

  • Get more training data
  • Use bagging (random forests)
  • Increase regularization (higher lambda, more dropout)
  • Feature selection (remove noisy features)
  • Use cross-validation to detect it early

Ensemble Methods and Variance Reduction

Ensemble methods are the most practical tool you have for fighting variance.

Bagging (Bootstrap Aggregating) draws many bootstrap samples (random resamples of the training data, drawn with replacement so the same row can appear more than once), trains one model per sample, then averages their predictions. Each individual model still has high variance, but averaging brings that variance down sharply. Random forests are bagging applied to decision trees.

Why it works mathematically: average N independent predictions, each with variance sigma^2, and the variance of the average drops to sigma^2 / N. The models aren't truly independent since they all see similar data, so the reduction falls short of 1/N. Still, it's substantial.

Boosting reduces bias by building models sequentially: each new model targets the errors the ensemble has made so far. Gradient boosting and AdaBoost are the main examples. Add too many models and boosting overfits, so you need early stopping or regularization to rein it in.

MethodPrimary EffectBias ChangeVariance Change
BaggingReduces varianceNo changeDecreases
BoostingReduces biasDecreasesCan increase
StackingReduces bothDepends on meta-learnerDepends on base models
DropoutImplicit baggingSlight increaseDecreases

Practical rule: if your base model has high variance (deep trees, high-degree polynomials), use bagging. If it has high bias (shallow stumps, simple linear models), use boosting.

Learning Curves

Learning curves plot training and validation error against training set size. They're the most practical diagnostic tool you have: unlike a single train/test comparison, they show you the model's trajectory and tell you whether more data will actually help.

Mermaid diagram

How to read them:

ScenarioTraining ErrorValidation ErrorGapWhat It MeansWhat to Do
High biasHighHighSmallModel cannot capture the patternMore features, complex model, less regularization
High varianceLowHighLargeModel memorizes training dataMore data, regularization, simpler model
Good fitModerateModerateSmallModel generalizes wellShip it
High variance, improvingLowDecreasing with more dataShrinkingVariance problem that data can fixCollect more data
High bias, flatHighHigh and flatSmall and flatMore data will NOT helpChange model architecture

The critical read: if both curves have flattened out with a small gap but both errors are still high, more data won't help. You need a better model. If the gap is large and still shrinking, more data will.

How to Generate Learning Curves

There are two approaches.

Approach 1: vary training set size, fixed model. Hold the model and hyperparameters constant, train on increasingly large subsets of the data, and measure training and validation error at each size. This is the standard learning curve.

Approach 2: vary model complexity, fixed data. Hold the data constant, sweep a complexity parameter (polynomial degree, tree depth, number of layers), and measure training and validation error at each setting. This is a validation curve, and it shows the bias-variance tradeoff directly.

The two complement each other: the first tells you if more data will help, the second tells you if a different model will help. Run both before deciding your next move.

Mermaid diagram

Check: The Concept0/31
1. A linear model is fit to a clearly curved (quadratic) relationship. Which error component dominates?Define
Scatter plot of 40 points that follow a U-shaped curve, with a note that the model to fit is a straight line y = w0 + w1 x.
Quadratic data y = 0.5 x^2 - 1 plus Gaussian noise (std 0.5), generated for this picture.
2. Which term of the decomposition comes from randomness in the data itself, so that no model can reduce it?Define
A horizontal bar split into three segments labelled term A 0.0529, term B 0.0397 and term C 0.2500, adding up to 0.3426.
Values from the lesson's own run: polynomial degree 3, 30 training samples, 200 training sets.
3. What does variance measure in the bias-variance decomposition?Define
Three small scatter plots of 15 training points each, drawn from the same source, with a dashed vertical line marking a test input x0 in each. A question mark stands for the variance of the model's prediction at x0.
Generated data, 15 points per set (f(x) + noise, std 0.5).
4. What is underfitting?Define
Scatter plot of 30 training points that follow a gently wavy rising trend, with the note that a model is fit to these points.
Data from generate_data(30, seed=42) in the lesson code.
5. What is overfitting?Define
Scatter plot with 30 filled blue training points and 30 hollow orange points of new data, all following the same gently wavy rising trend.
Training data from generate_data(30, seed=42); new points are the first 30 of generate_data(100, seed=99).
6. What is regularization?Define
Thirty scatter points with an orange degree 10 polynomial that wiggles between them, and the size of its largest weight printed.
Fit with the lesson's fit_polynomial on generate_data(30, seed=42), lam = 0.
7. As model capacity grows far past the interpolation threshold, what can happen to test error?Define
A log-log plot of test error against the number of parameters for 30 training samples. The curve is drawn up to a dashed vertical line at p = n and ends in a sharp rise. To the right of the line the plot area is blank apart from a question mark.
Numpy experiment: minimum-norm least squares on p random projections of a 300-input synthetic problem, mean over 300 training sets.
8. What does model complexity mean in this lesson?Define
A table of three polynomial models: A with 2 weights, B with 5 weights and C with 16 weights, each written as a formula. A question mark stands for the complexity of each.
Typed table; weight count is degree + 1.
9. Under squared loss, how does expected prediction error at a point break down?Explain
A number line around the true value f(x0) with six filled blue prediction dots from different training sets and six hollow orange dots for fresh observed labels. A question mark stands for the expected squared error.
Degree 3 polynomial fits from the lesson's repeated-training-set loop; label draws use noise std 0.5. Values illustrative of one test point.
10. Why can a larger model never push expected error below sigma squared on noisy data?Explain
Scatter plot of 40 points scattered around a dashed true curve, labelled y = f(x) + noise, with the statement that the lowest possible test error is a question mark.
Generated with the lesson's generate_data (noise std 0.5).
11. Adding L2 regularization to a model increases bias and decreases variance. Why is this useful?Explain
A table for a degree 10 polynomial with two rows. With lam equal to 0 bias squared is 0.0156 and variance 2.3985; with lam equal to 1 bias squared is 0.0308 and variance 0.6095. A question mark stands for the total error after the penalty.
Values from the lesson's own demo_regularization_effect run.
12. How do L1 and L2 regularization differ in their effect on weights?Explain
Bar chart of eight fitted weights with no penalty, next to two dashed empty panels titled fit with an L1 penalty and fit with an L2 penalty, each holding a question mark.
Numpy fit on synthetic data: 40 rows, 8 features, 3 of them informative; unpenalized weights drawn.
13. How does early stopping act as regularization?Explain
Three panels showing the same 16 points and the fitted curve after 3, 30 and 20000 epochs of gradient descent. The curve starts rough, becomes a smooth fit and ends as a wiggly curve. Train MSE is printed under each.
Numpy gradient descent, 15 Legendre polynomial features, full-batch.
14. Why does variance peak at the interpolation threshold?Explain
A log-log plot of prediction variance against the number of parameters, with a dashed vertical line at p = n. Variance climbs steeply, peaks at the line and falls afterwards.
Numpy experiment: minimum-norm least squares on p random projections of a 300-input synthetic problem, 300 training sets.
15. Why can massively overparameterized networks still generalize?Explain
A four-row table: 30 training samples, 300 parameters, training MSE 0.0000, and the test MSE. A line asks why such a model generalizes.
Numpy experiment: minimum-norm least squares on 300 random projections of a 300-input synthetic problem.
16. Averaging N independent predictions with variance sigma squared gives variance sigma squared / N. Why does bagging fall short of that?Explain
A log-log plot of the variance of an averaged prediction against the number of models N from 1 to 50. A dashed line shows sigma squared over N and a solid orange measured curve falls more slowly and ends above it.
Numpy run: 150 training sets of 30 points, each model fitted on a bootstrap resample; variance averaged over 100 test inputs.
17. What is the primary effect of bagging versus boosting on bias and variance?Explain
Two panels side by side. The bagging panel says each model is trained on a bootstrap sample and the results are averaged; the boosting panel says each model is trained on what the models so far get wrong. Each panel has two question marks for its effect on bias and on variance.
Schematic.
18. How do the two ways of generating diagnostic curves differ?Explain
Two plots titled Approach 1 and Approach 2, each with a blue training error curve and an orange validation error curve. The horizontal axis of each is labelled with a question mark and has no tick values; the vertical axes have no tick values either.
Real numpy runs; axis values hidden. Approach 2 uses a log scale on the vertical axis.
19. A model has training error = 2% and test error = 25%. What is the most likely diagnosis?Apply
Two vertical bars: training error 2 percent in blue, a short bar, and test error 25 percent in orange, a tall bar. A question mark stands for the diagnosis.
Typed numbers from the question.
20. A model's training error keeps decreasing while its validation error starts increasing partway through training. What does this indicate, and what is the fix?Analyze
A plot of error against epoch on a log axis. The blue training error keeps decreasing. The orange validation error drops, flattens and then climbs off the top of the plot.
Numpy gradient descent: 15 Legendre polynomial features, 16 training points, 300 validation points; curves clipped at the top.
21. Training error is low, and validation error is high but shrinking as the training set grows. What is the situation and the action?Analyze
A plot of training and validation MSE against training set size from 20 to 300 for a degree 9 polynomial. Training error stays low; validation error starts above the plot's top and falls toward it.
Numpy runs, median of 40 training sets; validation labels are noisy; validation values above 2.5 are clipped.
22. Both learning curves have flattened with a small gap, and both errors are still high. A teammate wants ten times more data. What is wrong with that plan?Analyze
A plot of training and validation MSE against training set size from 10 to 300 for a degree 1 model; both curves are flat and close together. Beyond 300 the plot is blank with the label 10x data followed by a question mark.
Numpy runs, median of 40 training sets; validation labels carry the noise.
23. A boosted ensemble's training error keeps falling while validation error rises after hundreds of models are added. What explains it?Analyze
A plot of training and validation MSE against the number of boosted models on a log axis up to 500. Training error keeps falling; validation error falls, then rises again.
Numpy gradient boosting of decision stumps, learning rate 0.5, 40 training and 600 validation points.
24. A team grows its network until parameters roughly equal training samples, sees test error spike, and concludes that bigger models always generalize worse. What did they miss?Analyze
A table of four models trained on 30 samples: p = 15, 24, 28 and 30 parameters with test errors that rise with p, ending in a very large value at p = 30.
Numpy experiment on a synthetic problem (random projections of 300 inputs, minimum-norm fit, mean over 300 training sets).
25. A model near the interpolation region gets worse on the test set after more training data is added. Which explanation fits?Analyze
A two-row table for a model with 30 parameters: with 18 training samples the test error is 1.94 and with 28 samples it is 14.13.
Numpy experiment on a synthetic problem, mean over 300 training sets.
26. A team bags 50 copies of a straight-line model on a curved dataset and sees little improvement. Why?Analyze
A two-row table of error against the true curve: one line 0.466 and the average of 50 bootstrap lines 0.461.
Numpy experiment on the lesson's generator (degree 1 polynomials); the sum of bias squared and variance is shown.
27. A network shows high training error and high test error. A teammate adds more dropout and a larger L2 penalty. Why does this likely backfire?Analyze
Two equally tall bars labelled training error and test error, both marked high, next to a note that a teammate wants more dropout and a larger L2 penalty.
Schematic: bar heights are typed, not measured.
28. Your base model is a set of shallow decision stumps with high train and test error. Which ensemble fits?Design
Scatter plot of 60 points with an orange one-step function: a decision stump that predicts one value left of x = 0.17 and another right of it. Train and test MSE are printed.
Numpy stump on the lesson's generator; test MSE on 1000 fresh noisy points.
29. Your linear model has hundreds of features and you suspect most are noise. You want the regularizer itself to drop the useless ones. Which fits?Design
Bar chart of thirty weights from a linear model fitted without a penalty. Most bars are short and a few are tall.
Numpy fit on synthetic data: 60 rows, 30 features (a scaled-down stand-in for hundreds), 3 informative.
30. Your neural net has about as many parameters as training samples and test error is spiking. Which plan matches the lesson?Design
A horizontal capacity scale from fewer to many more parameters with a marker at the point where parameters roughly equal training samples, labelled as where the network sits. A question mark sits below the scale.
Schematic.
31. You must decide whether to collect more data or change the model, and training and validation errors are both high. What should you run?Design
Two equally tall bars labelled training error and validation error, both marked high, and two boxes, collect more data and change the model, each asking will it help with a question mark.
Schematic: bar heights are typed, not measured.

Build It

code/bias_variance.py runs the full bias-variance decomposition experiment end to end. Here's the approach, step by step.

Step 1: Generate Synthetic Data from a Known Function

We use f(x) = sin(1.5x) + 0.5x with Gaussian noise on top. Knowing the true function up front is what lets us compute exact bias and variance instead of estimating them.

python
def true_function(x):
    return np.sin(1.5 * x) + 0.5 * x
 
def generate_data(n_samples=30, noise_std=0.5, x_range=(-3, 3), seed=None):
    rng = np.random.RandomState(seed)
    x = rng.uniform(x_range[0], x_range[1], n_samples)
    y = true_function(x) + rng.normal(0, noise_std, n_samples)
    return x, y

Step 2: Bootstrap Sampling and Polynomial Fitting

For each polynomial degree, we draw many bootstrap training sets, fit the polynomial, and record predictions on a fixed test grid. This gives us a distribution of predictions at each test point.

python
def fit_polynomial(x_train, y_train, degree, lam=0.0):
    X = np.column_stack([x_train ** d for d in range(degree + 1)])
    if lam > 0:
        penalty = lam * np.eye(X.shape[1])
        penalty[0, 0] = 0
        w = np.linalg.solve(X.T @ X + penalty, X.T @ y_train)
    else:
        w = np.linalg.lstsq(X, y_train, rcond=None)[0]
    return w

We fit this way across 200 different bootstrap samples, each drawn from the same underlying distribution but landing on different points.

Step 3: Computing Bias^2, Variance Decomposition

With 200 sets of predictions at each test point, we can compute the decomposition directly from the definition:

python
mean_pred = predictions.mean(axis=0)
bias_sq = np.mean((mean_pred - y_true) ** 2)
variance = np.mean(predictions.var(axis=0))
total_error = np.mean(np.mean((predictions - y_true) ** 2, axis=1))
  • mean_pred is E[f_hat(x)] estimated from bootstrap samples
  • bias_sq is the squared gap between average prediction and truth
  • variance is the average spread of predictions across bootstrap samples
  • total_error should approximately equal bias^2 + variance + noise

Step 4: Learning Curves

Learning curves sweep training set size while holding model complexity fixed. They show whether your model is data-limited or capacity-limited.

python
def demo_learning_curves():
    sizes = [10, 15, 20, 30, 50, 75, 100, 150, 200, 300]
    degree = 5
 
    for n in sizes:
        train_errors = []
        test_errors = []
        for seed in range(50):
            x_train, y_train = generate_data(n_samples=n, seed=seed * 100)
            w = fit_polynomial(x_train, y_train, degree)
            train_pred = predict_polynomial(x_train, w)
            train_mse = np.mean((train_pred - y_train) ** 2)
            test_pred = predict_polynomial(x_test, w)
            test_mse = np.mean((test_pred - y_test) ** 2)
            train_errors.append(train_mse)
            test_errors.append(test_mse)
        # Average over runs gives the learning curve point

For a high-variance model (degree 5 with small data), you see:

  • Training error starts low and increases as more data makes memorization harder
  • Test error starts high and decreases as the model gets more signal
  • The gap shrinks with more data

For a high-bias model (degree 1), both errors converge quickly to the same high value and more data does not help.

Step 5: Regularization Sweep

The code also includes demo_regularization_sweep(), which fixes a high-degree polynomial (degree 15) and sweeps Ridge strength from 0.001 to 100. It shows the same tradeoff from a different angle: instead of varying model complexity, we vary how hard the constraint bites.

python
def demo_regularization_sweep():
    alphas = [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 50.0, 100.0]
    for alpha in alphas:
        results = bias_variance_decomposition([15], lam=alpha)
        r = results[15]
        print(f"alpha={alpha:.3f}  bias={r['bias_sq']:.4f}  var={r['variance']:.4f}")

At low alpha, the degree-15 polynomial is almost unconstrained and variance dominates: the model chases noise in every bootstrap sample. At high alpha, the penalty is so strong the model collapses to a near-constant function and bias takes over. The optimal alpha sits somewhere between the two extremes.

It's the same U-curve you get from varying polynomial degree, just controlled by a continuous knob instead of a discrete one. In practice, regularization is the preferred lever because it gives you fine-grained control without touching the feature set.

Check: Build It0/6
1. Why is regularization strength often a better lever than changing the polynomial degree?Explain
A plot of 5-fold validation MSE for polynomial degrees 1 to 15, drawn as orange points joined by lines: high at degrees 1 and 2, lowest around degree 3, then slowly rising.
Numpy 5-fold cross-validation with a ridge penalty of 0.01 and inputs divided by 3; not scikit-learn.
2. In the Build It code, how is variance computed from the 200 bootstrap prediction sets?Apply
A code box with two lines from the lesson that create and fill the predictions array with 200 rows for bootstrap samples and 100 columns for test points, above a grid of cells drawn to match. A question mark stands for the variance.
Lines copied from the lesson's bias_variance.py; grid is schematic.
3. With mean_pred = [1.0, 2.0] over two test points and y_true = [1.5, 2.0], what does np.mean((mean_pred - y_true) ** 2) return?Apply
A plot with two test points. At point 1 a filled blue dot at 1.0 and a hollow orange dot at 1.5; at point 2 a filled blue dot and a hollow orange dot both at 2.0. The code expression is written to the right with a question mark.
Values from the question.
4. In fit_polynomial with lam > 0, what does penalty[0, 0] = 0 do?Apply
A 4 by 4 matrix with lam on the diagonal and zeros elsewhere, columns labelled x^0 to x^3, with the top-left cell outlined and annotated penalty[0, 0] equals a question mark.
Schematic of lam * np.eye(4) from the lesson's fit_polynomial.
5. In demo_learning_curves with degree 5, how do the average training and test MSE move as n grows from 10 to 300?Apply
Empty log-log axes for train and test MSE against training set size from 10 to 300, with a legend for a blue train curve and an orange test curve. No curves are drawn.
Axes only; the sizes are those in the lesson's demo_learning_curves.
6. In demo_regularization_sweep with a degree-15 polynomial, what do you expect at alpha = 100 compared with alpha = 0.001?Apply
A log-scale strip of the eleven alpha values from 0.001 to 100, with 0.001 and 100 highlighted, above a table with question marks for bias squared, variance and the dominant term at those two settings.
The sweep values are those in the lesson's demo_regularization_sweep.

Use It

sklearn's learning_curve and validation_curve automate these diagnostics so you don't have to hand-roll the bootstrap loops yourself.

Validation Curve: Sweep Model Complexity

python
from sklearn.model_selection import validation_curve
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import Ridge
 
degrees = list(range(1, 16))
train_scores_all = []
val_scores_all = []
 
for d in degrees:
    pipe = make_pipeline(PolynomialFeatures(d), Ridge(alpha=0.01))
    train_scores, val_scores = validation_curve(
        pipe, X, y, param_name="polynomialfeatures__degree",
        param_range=[d], cv=5, scoring="neg_mean_squared_error"
    )
    train_scores_all.append(-train_scores.mean())
    val_scores_all.append(-val_scores.mean())

This traces the bias-variance tradeoff curve directly: wherever the validation score lags train score badly, variance dominates, and wherever both are bad, bias does.

Learning Curve: Sweep Training Set Size

python
from sklearn.model_selection import learning_curve
 
pipe = make_pipeline(PolynomialFeatures(5), Ridge(alpha=0.01))
train_sizes, train_scores, val_scores = learning_curve(
    pipe, X, y, train_sizes=np.linspace(0.1, 1.0, 10),
    cv=5, scoring="neg_mean_squared_error"
)
train_mse = -train_scores.mean(axis=1)
val_mse = -val_scores.mean(axis=1)

Plot train_mse and val_mse against train_sizes. The shape tells you everything about your model.

Cross-Validation with Regularization Sweep

python
from sklearn.model_selection import cross_val_score
 
alphas = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]
for alpha in alphas:
    pipe = make_pipeline(PolynomialFeatures(10), Ridge(alpha=alpha))
    scores = cross_val_score(pipe, X, y, cv=5, scoring="neg_mean_squared_error")
    print(f"alpha={alpha:>7.3f}  MSE={-scores.mean():.4f} +/- {scores.std():.4f}")

This sweeps regularization strength for a fixed model complexity. You will see the same bias-variance tradeoff: low alpha means high variance, high alpha means high bias.

Putting It All Together: A Complete Diagnostic Workflow

In practice, you run these diagnostics in sequence:

  1. Train your model. Compute train and test error.
  2. If both are high: you have a bias problem. Skip to step 4.
  3. If train is low but test is high: you have a variance problem. Generate a learning curve to see if more data will help. If not, regularize.
  4. Generate a validation curve sweeping your main complexity parameter. Find the sweet spot.
  5. At the sweet spot, generate a learning curve. If the gap is still large, you need more data or regularization.
  6. Try Ridge/Lasso with different alpha values using cross_val_score. Pick the alpha where cross-validated error is lowest.

This takes 10-15 minutes of compute for most tabular datasets and saves hours of guessing.

Check: Use It0/2
1. In the validation-curve loop, validation MSE is far above train MSE at degree 14. What does that point to?Apply
Two bars at polynomial degree 14: a short training MSE of 0.24 and a much taller validation MSE of 9.44.
Numpy 5-fold cross-validation with a ridge penalty of 0.01, not scikit-learn.
2. In the cross_val_score loop over alphas, which alpha should you pick?Apply
A table listing the six alphas from the lesson's loop, 0.001 to 100, each with question marks for cross-validated MSE and training MSE, under the cross_val_score line.
Alpha values and code line are from the lesson.

Ship It

This lesson produces: outputs/prompt-model-diagnostics.md

Author's Note

The double descent section is the one people file away as trivia and then get burned by later. If you're fitting a small linear model, the classical U-curve is the whole story and you can stop there. But the moment you're staring at a neural network with more parameters than training examples that's still generalizing fine, the classical story alone will make you second-guess a model that's actually working. Know which regime you're in before you start regularizing on instinct.

The other thing worth saying directly: bias and variance aren't properties of a model. They're properties of a model plus a dataset plus a training procedure. Change any one of those and a high-bias problem can turn into a high-variance one. Rerun the diagnosis every time something upstream changes. Don't coast on last month's conclusion.

Exercises

  1. Run the decomposition with noise_std=0 (no noise). What happens to the irreducible error term? Does the optimal complexity change?

  2. Increase the training set size from 30 to 300. How does this affect the variance component? Does the optimal polynomial degree shift?

  3. Add L2 regularization (Ridge regression) to the experiment. For a fixed high-degree polynomial (degree 15), sweep lambda from 0 to 100. Plot bias^2 and variance as functions of lambda.

  4. Modify the true function from a polynomial to sin(x). How does the bias-variance decomposition change? Is there still a clear optimal degree?

  5. Implement a simple bootstrap aggregating (bagging) wrapper: train 10 models on bootstrap samples and average predictions. Show that this reduces variance without increasing bias much.

Key Terms

TermWhat people sayWhat it actually means
Bias"The model is too simple"Systematic error from wrong assumptions. The gap between the average model prediction and truth.
Variance"The model is overfitting"Error from sensitivity to training data. How much predictions change across different training sets.
Irreducible error"Noise in the data"Error from randomness in the true data-generating process. No model can eliminate it.
Underfitting"Not learning enough"Model has high bias. It misses the real pattern even on training data.
Overfitting"Memorizing the data"Model has high variance. It fits noise in training data that does not generalize.
Regularization"Constraining the model"Adding a penalty to reduce model complexity, trading bias for lower variance.
Double descent"More parameters can help"Test error decreases again when model capacity far exceeds the interpolation threshold.
Model complexity"How flexible the model is"The capacity of a model to fit arbitrary patterns. Controlled by architecture, features, or regularization.

Further Reading

Code

Ships With