AI Knowledge Tree

Ridge regression

Add an L2 penalty, derive the closed-form solution, and see why ridge shrinks small singular directions the most.

When the design matrix has nearly collinear columns or more features than examples, OLS coefficients become enormous and unstable. Ridge regression adds an L2 penalty to the loss, trading a small bias for a large variance reduction. The closed form has a clean SVD interpretation: ridge shrinks the small-singular-value directions the most.

The objective

Ridge regression adds an L2 (Tikhonov) penalty to the OLS loss:

β^λ=arg⁡min⁡β  ∥y−Xβ∥2+λ ∥β∥2,\hat\beta_\lambda = \arg\min_\beta\; \lVert \mathbf{y} - X\beta\rVert^2 + \lambda\,\lVert \beta \rVert^2,

with λ≥0\lambda \ge 0 controlling the shrinkage. At λ=0\lambda = 0 it is OLS; as λ→∞\lambda \to \infty all coefficients shrink to zero. The intercept is usually not penalized (center the data instead).

Closed-form solution

Setting the gradient of the objective to zero,

2X⊤(Xβ−y)+2λβ=0  ⟹  (X⊤X+λI)β=X⊤y,2 X^\top(X\beta - \mathbf{y}) + 2\lambda\beta = 0 \implies (X^\top X + \lambda I)\beta = X^\top \mathbf{y},

so

β^λ=(X⊤X+λI)−1X⊤y.\hat\beta_\lambda = (X^\top X + \lambda I)^{-1} X^\top \mathbf{y}. [1]

The added λI\lambda I makes X⊤X+λIX^\top X + \lambda I always invertible (its eigenvalues are shifted up by λ>0\lambda > 0), which is the cure for the collinearity disease of OLS.

The SVD reading: shrink small directions hardest

Let X=UΣV⊤X = U \Sigma V^\top be the SVD with singular values σj\sigma_j. Substitute:

β^λ=V(Σ2+λI)−1Σ U⊤y=V diag⁡ ⁣(σjσj2+λ)U⊤y.\hat\beta_\lambda = V (\Sigma^2 + \lambda I)^{-1} \Sigma\, U^\top \mathbf{y} = V\,\operatorname{diag}\!\left(\frac{\sigma_j}{\sigma_j^2 + \lambda}\right) U^\top \mathbf{y}.

Compare to OLS: β^OLS=V diag⁡(1/σj) U⊤y\hat\beta_{\text{OLS}} = V\,\operatorname{diag}(1/\sigma_j)\,U^\top \mathbf{y}. The shrinkage factor in direction jj is

σj2σj2+λ∈(0,1].\frac{\sigma_j^2}{\sigma_j^2 + \lambda} \in (0, 1].

Directions with large σj\sigma_j (high variance in XX, well-determined) are barely shrunk: σj2/(σj2+λ)≈1\sigma_j^2/(\sigma_j^2 + \lambda) \approx 1. Directions with small σj\sigma_j (collinear or rarely seen) get crushed: σj2/(σj2+λ)≈0\sigma_j^2/(\sigma_j^2 + \lambda) \approx 0. Ridge does not zero out coefficients; it bends the OLS solution back toward the origin proportionally to how poorly each direction was determined.

Fix λ=1\lambda = 1 and read the factor across a range of singular values to feel the asymmetry:

  • σj=10\sigma_j = 10 (a well-determined direction): factor 100/101≈0.99100/101 \approx 0.99, almost untouched.
  • σj=1\sigma_j = 1 (singular value equal to λ\sqrt{\lambda}): factor 1/2=0.51/2 = 0.5, the crossover where the coefficient is halved.
  • σj=0.1\sigma_j = 0.1 (a nearly collinear direction): factor 0.01/1.01≈0.00990.01/1.01 \approx 0.0099, kept down to about 1%1\% of its OLS value.

The penalty barely sees the strong directions and almost erases the weak ones, which is the point: the weak directions are where OLS blows up.

Ridge as MAP estimation

Place a Gaussian prior β∼N(0,τ2I)\beta \sim \mathcal{N}(0, \tau^2 I) and combine with the Gaussian likelihood from the MLE lesson. The negative log posterior is

12σ2∑i(yi−xi⊤β)2+12τ2∥β∥2+const.\frac{1}{2\sigma^2}\sum_i (y_i - x_i^\top\beta)^2 + \frac{1}{2\tau^2}\lVert\beta\rVert^2 + \text{const}.

