Neural Mastery

Ridge Regression, In Full Depth

Ordinary linear regression (see Linear Regression) has a failure mode: when features are highly correlated, or there are more features than examples, (XTX)1(X^TX)^{-1} becomes unstable — small changes in the data cause huge swings in the fitted weights. Ridge regression fixes this by penalizing large weights directly in the loss function.

What Is Ridge Regression?

Ridge is linear regression with one addition: a penalty term that discourages weights from growing large. The hypothesis is identical to plain linear regression — y^=wTx+b\hat{y} = \mathbf{w}^T\mathbf{x} + b — only the cost function changes.

Why penalize large weights at all? A model with huge, wildly-swinging coefficients has usually latched onto noise in the training data rather than a real signal — a hallmark of overfitting (see Model Evaluation & Metrics — Bias-Variance Tradeoff). Shrinking the weights trades a small amount of bias for a large reduction in variance, which usually wins on unseen data.

The Ridge Cost Function

Jridge(w,b)=1ni=1n(y^(i)y(i))2same MSE as OLS+λj=1dwj2L2 penaltyJ_{\text{ridge}}(\mathbf{w}, b) = \underbrace{\frac{1}{n}\sum_{i=1}^n \left(\hat{y}^{(i)} - y^{(i)}\right)^2}_{\text{same MSE as OLS}} + \underbrace{\lambda \sum_{j=1}^d w_j^2}_{\text{L2 penalty}}

The first term is exactly the MSE cost function from plain linear regression. The second term — λwj2\lambda \sum w_j^2, the squared L2 norm of the weight vector (see Linear Algebra — Norms) — is new. λ0\lambda \geq 0 controls the tradeoff: λ=0\lambda = 0 recovers plain OLS exactly; larger λ\lambda shrinks weights more aggressively toward zero. Note the bias bb is not penalized — only shrinking the feature weights makes sense, since bb just sets the overall output level.

Deriving the Gradient

The MSE part of the gradient is unchanged from Linear Regression — Section 3. The new penalty term adds wj(λwj2)=2λwj\frac{\partial}{\partial w_j}\left(\lambda w_j^2\right) = 2\lambda w_j:

Jridgewj=2ni=1n(y^(i)y(i))xj(i)OLS gradient+2λwj\frac{\partial J_{\text{ridge}}}{\partial w_j} = \underbrace{\frac{2}{n}\sum_{i=1}^n \left(\hat{y}^{(i)} - y^{(i)}\right) x_j^{(i)}}_{\text{OLS gradient}} + 2\lambda w_j

The gradient descent update becomes:

wjwjα(2ni(y^(i)y(i))xj(i)+2λwj)=wj(12αλ)α(OLS gradient term)w_j \leftarrow w_j - \alpha\left(\frac{2}{n}\sum_i \left(\hat{y}^{(i)} - y^{(i)}\right)x_j^{(i)} + 2\lambda w_j\right) = w_j(1 - 2\alpha\lambda) - \alpha \cdot (\text{OLS gradient term})

Written this way, the mechanism is obvious: every single update step first shrinks wjw_j by a factor of (12αλ)(1 - 2\alpha\lambda) before applying the usual OLS correction. This is why ridge is sometimes called "weight decay" in the deep learning literature (see Training Deep Networks — Regularization) — it's the exact same mechanism.

The Closed-Form Solution

Ridge has a closed form too, a small modification of the normal equation:

w=(XTX+λI)1XTy\mathbf{w} = (X^TX + \lambda I)^{-1}X^T\mathbf{y}

This is why ridge regression exists mathematically, not just statistically: adding λI\lambda I to XTXX^TX before inverting guarantees the matrix is invertible, even when XTXX^TX alone is singular or near-singular (highly correlated features, or more features than examples). Plain OLS can fail outright in that situation; ridge never does, for any λ>0\lambda > 0.

The Regularization Path

As λ\lambda increases from 0, every weight shrinks smoothly toward zero — but critically, never exactly reaches zero (except in the limit λ\lambda \to \infty):

Ridge regularization path — coefficients shrink smoothly toward zero as regularization strength increases

Compare this to Lasso's path — the visual difference between the two curves is the core conceptual difference between L2 and L1 regularization.

Predict First
In the Studio below, set λ=0 and push Correlation to ~0.98. What happens to x1's and x2's individual coefficients?

Try it on a real (small, synthetic) multicollinear dataset — drag λ\lambda from 0 and watch two deliberately correlated features fight over shared credit, then settle down:

Interactive
Ridge Regression Studio
x1 = 2.20x2 = 3.80x3 = 0.05x4 = 1.65
MSE 1.522x1 + x2 = 6.01 (true combined effect ≈ 6.0)
Drag λ to 0 (plain OLS) and push Correlation up -- watch x1 and x2 swing individually while their sum barely moves. Now increase λ and watch them settle toward each other, with MSE barely changing.
A real 4-feature synthetic dataset (x1 and x2 deliberately correlated) and a real, from-scratch closed-form ridge solve -- w(lambda) = (X^TX + lambda*P)^-1 X^Ty -- recomputed live as you move lambda.

Choosing λ

λ\lambda is a hyperparameter, not learned from the training data directly — it's chosen via cross-validation (see ML Workflow Fundamentals): train with several candidate λ\lambda values, and pick whichever generalizes best on a held-out validation set.

When to Use Ridge

  • Many correlated features (ridge handles multicollinearity gracefully — plain OLS coefficients become unstable, ridge's don't)
  • More features than examples, or close to it
  • You want to keep all features in the model, just with controlled magnitude (contrast with Lasso, which drops features entirely)

Minimal Implementation

import numpy as np

def fit_ridge(X, y, lam=1.0, lr=0.01, epochs=1000):
    n, d = X.shape
    w = np.zeros(d)
    b = 0.0
    for _ in range(epochs):
        y_hat = X @ w + b
        error = y_hat - y
        dw = (2 / n) * X.T @ error + 2 * lam * w   # OLS gradient + ridge penalty
        db = (2 / n) * np.sum(error)                # bias is never penalized
        w -= lr * dw
        b -= lr * db
    return w, b

# Closed form, for comparison
def fit_ridge_normal_equation(X, y, lam=1.0):
    d = X.shape[1]
    return np.linalg.inv(X.T @ X + lam * np.eye(d)) @ X.T @ y

Next: Lasso Regression — the L1 alternative that drops features entirely instead of just shrinking them.

Last updated Sep 5, 2026Edit this pageReport an issue
← Previous
Linear Regression, In Full Depth
Next →
Lasso Regression, In Full Depth