Regularization: L1/L2, Early Stopping, and Dropout
The main tool for fixing the overfitting side of the last page — deliberately making a model worse at fitting its training data so it gets better at everything else.
Intermediate
lambda:
J(w, b) = MSE(w, b) + (lambda / 2m) * sum(w_j^2 for each feature j)
# the bias term b is conventionally left out of the penalty --
# only the feature weights are pushed toward zero
J(w, b) = MSE(w, b) + (lambda / m) * sum(abs(w_j) for each feature j)
w² shrinks with w), so it shrinks weights
toward zero without much pressure to reach it exactly — most features keep a small, nonzero
weight. L1's penalty stays constant regardless of how small the weight already is, so it keeps
pushing until some weights land on exactly zero. Concretely: if day_of_week turns
out to carry no real signal about CI failures, L1 regularization can drive its weight to
precisely 0 — the feature is effectively removed from the model — while L2 would leave it at
some small nonzero value that still technically contributes to every prediction. That makes L1
a built-in feature-selection mechanism, useful when you suspect many features are irrelevant
and want a sparser, more interpretable model; L2 is the more common default otherwise.
lambda directly controls the bias/variance tradeoff from the previous page.
lambda = 0 is no regularization at all — back to the original overfitting risk.
A very large lambda crushes every weight toward zero so hard that the model can
no longer fit even the training data — a regularization-induced underfitting. The right value
sits between the two, and the honest way to find it is the same cross-validation sweep from
Train/Test Splits & Cross-Validation: train the model
once per candidate lambda, score each on the validation set, and pick whichever
minimizes validation error — not training error, which decreasing lambda will
always improve on its own.
w_j = w_j - alpha * (dJ/dw_j + (lambda/m) * w_j)
= w_j * (1 - alpha*lambda/m) - alpha * (dJ/dw_j)
w_j by
a small multiplicative factor (1 - alpha*lambda/m, slightly less than 1) before
applying the usual gradient-based update — the parameter literally decays toward zero a little
every step, independent of whatever the data says. That's the origin of the term
weight decay, used interchangeably with L2 regularization in most of the
literature. One nuance worth flagging for later: this clean equivalence between L2 and weight
decay holds for plain gradient descent, but breaks down for adaptive optimizers like Adam —
exactly the gap AdamW was built to close, covered in the
Deep Learning & PyTorch Engineering track.