Maximizing the posterior (MAP) is the same as ridge with λ=σ2/τ2\lambda = \sigma^2/\tau^2. Stronger prior belief in small coefficients (small τ2\tau^2) means larger λ\lambda. Regularization is a prior in disguise[2].

Bias-variance tradeoff at the lever

Ridge biases coefficients toward zero (the bias term in the bias-variance decomposition grows) but cuts their sensitivity to the data (variance shrinks). On problems where OLS variance is the dominant error term (small nn, large dd, collinear features), the net effect of even a small λ\lambda is a lower expected test error. The optimal λ\lambda is chosen by cross-validation.

Ridge coefficient paths: as the penalty λ grows, every coefficient shrinks smoothly toward zero (but, unlike LASSO, never exactly to zero).
Ridge coefficient paths: as the penalty λ grows, every coefficient shrinks smoothly toward zero (but, unlike LASSO, never exactly to zero).

Check it on arrays

python · numpy
import numpy as np

rng = np.random.default_rng(0)
n, d = 30, 12                                # n only slightly > d
X = rng.normal(size=(n, d))
X[:, 0] = 1.0
beta_true = rng.normal(size=d)
y = X @ beta_true + 0.3 * rng.normal(size=n)

def ridge(X, y, lam):
    # Penalize every coefficient EXCEPT the intercept (column 0 is the constant
    # 1). Otherwise large lambda shrinks the intercept toward 0, biasing
    # predictions on uncentered targets.
    d = X.shape[1]
    P = np.eye(d); P[0, 0] = 0.0
    return np.linalg.solve(X.T @ X + lam * P, X.T @ y)

def coef_norm(b): return np.linalg.norm(b)
def train_err(b): return np.mean((y - X @ b)**2)

# Sweep lambda and compare to OLS via the SVD shrinkage factors
print(f"{'lambda':>8}  {'||beta||':>9}  {'train MSE':>10}")
for lam in [0.0, 0.1, 1.0, 10.0, 100.0]:
    b = ridge(X, y, lam)
    print(f"{lam:>8.2f}  {coef_norm(b):>9.4f}  {train_err(b):>10.4f}")

# Confirm the SVD shrinkage formula. The closed form penalizes EVERY direction
# uniformly, so for this check we run a fully-penalized ridge variant.
def ridge_all_penalized(X, y, lam):
    return np.linalg.solve(X.T @ X + lam * np.eye(X.shape[1]), X.T @ y)

U, s, Vt = np.linalg.svd(X, full_matrices=False)
lam = 1.0
b_formula = Vt.T @ (s / (s**2 + lam) * (U.T @ y))
b_direct = ridge_all_penalized(X, y, lam)
print("SVD form == fully-penalized ridge:", np.allclose(b_formula, b_direct))

# Cross-validation to choose lambda
from itertools import islice
def cv_score(lam, k=5):
    idx = rng.permutation(n)
    folds = np.array_split(idx, k)
    errs = []
    for fold in folds:
        train = np.setdiff1d(idx, fold)
        b = ridge(X[train], y[train], lam)
        errs.append(np.mean((y[fold] - X[fold] @ b)**2))
    return np.mean(errs)

lams = np.logspace(-2, 2, 9)
scores = [cv_score(l) for l in lams]
best = lams[int(np.argmin(scores))]
print("best lambda:", round(best, 3))

The coefficient norm shrinks as λ\lambda grows, train MSE grows (fitting less), the SVD shrinkage formula matches the direct solve to machine precision, and cross-validation picks a finite λ\lambda where bias and variance balance.

Exercises

Exercise 1. For a single direction with singular value σ=2\sigma = 2 and penalty λ=4\lambda = 4, compute the ridge shrinkage factor σ2/(σ2+λ)\sigma^2/(\sigma^2 + \lambda) and state by what fraction the OLS coefficient in that direction is reduced.

Solution

Step 1. The shrinkage factor multiplies the OLS coefficient in that direction. With σ=2\sigma = 2, σ2=4\sigma^2 = 4, and λ=4\lambda = 4,

σ2σ2+λ=44+4=48=0.5.\frac{\sigma^2}{\sigma^2 + \lambda} = \frac{4}{4 + 4} = \frac{4}{8} = 0.5.

Step 2. A factor of 0.50.5 means the ridge coefficient in that direction is half the OLS value, a reduction of 50%50\%. This is the crossover case σ2=λ\sigma^2 = \lambda (equivalently σ=λ\sigma = \sqrt{\lambda}): directions with larger σ\sigma are shrunk less, smaller σ\sigma more.

