Concept units

Overfitting: when a model fits the noise

Intermediate

Read these first if they are new to you

The idea in one paragraph

A model with many adjustable weights can fit its training examples almost exactly, noise included. That is overfitting: the training loss is low, but the loss on new examples is high. Regularization is any change to training that aims to lower the loss on new examples, not on the training ones. A common kind adds a penalty to the loss that grows with the squares of the weights. In many models, the curve on this page included, a fit that swings wildly needs large weights, so the penalty steers training toward calmer fits. Choose the penalty's strength by the validation loss: too weak and the model still overfits, too strong and it misses the pattern.

A flexible model can fit the noise along with the pattern

Take 12 training points, evenly spaced from x = −1 to x = 1. Each y is a smooth sine wave, sin(2.5x), plus random noise with a standard deviation of 0.25. Another 40 points from the same wave, at random x and with their own noise, form the validation set.

The model is a curve with 12 weights:

y = w0 + w1x + w2x2 + … + w11x11

With 12 weights and 12 points at different x, one choice of weights makes the curve pass through every training point exactly. Its training loss, the mean squared error (MSE) on those points, is 0. But its validation loss is 6.36. The wave itself scores 0.070 on the validation points, close to 0.0625, which is 0.252: the noise alone.

Fitting the noise of the training examples, so that the model does worse on new ones, is called overfitting. The opposite failure is underfitting: a model too stiff to follow the pattern, so that both losses stay high. A sign of overfitting is a low training loss with a validation loss that is much higher, and higher than a calmer model gives.

The exact fit uses huge weights that nearly cancel: w9 is about −2,333 and w7 about 1,822. At the training points, the terms cancel to give each y. Between the points they do not, and the curve swings far from the wave.

A penalty on the squared weights makes large weights cost loss

To regularize the fit, train on a total that adds a penalty to the training MSE:

total = MSE + (λ/2) × (w12 + w22 + … + w112)

The number λ (lambda) is the regularization strength, zero or more. You choose it; training does not. At λ = 0 there is no penalty. The larger λ is, the more loss each large weight costs, so training accepts a less exact fit to keep the weights small. This penalty is called L2 regularization, or ridge regression in statistics. The ½ only makes the step formula below tidier.

The penalty leaves out w0. That weight moves the whole curve up or down, which cannot make it swing. A penalty on it would only pull the curve toward y = 0. Leaving out such a constant term, called a bias in a network, is the common practice.

Predict first. The slider starts at λ = 0, the exact fit. As you raise λ, will the training loss rise or fall? Then find the λ with the lowest validation loss, and keep going to see what a very strong penalty does.

One curve, fitted with a stronger and stronger penalty
training points and training loss validation points and validation loss

Losses at this strength.

What to notice. At λ = 0 the curve passes through every solid blue dot and swings off the chart between them. As λ grows, the training loss rises, while the validation loss falls to a low point and then rises. At the largest strengths the curve flattens and misses the wave. The lower panel marks the losses only at the strengths you have tried. Each labelled tick on the λ axis is 100 times the one before. The column for λ = 0 sits apart at the left; its validation loss, 6.36, is off the chart.

This code computes the figure's fits for a few strengths. Setting every slope of the total to zero gives 12 linear equations in the 12 weights, and np.linalg.solve solves them. So it finds the lowest total directly, without gradient-descent steps. In the code, X_tr @ w multiplies a matrix by a vector, as in Multiplying a matrix by a vector. X_tr.T is X_tr with its rows and columns swapped, and @ also multiplies two matrices.

ridge_fit.py

import numpy as np
rng = np.random.default_rng(4)
x_tr = np.linspace(-1, 1, 12)                  # 12 training inputs, evenly spaced
y_tr = np.sin(2.5 * x_tr) + 0.25 * rng.normal(size=12)
x_va = rng.uniform(-1, 1, 40)                  # 40 random validation inputs from -1 to 1
y_va = np.sin(2.5 * x_va) + 0.25 * rng.normal(size=40)

X_tr = np.vander(x_tr, 12, increasing=True)    # row i holds 1, x, x**2, ..., x**11
X_va = np.vander(x_va, 12, increasing=True)
P = np.eye(12)                                 # 12 × 12: 1 on the diagonal, 0 elsewhere
P[0, 0] = 0                                    # the penalty leaves out w0

print("lambda    train    valid  sum of squares")
for lam in [0, 1e-6, 1e-4, 1e-3, 1e-2, 1e-1, 1, 10]:
    # The weights with the lowest total: training MSE + (lam / 2) * (w1**2 + ... + w11**2).
    w = np.linalg.solve(X_tr.T @ X_tr + 6 * lam * P, X_tr.T @ y_tr)
    train = np.mean((X_tr @ w - y_tr) ** 2)
    valid = np.mean((X_va @ w - y_va) ** 2)
    # The g in :6g and :14.4g picks plain or e notation by the value's size.
    # .4g rounds to 4 significant digits.
    print(f"{lam:6g}  {train:7.4f}  {valid:7.4f}  {np.sum(w[1:] ** 2):14.4g}")
lambda    train    valid  sum of squares
     0   0.0000   6.3556       1.013e+07
 1e-06   0.0102   0.1214            3248
0.0001   0.0221   0.0845           86.14
 0.001   0.0321   0.0802            10.5
  0.01   0.0424   0.0895           3.076
   0.1   0.0748   0.1336           1.146
     1   0.2218   0.3023           0.203
    10   0.4727   0.5454         0.01138

