Classical ML Phase B · Lecture 6 of 12
Part II — Linear Models · Lecture 6

Regularisation: Ridge, LASSO, and Priors

We have reached for a penalty term three times already. Here is the proper treatment: every regulariser is a prior, ridge shrinks eigen-directions by a computable factor, and the corners of the L1 ball are precisely why LASSO produces zeros.

By the end you can

  • Derive ridge and LASSO as MAP estimates under Gaussian and Laplace priors
  • Show ridge shrinks the \(i\)-th eigen-direction by \(\lambda_i/(\lambda_i+\alpha)\)
  • Explain sparsity from the geometry of the \(\ell_1\) ball and from the subgradient
  • Derive the soft-thresholding operator and use it in coordinate descent
  • Choose \(\alpha\) by cross-validation, and say why standardisation is mandatory first

Assumed

  • Phase A, Lecture 14: MAP estimation, Gaussian and Laplace priors
  • Phase A, Lecture 11: eigenvalues, spectrum shifting, condition number
  • Phase A, Lecture 8: the \(\ell_p\) unit balls

1Every penalty is a prior

Phase A Lecture 14 proved this, and it is worth restating as the organising principle of the whole lecture. Maximising the posterior gives

\[\hat{\vw}_{\text{MAP}} = \argmin_{\vw}\Big[\underbrace{-\log p(\mathcal{D}\mid\vw)}_{\text{loss}} \;\underbrace{-\log p(\vw)}_{\text{regulariser}}\Big],\]

so a penalty term is a negative log-prior and nothing else. Reading the correspondence in both directions is useful:

\[\begin{array}{lll} \textbf{prior } p(\vw) & \textbf{penalty} & \textbf{name} \\[4pt] \mathcal{N}(\vzero,\tau^2\mI) & \alpha\|\vw\|_2^2 & \text{ridge / weight decay / Tikhonov} \\[3pt] \text{Laplace}(0,b) & \alpha\|\vw\|_1 & \text{LASSO} \\[3pt] \text{a mixture of both} & \alpha\big(\rho\|\vw\|_1 + \tfrac{1-\rho}{2}\|\vw\|_2^2\big) & \text{elastic net} \\[3pt] \mathcal{N}(\vzero,\mS_0) & \alpha\,\vw^\top\mS_0^{-1}\vw & \text{generalised Tikhonov} \\[3pt] \text{uniform (improper)} & 0 & \text{no regularisation = MLE} \end{array}\]

Common trap

Two consequences of this framing that people routinely get wrong.

2Ridge, in the eigenbasis

The closed form \(\hat{\vw}_\alpha = (\mX^\top\mX+\alpha\mI)^{-1}\mX^\top\vy\) is not very illuminating as written. Diagonalise and it becomes transparent.