Exercise 2. Derive the ridge closed form β^λ=(X⊤X+λI)−1X⊤y\hat\beta_\lambda = (X^\top X + \lambda I)^{-1} X^\top \mathbf{y} by setting the gradient of the penalized objective to zero, and explain why X⊤X+λIX^\top X + \lambda I is always invertible for λ>0\lambda > 0.

Solution

Step 1. Write the objective J(β)=∥y−Xβ∥2+λ∥β∥2J(\beta) = \lVert \mathbf{y} - X\beta\rVert^2 + \lambda\lVert\beta\rVert^2. Its gradient is the OLS gradient plus the penalty gradient:

∇βJ=−2X⊤(y−Xβ)+2λβ.\nabla_\beta J = -2 X^\top(\mathbf{y} - X\beta) + 2\lambda\beta.

Step 2. Set the gradient to zero and divide by 2:

−X⊤y+X⊤Xβ+λβ=0  ⟹  (X⊤X+λI)β=X⊤y.-X^\top \mathbf{y} + X^\top X\beta + \lambda\beta = 0 \implies (X^\top X + \lambda I)\beta = X^\top \mathbf{y}.

Solving for β\beta gives β^λ=(X⊤X+λI)−1X⊤y\hat\beta_\lambda = (X^\top X + \lambda I)^{-1} X^\top \mathbf{y}.

Step 3. X⊤XX^\top X is symmetric positive semidefinite, so its eigenvalues νj≥0\nu_j \ge 0. Adding λI\lambda I shifts every eigenvalue to νj+λ\nu_j + \lambda. For λ>0\lambda > 0 each νj+λ>0\nu_j + \lambda > 0, so the matrix has no zero eigenvalue and is invertible, even when XX is rank-deficient and X⊤XX^\top X alone is singular.

Exercise 3 (code). Verify the MAP equivalence numerically: ridge with penalty λ\lambda equals the maximum-a-posteriori estimate under a Gaussian prior β∼N(0,τ2I)\beta \sim \mathcal{N}(0, \tau^2 I) and Gaussian likelihood with noise variance σ2\sigma^2, where λ=σ2/τ2\lambda = \sigma^2/\tau^2. Compute the ridge solution for a chosen (σ2,τ2)(\sigma^2, \tau^2) and confirm it matches the direct ridge solve with that λ\lambda.

Solution
python · numpy
import numpy as np

rng = np.random.default_rng(0)
n, d = 40, 8
X = rng.normal(size=(n, d))
beta_true = rng.normal(size=d)
sigma2 = 0.25                                  # likelihood noise variance
y = X @ beta_true + np.sqrt(sigma2) * rng.normal(size=n)

tau2 = 2.0                                      # prior variance on beta
lam = sigma2 / tau2                             # the MAP <-> ridge bridge

# Ridge solve with lambda = sigma^2 / tau^2.
beta_ridge = np.linalg.solve(X.T @ X + lam * np.eye(d), X.T @ y)

# MAP: minimize (1/sigma^2)||y - Xb||^2 + (1/tau^2)||b||^2. Multiplying the
# normal equations through by sigma^2 gives exactly the ridge system above.
A = (X.T @ X) / sigma2 + np.eye(d) / tau2
b = (X.T @ y) / sigma2
beta_map = np.linalg.solve(A, b)

print("lambda = sigma^2 / tau^2 =", round(lam, 4))
assert np.allclose(beta_ridge, beta_map)
print("ridge == MAP:", np.allclose(beta_ridge, beta_map))

The MAP estimate under the Gaussian prior and the ridge solution with λ=σ2/τ2\lambda = \sigma^2/\tau^2 coincide to machine precision: regularization strength is the ratio of noise variance to prior variance, so a tighter prior (small τ2\tau^2) means a larger λ\lambda.

The next lesson swaps the L2 penalty for L1 and gets sparsity instead of shrinkage.


References

  1. [1]Hoerl, A. E., & Kennard, R. W. (1970). "Ridge regression: biased estimation for nonorthogonal problems". Technometrics, 12(1), 55-67. doi:10.1080/00401706.1970.10488634↩
  2. [2]Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning (2nd ed.), §3.4. Springer. doi:10.1007/978-0-387-84858-7. SVD shrinkage view and the Gaussian-prior (MAP) reading.↩