Skip to content
VibeFormer
Intermediate30 min

Regularisation

L1 and L2 penalties, elastic net, the constrained-optimisation view, and why L1 induces sparsity.

Regularisation

Intuition first

Overfitting happens when a model has enough freedom to chase noise. Regularisation removes some of that freedom — not by deleting parameters, but by making large parameters expensive.

Think of it as a tax on complexity. The model still wants to fit the data, but now every unit of coefficient magnitude costs something. Faced with two explanations that fit equally well, it picks the smaller one. Since noise-chasing generally requires large, finely-tuned coefficients that cancel each other out, taxing magnitude suppresses noise-fitting more than it suppresses genuine signal.

The tax rate is a hyperparameter. Set it to zero and you are back to unregularised fitting. Set it too high and the model is taxed into predicting nothing but the mean.

Notation used in this lesson
SymbolMeaning
wVector of model weights (coefficients)
λRegularisation strength — the tax rate
‖w‖₂²Sum of squared weights
‖w‖₁Sum of absolute weights
J(w)Regularised objective being minimised

The penalised objective

J(w)=1ni=1nL(yi,hw(xi))fit the data  +  λΩ(w)stay simpleJ(w) = \underbrace{\frac{1}{n}\sum_{i=1}^{n} L\big(y_i, h_w(x_i)\big)}_{\text{fit the data}} \;+\; \underbrace{\lambda\, \Omega(w)}_{\text{stay simple}}

The two standard penalties:

L2 (ridge):Ω(w)=w22=j=1dwj2\text{L2 (ridge)}: \quad \Omega(w) = \lVert w \rVert_2^2 = \sum_{j=1}^{d} w_j^2 L1 (lasso):Ω(w)=w1=j=1dwj\text{L1 (lasso)}: \quad \Omega(w) = \lVert w \rVert_1 = \sum_{j=1}^{d} \lvert w_j \rvert

Why L1 produces exact zeros and L2 does not

This is the single most asked question about regularisation, and the geometric answer is the clearest.

w₁ = 0L1 — corner contactboth ≠ 0L2 — smooth contact
The penalty defines a feasible region; the ellipses are contours of the data-fitting loss. L1's diamond has corners on the axes, so the first contact often lands exactly on an axis — a zero coefficient. L2's circle has no corners.
The algebraic version: soft thresholdingAdvanced

Consider the simplest case — one coefficient, orthonormal features, so the least-squares solution is some value zz. The L1-penalised problem is

minw  12(wz)2+λw\min_{w} \; \tfrac{1}{2}(w - z)^2 + \lambda \lvert w \rvert

For w>0w > 0 the derivative is (wz)+λ(w - z) + \lambda, zero at w=zλw = z - \lambda. For w<0w < 0 it is (wz)λ(w - z) - \lambda, zero at w=z+λw = z + \lambda. Neither is valid if it crosses zero, in which case the minimum sits at the kink w=0w = 0. Combining:

wlasso=sign(z)max(zλ,  0)w^{\text{lasso}} = \text{sign}(z)\,\max\big(\lvert z \rvert - \lambda,\; 0\big)

This is the soft-thresholding operator: shift every coefficient towards zero by λ\lambda, and clamp at zero. Any coefficient with zλ\lvert z \rvert \leq \lambda becomes exactly zero.

The L2 problem is smooth:

minw  12(wz)2+λw2(wz)+2λw=0wridge=z1+2λ\min_w \; \tfrac{1}{2}(w - z)^2 + \lambda w^2 \quad\Longrightarrow\quad (w - z) + 2\lambda w = 0 \quad\Longrightarrow\quad w^{\text{ridge}} = \frac{z}{1 + 2\lambda}

A proportional shrinkage. It can make coefficients arbitrarily small but never exactly zero for finite λ\lambda, because the penalty's gradient vanishes at the origin while L1's does not.

That asymmetry — L1 has a non-zero gradient at zero, L2 does not — is the entire mechanism behind sparsity.

Ridge in closed form

For linear regression the L2 solution is analytic:

w^ridge=(XTX+λI)1XTy\hat{w}_{\text{ridge}} = \big(X^{\mathsf{T}}X + \lambda I\big)^{-1} X^{\mathsf{T}} y
Why ridge fixes multicollinearityAdvanced

Take the SVD X=UΣVTX = U\Sigma V^{\mathsf{T}} with singular values σj\sigma_j. The ordinary least-squares and ridge solutions become

w^OLS=j1σj(ujTy)vj,w^ridge=jσjσj2+λ(ujTy)vj\hat{w}_{\text{OLS}} = \sum_j \frac{1}{\sigma_j}\,(u_j^{\mathsf{T}}y)\, v_j, \qquad \hat{w}_{\text{ridge}} = \sum_j \frac{\sigma_j}{\sigma_j^2 + \lambda}\,(u_j^{\mathsf{T}}y)\, v_j

When features are nearly collinear, some σj0\sigma_j \approx 0. In OLS that 1/σj1/\sigma_j explodes, so tiny changes in the data produce enormous swings in the coefficients — the definition of high variance.

Ridge replaces 1/σj1/\sigma_j with σj/(σj2+λ)\sigma_j/(\sigma_j^2 + \lambda), which tends to σj/λ0\sigma_j / \lambda \to 0 as σj0\sigma_j \to 0. The unstable directions are damped rather than amplified.

Adding λI\lambda I also guarantees XTX+λIX^{\mathsf{T}}X + \lambda I is invertible for any λ>0\lambda > 0, so ridge has a unique solution even when d>nd > n and OLS has none.

Comparing the penalties

L2 / RidgeL1 / LassoElastic Net
Shrinks coefficientsProportionallyBy a constant, then clampsBoth
Produces exact zerosNoYesYes
Correlated featuresShares weight between themPicks one arbitrarilyShares among the group
Solution uniqueAlwaysNot alwaysAlways
Closed formYesNo — needs coordinate descentNo
Use whenMany weak predictorsFew strong predictors, want selectionCorrelated groups
Elastic Net:Ω(w)=αw1+(1α)w22\text{Elastic Net}: \quad \Omega(w) = \alpha \lVert w \rVert_1 + (1 - \alpha)\lVert w \rVert_2^2

Solved problem 1 · Ridge and lasso by hand

With orthonormal features, the unregularised coefficients are

z=(3.0,  1.4,  0.5,  0.2)z = (3.0,\; -1.4,\; 0.5,\; -0.2)

Compute the ridge solution with λ=0.5\lambda = 0.5 and the lasso solution with λ=0.6\lambda = 0.6.

Step 1 — ridge: proportional shrinkage

wj=zj1+2λ=zj1+1.0=zj2w_j = \frac{z_j}{1 + 2\lambda} = \frac{z_j}{1 + 1.0} = \frac{z_j}{2}wridge=(1.50,  0.70,  0.25,  0.10)w^{\text{ridge}} = (1.50,\; -0.70,\; 0.25,\; -0.10)

Every coefficient halved. None reached zero, and the relative ordering is preserved exactly.

Step 2 — lasso: soft thresholding, coefficient by coefficient

wj=sign(zj)max(zj0.6,  0)w_j = \text{sign}(z_j)\max(\lvert z_j \rvert - 0.6,\; 0)z1=3.0:3.00.6=2.4w1=+2.40z_1 = 3.0: \quad 3.0 - 0.6 = 2.4 \quad\Longrightarrow\quad w_1 = +2.40z2=1.4:1.40.6=0.8w2=0.80z_2 = -1.4: \quad 1.4 - 0.6 = 0.8 \quad\Longrightarrow\quad w_2 = -0.80z3=0.5:0.50.6=0.1<0w3=0z_3 = 0.5: \quad 0.5 - 0.6 = -0.1 < 0 \quad\Longrightarrow\quad w_3 = 0z4=0.2:0.20.6=0.4<0w4=0z_4 = -0.2: \quad 0.2 - 0.6 = -0.4 < 0 \quad\Longrightarrow\quad w_4 = 0wlasso=(2.40,  0.80,  0,  0)w^{\text{lasso}} = (2.40,\; -0.80,\; 0,\; 0)