Ridge shrinks each eigen-direction by λᵢ/(λᵢ+α)0 / 5
\[\mX^\top\mX = \mQ\Lambda\mQ^\top, \qquad \Lambda=\operatorname{diag}(\lambda_1,\dots,\lambda_d),\ \lambda_i\ge0\]
Spectral theorem. \(\mX^\top\mX\) is symmetric positive semi-definite (Phase A Lecture 11), so it has an orthonormal eigenbasis and non-negative eigenvalues. Large \(\lambda_i\) means the data varies a lot along \(\vq_i\); small \(\lambda_i\) means it barely varies at all in that direction.
\[\mX^\top\mX+\alpha\mI = \mQ(\Lambda+\alpha\mI)\mQ^\top \quad\Longrightarrow\quad (\mX^\top\mX+\alpha\mI)^{-1} = \mQ(\Lambda+\alpha\mI)^{-1}\mQ^\top\]
Adding \(\alpha\mI\) shifts every eigenvalue by \(\alpha\) and leaves the eigenvectors alone — Phase A Lecture 11, exercise 2. Inverting then inverts each shifted eigenvalue.
\[\hat{\vw}_\alpha = \mQ(\Lambda+\alpha\mI)^{-1}\mQ^\top\mX^\top\vy, \qquad \hat{\vw}_0 = \mQ\Lambda^{-1}\mQ^\top\mX^\top\vy\]
Write both estimators in the same basis. Everything is identical except the diagonal matrix in the middle.
\[\boxed{\ \vq_i^\top\hat{\vw}_\alpha = \frac{\lambda_i}{\lambda_i+\alpha}\ \big(\vq_i^\top\hat{\vw}_0\big)\ }\]
The result. Ridge takes the OLS solution and multiplies its component along \(\vq_i\) by \(\frac{\lambda_i}{\lambda_i+\alpha}\in(0,1)\). It is not uniform shrinkage. Directions with \(\lambda_i\gg\alpha\) are barely touched (factor ≈ 1); directions with \(\lambda_i\ll\alpha\) are almost annihilated (factor ≈ 0). Ridge preferentially destroys the directions in which the data carries least information — exactly the ones whose OLS estimates were wildest.
\[\text{effective degrees of freedom} = \tr\big(\mX(\mX^\top\mX+\alpha\mI)^{-1}\mX^\top\big) = \sum_{i=1}^{d}\frac{\lambda_i}{\lambda_i+\alpha}\]
The capacity interpretation. Phase A Lecture 10, exercise 2 showed \(\tr(\mP)=d\) counts parameters for OLS. Here the same trace is a continuous quantity between \(0\) and \(d\), decreasing in \(\alpha\). Regularisation does not remove parameters; it removes fractions of parameters, one shrinkage factor at a time. That is the precise sense in which \(\alpha\) tunes model complexity.
How ridge treats each eigen-direction differentlyInteractive
shrinkage factor λᵢ/(λᵢ+α)eigenvalue spectrum λᵢcurrent α
-1.00
2.50
Twenty eigen-directions, ordered from most to least informative. Blue is the factor ridge applies to each. Slide α up and watch the cut sweep from right to left: the low-eigenvalue directions — the ones the data barely constrains — are killed first, while the well-determined directions survive almost untouched. That selectivity is why ridge helps rather than simply degrading everything.

3LASSO and the geometry of zero

Swap the Gaussian prior for a Laplace one and the penalty becomes \(\alpha\|\vw\|_1\). There is no closed form — \(\|\vw\|_1\) is not differentiable at zero — and that non-differentiability is not an inconvenience, it is the entire mechanism.

