When a model is wrong, why is it wrong — and what to do in each case
Each training set fits a polynomial and predicts at \(x = 0.25\), where the truth is 1. Bias \(= \overline{\hat f} - f(0.25)\); variance \(= \tfrac{1}{k}\sum_i (\hat f_i - \overline{\hat f})^2\). Predict. Which degree is right on average, and which one spreads more?
Truth: \(\sin(2\pi x)\). Each curve is a polynomial fitted to a different 30-point training set.
At a fixed \(x\): the truth \(f(x)\); a new observation \(y = f(x) + \varepsilon\), noise \(\varepsilon\) with mean 0 and variance \(\sigma^2\); the prediction \(\hat f(x)\), random because it depends on the training set; \(\mathbb{E}\): the average over training sets and noise.
\[ \mathbb{E}\big[(y - \hat f(x))^2\big] = \underbrace{\big(f(x) - \mathbb{E}[\hat f(x)]\big)^2}_{\text{bias}^2} + \underbrace{\mathbb{E}\big[(\hat f(x) - \mathbb{E}[\hat f(x)])^2\big]}_{\text{variance}} + \underbrace{\sigma^2}_{\text{noise}} \]Bias: the family's best attempt is wrong on average (a line cannot follow a sine). Variance: the price of listening to the sample. Noise: the part of \(y\) that does not depend on \(x\); here \(\sigma^2 = 0.3^2 = 0.09\), and nobody goes below it.
Predict. 500 training sets of 30 points per degree. At which degree is the test mean squared error (MSE) lowest? And what happens to the variance at degree 12?
| degree | bias² | variance | noise | sum | measured test MSE |
|---|---|---|---|---|---|
| 0 | 0.495 | 0.020 | 0.09 | 0.605 | 0.603 |
| 1 | 0.204 | 0.022 | 0.09 | 0.316 | 0.314 |
| 3 | 0.005 | 0.018 | 0.09 | 0.113 | 0.112 |
| 5 | 0.000 | 0.045 | 0.09 | 0.135 | 0.135 |
| 7 | 0.001 | 0.635 | 0.09 | 0.726 | 0.723 |
| 12 | 0.001 | 38.897 | 0.09 | 38.987 | 38.985 |
Predict. Slide the degree from 0 (pure bias) to 12 (pure variance). Which error only falls, and which one turns back up?
Predict. More and more training points: does the error of degree 1 keep falling? And that of degree 9?
What sets them apart is what is varied and what stays fixed.
| what is varied | what stays fixed | needs the truth? | |
|---|---|---|---|
| bias–variance decomposition | the training set (500 samples) | the model | yes |
| validation curve | the complexity | the data | no |
| learning curve | the number of training rows | the model | no |
| grid search | combinations of hyperparameters | the data and the cv | no |
A knob is the hyperparameter that moves the model along the complexity axis of the U: to the left, more bias (underfitting); to the right, more variance (overfitting). High bias asks for a turn to the right; high variance, to the left. Predict. To make each model more complex, which way do you turn each knob?
| family | knob | more complex (→ variance) | simpler (→ bias) |
|---|---|---|---|
| polynomial | degree | larger | smaller |
| Ridge, Lasso | alpha (penalty strength) | smaller | larger |
| logistic regression | C (inverse of the penalty) | larger | smaller |
| k-NN | n_neighbors (\(k\), neighbors that vote) | smaller | larger |
| tree | max_depth | larger | smaller |
| tree | min_samples_leaf (minimum rows per leaf) | smaller | larger |
alpha, n_neighbors and min_samples_leaf, larger is simpler: more penalty, more neighbors in the average, bigger leaves.GridSearchCV: the validation curve that chooses by itself
from sklearn.model_selection import GridSearchCV, RepeatedKFold
# 1. the model, with the knob still loose
model = make_pipeline(PolynomialFeatures(), StandardScaler(),
LinearRegression())
# 2. the knob values to try
# (step name + __ + hyperparameter)
grid = {"polynomialfeatures__degree": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
# 3. how to measure each value: 5 folds × 20 repeats (slide 10's cv)
cv = RepeatedKFold(n_splits=5, n_repeats=20, random_state=0)
search = GridSearchCV(model, grid, cv=cv,
scoring="neg_mean_squared_error")
# 4. measure the 10 degrees, pick the lowest error
# and refit the winner on the 30 rows
search.fit(X, y)
search.best_params_ # {'polynomialfeatures__degree': 3}
What the search measured (search.cv_results_):
| degree | validation MSE |
|---|---|
| 1 | 0.319 |
| 2 | 0.386 |
| 3 | 0.114 |
| 4 | 0.311 |
| 5 | 0.198 |
| 6 | 0.255 |
| 7 | 0.579 |
| 8 | 0.424 |
| 9 | 1.748 |
| 10 | 1.222 |
search.predict then uses degree 3. The MSE goes in negative (neg_mean_squared_error) because scikit-learn always maximizes.On the training and validation error curves (here, low is good):
| what you see | diagnosis | action |
|---|---|---|
| training ≈ validation, both high, flat curves | bias | change the model (more capacity) |
| training low, validation high, gap closing | variance | more data |
| training low, validation high, gap stuck | variance | regularize or simplify |
| training high and a large gap | both | capacity first, then look again |
| both low, together | ok | stop (it may be the noise floor) |
"High" is relative: without knowing \(\sigma^2\) (the noise variance), compare with a baseline (predicting the mean, a simple model) or with the error the business can accept.
Pace: steps 1 to 3 and the first simulation in 15 min; steps 4 to 6 and the second in 25 min.