Step 3 — contrast the two

Ridge kept all four features with every coefficient halved. Lasso eliminated the two weakest and shrank the survivors by a fixed amount rather than proportionally.

Note that lasso shrank the large coefficient less in relative terms — 3.02.43.0 \to 2.4 is a 20% reduction, while 1.40.81.4 \to 0.8 is 43%. Ridge reduced both by exactly 50%.

Answer

Ridge: (1.50,0.70,0.25,0.10)(1.50, -0.70, 0.25, -0.10) — all retained, proportionally shrunk. Lasso: (2.40,0.80,0,0)(2.40, -0.80, 0, 0) — two coefficients eliminated, performing feature selection as a side effect of fitting.

Regularisation beyond penalties

Anything that reduces effective capacity regularises, whether or not it appears in the objective:

  • Early stopping — halting before the model has time to memorise. For linear models it is provably close to ridge.
  • Dropout — randomly deactivating units, approximately averaging an ensemble.
  • Data augmentation — enlarging the effective dataset with label-preserving transformations.
  • Batch normalisation — the noise from batch statistics acts as a mild regulariser.
  • Weight sharing — convolution is a hard constraint that a filter applies identically everywhere.
  • Adding noise to inputs — for linear regression, equivalent to ridge exactly.

Choosing λ

Cross-validate over a logarithmic grid. Never a linear one: the interesting behaviour spans orders of magnitude.

python
import numpy as np
from sklearn.linear_model import RidgeCV, LassoCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_regression

X, y = make_regression(n_samples=300, n_features=40, n_informative=8,
                       noise=15.0, random_state=0)

alphas = np.logspace(-3, 3, 25)          # log grid, 0.001 → 1000

# StandardScaler inside the pipeline: the penalty is scale-sensitive, and the
# scaler must be fitted per fold to avoid leakage.
ridge = make_pipeline(StandardScaler(), RidgeCV(alphas=alphas, cv=5)).fit(X, y)
lasso = make_pipeline(StandardScaler(), LassoCV(alphas=alphas, cv=5, max_iter=5000)).fit(X, y)

r_coef = ridge[-1].coef_
l_coef = lasso[-1].coef_

print(f"ridge  alpha={ridge[-1].alpha_:.4f}  zeros={np.sum(r_coef == 0):2d}/40")
print(f"lasso  alpha={lasso[-1].alpha_:.4f}  zeros={np.sum(l_coef == 0):2d}/40")
print(f"true informative features: 8")

Ridge reports zero exact zeros; lasso typically recovers close to the 8 informative features. That contrast is the whole lesson in two lines of output.

Exercise 1

A model has 5,000 features and 300 training examples. Which penalty, and why?

Show solution

L1, or elastic net. With dnd \gg n the priority is reducing the effective number of parameters, and at most 300 can be identified from 300 examples regardless.

Lasso sets most coefficients to exactly zero, producing an interpretable subset and a model whose effective capacity matches the data available. Ridge would retain all 5,000 features with small coefficients — numerically stable, since λI\lambda I guarantees invertibility, but neither sparse nor interpretable.

Elastic net is the safer default if features are correlated. Pure lasso picks one member of a correlated group essentially arbitrarily, and which one it picks can change with a small perturbation of the data — unstable, and misleading if you interpret the selection as "these features matter". The L2 component makes correlated features share weight, stabilising the selection.

Exercise 2

Training accuracy 0.71, validation accuracy 0.69. A colleague suggests increasing L2 strength. Assess.

Show solution

Wrong direction. The gap is 2 points — there is essentially no variance problem. Both numbers being low means high bias: the model cannot represent the pattern.

Increasing λ\lambda further constrains an already over-constrained model, raising bias and pushing both numbers down.

The right moves are the opposite: decrease λ\lambda, add capacity or features, or use a more expressive model family. If λ\lambda is already small and the model is still underfitting, regularisation is not the lever at all.

The general rule: diagnose from the gap before choosing a remedy. Regularisation treats variance; it makes bias worse.


Next: The Curse of Dimensionality, which explains why high-dimensional data needs this kind of constraint so badly.