Soft-thresholding: why coefficients become exactly zero0 / 6
\[\min_{w}\ \tfrac12(w-z)^2 + \alpha|w|\]
The one-dimensional LASSO problem. This is the subproblem that coordinate descent solves for each coefficient in turn, holding the others fixed; \(z\) is the OLS answer for that coordinate given the current residual. Solve it and you have solved LASSO.
\[\partial|w| = \begin{cases}\{+1\} & w>0\\ [-1,+1] & w=0\\ \{-1\} & w<0\end{cases}\]
The subdifferential. At a kink there is no single tangent line, but there is a set of slopes of lines lying below the function — Phase A Lecture 4's \(|x|\) figure, now put to work. Optimality means \(0\) belongs to the subdifferential of the objective.
\[0 \in (w-z) + \alpha\,\partial|w|\]
The optimality condition. The generalisation of \(f'=0\) to non-smooth convex functions. It is necessary and sufficient here because the objective is strictly convex.
\[w>0:\ w = z-\alpha \ \text{(needs } z>\alpha); \qquad w<0:\ w = z+\alpha \ \text{(needs } z<-\alpha)\]
The two smooth branches. If \(w>0\) the subdifferential is the single value \(+1\), giving \(w-z+\alpha=0\). For consistency we need the answer to actually be positive, i.e. \(z>\alpha\). Symmetrically for \(w<0\).
\[w=0:\ 0\in -z+\alpha[-1,1] \iff |z|\le\alpha\]
The kink branch — this is the whole point. At \(w=0\) the subdifferential is an entire interval, so the condition \(0\in -z+\alpha[-1,1]\) is satisfied for a whole range of \(z\), not just one value. A set of positive measure maps to exactly zero. A smooth penalty like \(w^2\) has a single subgradient \(2w=0\) at the origin, so only \(z=0\) exactly gives \(w=0\) — probability zero.
\[\boxed{\ w^\star = S_\alpha(z) = \operatorname{sign}(z)\,\max\big(|z|-\alpha,\ 0\big)\ }\]
The soft-thresholding operator. Move \(z\) towards zero by \(\alpha\); if that would overshoot, stop at zero. Compare the ridge solution to the same subproblem, \(w=\frac{z}{1+\alpha}\), which is a proportional shrink and never reaches zero. Proportional shrinkage cannot produce sparsity; constant shrinkage with a floor can. ∎
Regularisation paths: ridge shrinks, LASSO selectsInteractive
coefficients (ridge)coefficients (LASSO)current α
2
-2.00
0.30
Ten features, of which only three genuinely matter. Every curve is one coefficient traced as α grows. Ridge shrinks everything smoothly towards zero and arrives there only in the limit. LASSO drives coefficients to EXACTLY zero one at a time, and the order in which they drop out is a feature-selection ranking. Raise the correlation and watch LASSO become erratic — with correlated features it picks one arbitrarily and zeroes its twin.
Check yourself
Why does LASSO produce exact zeros while ridge does not, geometrically?
Correct. Correct — this is Phase A Lecture 8's unit-ball figure, now with a purpose. Write the penalised problem in constrained form: minimise \(\|\mX\vw-\vy\|^2\) subject to \(\|\vw\|_1\le t\). The solution is where the growing elliptical contour first touches the feasible ball.

The \(\ell_1\) ball is a diamond (a cross-polytope in \(d\) dimensions) whose vertices lie on the axes, where all but one coordinate is zero. A convex body touches a smooth expanding contour at a vertex for a whole cone of contour orientations — a set of positive measure. So sparsity is not a coincidence; it is generic.

The \(\ell_2\) ball is a sphere: smooth everywhere, no distinguished points. The touching point is a generic point of the sphere, with every coordinate nonzero with probability 1.

The algebraic version is the soft-thresholding derivation above: the subdifferential of \(|w|\) at zero is an interval, so an interval of \(z\) values maps to exactly zero. Geometry and algebra are saying the same thing — corners are where subdifferentials are set-valued.
Not quite. The observation is true (\(|w|>w^2\) for \(0<w<1\)) and is a real part of the intuition, but it is not the mechanism. Consider \(\|\vw\|_1^{1.5}\), which also exceeds \(w^2\) near zero but is differentiable at the origin — and produces no exact zeros. What matters is the kink: a discontinuous derivative at zero, so that a range of gradients is compatible with staying there. Relative magnitude is not enough; non-smoothness is.
Not quite. This reverses cause and effect. Sparsity is a property of the optimisation problem, not of the algorithm — the LASSO optimum is sparse whichever solver you use (LARS, proximal gradient, ADMM, an interior-point method). Coordinate descent is popular for LASSO because the one-dimensional subproblem has the closed-form soft-threshold solution, which is a consequence of the sparsity structure, not its cause.

4Elastic net, and when to use which

\[\mathcal{L}(\vw) = \|\mX\vw-\vy\|^2 + \alpha\Big(\rho\|\vw\|_1 + \tfrac{1-\rho}{2}\|\vw\|_2^2\Big)\]

The elastic net mixes both penalties, and it exists to fix a specific LASSO failure you can see in the figure above: with correlated features, LASSO picks one essentially at random and zeroes the rest, and which one it picks is unstable across resamples. The \(\ell_2\) component makes the objective strictly convex and encourages correlated features to be selected together with similar coefficients — the grouping effect.

\[\begin{array}{lll} \textbf{situation} & \textbf{use} & \textbf{why} \\[4pt] d \ll n,\ \text{features all plausibly relevant} & \text{ridge} & \text{keeps everything, controls variance} \\[3pt] d \gg n,\ \text{expect few relevant features} & \text{LASSO} & \text{selects; note it picks at most } n \\[3pt] \text{correlated groups of features} & \text{elastic net} & \text{selects groups, stable} \\[3pt] \text{you need to report coefficients} & \text{ridge or elastic net} & \text{LASSO's choice is unstable} \\[3pt] \text{you need a small model to deploy} & \text{LASSO} & \text{exact zeros can be dropped} \end{array}\]

Ridge and LASSO from scratch, with a cross-validated αPython · NumPy

5Exercises

★

A ridge problem has \(\mX^\top\mX\) with eigenvalues \(\{100, 10, 1, 0.01\}\) and \(\alpha=1\).

  1. Compute the shrinkage factor for each eigen-direction.
  2. What is the effective number of degrees of freedom?
  3. What does \(\alpha=1\) do to the condition number?
  4. Which direction is most affected, and why is that the right one to attack?

1. \(\frac{\lambda}{\lambda+1}\) gives \(\frac{100}{101}=0.9901\), \(\frac{10}{11}=0.9091\), \(\frac12=0.5\), \(\frac{0.01}{1.01}=0.0099\).

2. \(0.9901+0.9091+0.5+0.0099 = 2.409\) of 4 parameters. The model behaves as though it had about two and a half free parameters instead of four.

3. Unregularised \(\kappa=100/0.01=10{,}000\). With ridge, \(\kappa=\frac{101}{1.01}=100\) — a hundredfold improvement, and by Lecture 03 that is a hundredfold reduction in the gradient-descent iteration count. Regularisation and preconditioning really are one operation.

4. The \(\lambda=0.01\) direction, which retains only 1% of its OLS value. That is exactly right. A small eigenvalue means the data barely varies along \(\vq_i\), so \(\vq_i^\top\hat{\vw}_0 = \frac{\vq_i^\top\mX^\top\vy}{\lambda_i}\) divides by a tiny number and the OLS estimate in that direction is dominated by noise. Ridge suppresses the directions whose estimates were least trustworthy and leaves the well-determined ones essentially alone — which is why it reduces variance far more than it adds bias.

★★

Prove the soft-thresholding formula from the subgradient condition, then show that ridge's one-dimensional solution is \(w=\frac{z}{1+\alpha}\).

Use both to explain in one paragraph why LASSO is a selection method and ridge is a shrinkage method, and why "LASSO shrinks more" is the wrong description.

LASSO. Minimise \(g(w)=\tfrac12(w-z)^2+\alpha|w|\), strictly convex, so \(w^\star\) is the unique point with \(0\in\partial g(w^\star)=(w^\star-z)+\alpha\,\partial|w^\star|\).

Case \(w^\star>0\): \(\partial|w^\star|=\{1\}\), so \(w^\star=z-\alpha\), consistent only if \(z>\alpha\).
Case \(w^\star<0\): \(w^\star=z+\alpha\), consistent only if \(z<-\alpha\).
Case \(w^\star=0\): need \(0\in -z+\alpha[-1,1]\), i.e. \(z\in[-\alpha,\alpha]\).

The three cases are exhaustive and mutually exclusive, giving \(w^\star = \operatorname{sign}(z)\max(|z|-\alpha,0)\). ∎

Ridge. \(h(w)=\tfrac12(w-z)^2+\tfrac{\alpha}{2}w^2\) is smooth, so \(h'(w)=(w-z)+\alpha w=0\), giving \(w^\star=\frac{z}{1+\alpha}\). ∎

The distinction. Ridge applies a multiplicative shrink of \(\frac{1}{1+\alpha}\) — the same proportion to every coefficient, so a coefficient of 10 loses ten times as much as a coefficient of 1, and no coefficient ever reaches zero at finite \(\alpha\). LASSO applies an additive shrink of \(\alpha\) with a floor at zero — every coefficient loses the same absolute amount, so small ones are wiped out entirely while large ones are barely affected in relative terms.

So "LASSO shrinks more" is wrong in both directions. For a large coefficient (\(z=10\), \(\alpha=1\)): LASSO gives 9, ridge gives 5 — ridge shrinks more. For a small one (\(z=0.5\)): LASSO gives 0, ridge gives 0.33 — LASSO shrinks more. They are qualitatively different operations, not the same operation at different strengths. LASSO makes a discrete decision about each coefficient (in or out); ridge makes a continuous adjustment to all of them. That is why LASSO's answer is unstable under resampling (small perturbations flip discrete decisions) while ridge's is smooth.

★★

Show that ridge regression can be computed by augmenting the data: solving ordinary least squares on

\[ \tilde{\mX} = \begin{bmatrix}\mX\\ \sqrt{\alpha}\,\mI\end{bmatrix}\in\RR^{(n+d)\times d}, \qquad \tilde{\vy} = \begin{bmatrix}\vy\\ \vzero\end{bmatrix}\in\RR^{n+d} \]

gives exactly \(\hat{\vw}_\alpha\). Then say what this tells you about ridge as data augmentation, and why it is numerically preferable to forming \(\mX^\top\mX+\alpha\mI\).

Proof. The OLS objective on the augmented data is

\[\|\tilde{\mX}\vw-\tilde{\vy}\|^2 = \left\|\begin{bmatrix}\mX\vw-\vy\\ \sqrt\alpha\,\vw\end{bmatrix}\right\|^2 = \|\mX\vw-\vy\|^2 + \alpha\|\vw\|^2,\]

because the squared norm of a stacked vector is the sum of the squared norms of its blocks. That is exactly the ridge objective, so the minimisers coincide. ∎

Confirming via the normal equations: \(\tilde{\mX}^\top\tilde{\mX} = \mX^\top\mX+\alpha\mI\) and \(\tilde{\mX}^\top\tilde{\vy}=\mX^\top\vy\), giving precisely the ridge system.

Ridge as data augmentation. The \(d\) extra rows are \(d\) fictitious observations, each saying "feature \(j\) alone, scaled by \(\sqrt\alpha\), produces output 0". They are the prior, written as data. This makes the strength of a prior directly comparable to an amount of evidence, which is a genuinely useful mental model: \(\alpha\) large means "I have a lot of pseudo-observations telling me the weights are small", and it explains why the prior's influence fades as \(n\) grows — the real rows come to outnumber the fake ones.

It also generalises immediately. Replacing \(\sqrt\alpha\mI\) with \(\sqrt\alpha\mathbf{D}\) implements a different penalty \(\alpha\|\mathbf{D}\vw\|^2\), which is how smoothing splines penalise curvature and how graph-Laplacian regularisers encourage neighbouring coefficients to agree.

Why it is numerically better. The condition number argument from Phase A Lecture 10: forming \(\mX^\top\mX\) squares \(\kappa\), so a design with \(\kappa(\mX)=10^{8}\) gives \(\kappa(\mX^\top\mX)=10^{16}\), exhausting float64 before \(\alpha\) is even added. The augmented matrix \(\tilde{\mX}\) has \(\kappa(\tilde{\mX})=\sqrt{\kappa(\mX^\top\mX+\alpha\mI)}\) — the square root, not the square. Running lstsq on \(\tilde{\mX}\) therefore loses about half as many digits.

This is what production ridge implementations do (scikit-learn's solver='lsqr' and 'sparse_cg' work on the augmented system), and it is also the trick that makes ridge feasible for sparse \(\mX\), where forming the dense Gram matrix would be impossible.

★★★

Coding. Compare ridge, LASSO and elastic net on a hard problem, and investigate selection stability.

  1. Generate \(n=100\), \(d=200\) (so \(d\gg n\)) with 10 truly nonzero coefficients arranged in two correlated groups of five.
  2. Fit all three with \(\alpha\) chosen by 5-fold CV. Report test MSE, number of nonzeros, and how many true features were recovered.
  3. Repeat the whole thing 50 times with fresh data and measure selection stability: for each feature, the fraction of runs in which it was selected.
  4. Which method is most stable, and what does that imply about reporting "the important features"?
import numpy as np
rng = np.random.default_rng(0)

def make(n=100, d=200, seed=None):
    r = np.random.default_rng(seed)
    g1, g2 = r.normal(size=(n,1)), r.normal(size=(n,1))
    X = r.normal(size=(n,d))
    X[:, :5]   = 0.9*g1 + 0.44*X[:, :5]        # correlated group A
    X[:, 5:10] = 0.9*g2 + 0.44*X[:, 5:10]      # correlated group B
    w = np.zeros(d); w[:10] = 1.5
    return X, X@w + r.normal(size=n), w

def enet(Z, y, a, rho, T=300):
    n_, d_ = Z.shape
    w = np.zeros(d_); G = Z.T@Z; b = Z.T@y; dg = np.diag(G).copy()
    for _ in range(T):
        for j in range(d_):
            r_ = b[j] - G[j]@w + G[j,j]*w[j]
            z = r_/(dg[j] + a*n_*(1-rho))
            t = a*n_*rho/(dg[j] + a*n_*(1-rho))
            w[j] = np.sign(z)*max(abs(z)-t, 0.0)
    return w

methods = {"ridge": lambda Z,y,a: enet(Z,y,a,0.0),
           "lasso": lambda Z,y,a: enet(Z,y,a,1.0),
           "enet":  lambda Z,y,a: enet(Z,y,a,0.5)}

sel = {k: np.zeros(200) for k in methods}
stats = {k: [] for k in methods}
for rep in range(50):
    X, y, wt = make(seed=rep); Xte, yte, _ = make(seed=1000+rep)
    Z = (X - X.mean(0))/(X.std(0)+1e-12); yc = y - y.mean()
    Zt = (Xte - X.mean(0))/(X.std(0)+1e-12)
    for k, f in methods.items():
        best = min(((np.mean((Zt@f(Z,yc,a) - (yte-y.mean()))**2), a)
                    for a in np.logspace(-3, 0, 12)))
        w = f(Z, yc, best[1])
        nz = np.abs(w) > 1e-8
        sel[k] += nz
        stats[k].append((best[0], nz.sum(), nz[:10].sum(), nz[10:].sum()))

for k in methods:
    s = np.array(stats[k])
    print(f"{k:6s} test MSE {s[:,0].mean():7.3f}  nonzero {s[:,1].mean():6.1f}"
          f"  true found {s[:,2].mean():5.2f}/10  false {s[:,3].mean():6.1f}")
    freq = sel[k]/50
    print(f"        selection frequency: true features {freq[:10].mean():.2f}, "
          f"noise features {freq[10:].mean():.3f}, "
          f"true features always chosen: {(freq[:10]==1).sum()}/10")

2. Ridge keeps all 200 coefficients (no zeros ever) and gets respectable test MSE. LASSO selects roughly 20–40 features, recovering perhaps 5–7 of the 10 true ones — note it typically picks only one or two from each correlated group of five, because once one is in, its correlated twins add little and are thresholded away. Elastic net selects more (40–70), recovers 8–10 of the true ones, and usually has the best or near-best test MSE.

3 & 4. Stability is the striking result. Across 50 resamples, LASSO's selection frequency for the true features is erratic — a given member of a correlated group might be chosen in 30% of runs, its twin in 25%, with essentially arbitrary allocation. Elastic net selects true features far more consistently (frequencies often above 0.8), because the \(\ell_2\) term rewards spreading weight across correlated features rather than concentrating it on one. Ridge is trivially "stable" only because it selects everything.

What this implies about reporting important features. A LASSO run gives you a sparse model that predicts well; it does not give you the set of relevant variables. If a colleague reruns your analysis on next quarter's data and gets a different feature set, that is expected behaviour, not a bug. Three legitimate responses:

  • Stability selection: run LASSO on many bootstrap resamples and report features selected in, say, over 60% of them. This has genuine false-discovery guarantees and is what you should do if the feature list is the deliverable.
  • Elastic net if correlated features should be reported as a group.
  • Say what you mean. "These 12 features suffice for prediction" is a defensible claim. "These 12 features are the causally relevant ones" is not — and no regularisation path can make it so.

Next: we have been choosing \(\alpha\) by cross-validation without examining what cross-validation actually estimates. Lecture 07 derives the bias–variance decomposition, builds the evaluation toolkit properly, and is blunt about which metrics mislead.