The last column is w12 + … + w112, and 1.013e+07 means 1.013 × 107. The 6 in the code is 12 points divided by 2, from setting the slopes to zero.

Worked example: the penalty changes which fit wins

Score two fits from the table by the total at λ = 0.001, so λ/2 = 0.0005.

  1. The exact fit (the row for λ = 0): MSE 0, sum of squares 10,130,000. Penalty = 0.0005 × 10,130,000 = 5,065. Total = 0 + 5,065 = 5,065.
  2. The fit from the row for λ = 0.001: MSE 0.0321, sum of squares 10.5. Penalty = 0.0005 × 10.5 = 0.00525. Total = 0.0321 + 0.00525 ≈ 0.037.
  3. The second fit has the higher training loss but by far the lower total. So training on the total picks the calmer fit.
  4. To choose λ, read the validation column. Of the rows printed, the lowest validation loss is 0.0802, at λ = 0.001. So keep that fit. The rows from 0.0001 to 0.01 are all within 0.01 of it, so the exact choice in that range matters little here.

Your turn. The row for λ = 0.1 has MSE 0.0748 and sum of squares 1.146. What is its total at λ = 0.1? Is it lower than the exact fit's total at the same λ?

Answer

Penalty = 0.05 × 1.146 = 0.0573, so the total is 0.0748 + 0.0573 = 0.1321. The exact fit's total at λ = 0.1 is 0.05 × 10,130,000 = 506,500, so yes, far lower.

What this toy leaves out

A network has too many weights to solve for, so training takes gradient-descent steps toward the lowest total instead. The penalty treats all weights alike, so it works best when the inputs share a scale; otherwise normalize them first. Large weights go with wild swings in this curve, but not in every model. Some libraries leave out the ½, or add the squared errors instead of averaging them, so check the formula before you compare values of λ.

With gradient descent, the penalty shrinks each weight a little at every step

Look at the penalty's part for one weight w: (λ/2) × w2. The slope of w2 is 2w, as the unit on derivatives shows, and multiplying a curve by a number multiplies its slope by the same number. So the penalty's slope is λw. If g is the gradient of the MSE for this weight, the gradient of the total is g + λw. One gradient-descent step with learning rate η is then:

wnew = w − η × (g + λw) = w × (1 − ηλ) − η × g

The right-hand form says: shrink the weight by the factor 1 − ηλ, then take the usual step. That shrinking is the weight decay of the AdamW unit, with the same formula. When ηλ is below 1, as it is in practice, the factor pulls a weight toward zero from either side without making it exactly zero.

Worked example: one step with the penalty

Take w = 2, g = 0.3, η = 0.1 and λ = 0.5.

  1. Gradient of the total: 0.3 + 0.5 × 2 = 1.3.
  2. Step: 2 − 0.1 × 1.3 = 2 − 0.13 = 1.87.
  3. The same by the right-hand form: 2 × (1 − 0.05) − 0.1 × 0.3 = 1.9 − 0.03 = 1.87.

Without the penalty, the step would give 2 − 0.03 = 1.97.

The penalty equals weight decay only for plain gradient descent

Adam divides the whole gradient, penalty term included, by each weight's typical gradient size, so the two differ there. The AdamW unit explains why AdamW shrinks the weights separately.

A penalty is one of several ways to curb overfitting

Each of these often lowers the validation loss too:

  • More training examples. A curve with 12 weights cannot pass through all of 100 noisy points.
  • Fewer weights. A curve with 5 weights turns at most 3 times, against 10 for 12 weights. Too few weights underfit.
  • Early stopping. Stop where the validation loss is lowest, as the validation-set unit shows.
  • Data augmentation. Train on altered copies of each example, such as rotated ones.

By the broad definition in the idea paragraph, early stopping and data augmentation count as regularization too.

Check yourself

  1. With λ = 0, a model has training loss 0.01 and validation loss 0.90. With a larger λ, the same model has 0.08 and 0.12. Which setting overfits, and which would you keep?

    Answer

    The first overfits: its training loss is tiny but its validation loss is far higher, and far higher than the second setting's. Keep the second, because the validation loss estimates the loss on new examples, and 0.12 is much lower than 0.90.

  2. You raise λ to 10 and both losses climb to about 0.5. What has gone wrong, and what does the curve look like?

    Answer

    Underfitting. The penalty is so strong that w1 to w11 are nearly zero (their squares add up to about 0.01 in the table). So the curve is nearly the level line y = w0 and misses the wave. Lower λ.

  3. Suppose every target were near 100 instead of near 0. Why would a penalty on w0 hurt?

    Answer

    The curve needs w0 near 100 to reach the points. A penalty on it would pull the whole curve down toward 0, away from every point. Shifting the curve never makes it swing, so that penalty costs accuracy and buys nothing.

  4. With η = 0.05 and λ = 2, a weight is −4 and the gradient of its MSE is −1. What is the weight after one gradient-descent step on the total?

    Answer

    −4 × (1 − 0.05 × 2) − 0.05 × (−1) = −3.6 + 0.05 = −3.55. The shrinking moves a negative weight up toward zero, just as it moves a positive one down.

Go further

Optional background, for readers who want more than this page.

Where this shows up

No unit or explanation builds on this one yet.