Skip to main content

Linear Regression

Every model in this knowledge base is measured against linear regression, and for good reason: it's the only widely-used model whose optimum you can write down in one line, no iteration required. Understanding exactly why that's possible — and exactly when it stops being possible — is the fastest way to understand the rest of classical ML.

Key idea

Fitting a line is solving a convex least-squares problem — there is exactly one answer, and you can write it down in closed form.

A fitted regression line with vertical residual segments drawn to each point, and the corresponding residual plot
Least squares minimises the sum of the squared vertical distances — the grey segments. Squaring is what makes distant points dominate the fit, and why a single outlier can tilt the whole line.

The model

y^=Xw+b\hat y = Xw + b

Each prediction is a weighted sum of features plus a bias term. In matrix form, absorbing bb into ww by adding a constant column of ones to XX, this is just y^=Xw\hat y = Xw.

Least squares objective

L(w)=1nXwy22=1ni(xiwyi)2L(w) = \frac{1}{n}\|Xw - y\|_2^2 = \frac{1}{n}\sum_i (x_i^\top w - y_i)^2

This is exactly the MSE loss from Loss Functions, and it is convex in ww — a single global minimum, no local minima to worry about.

The normal equation, derived

Setting the gradient to zero:

wL(w)=2nX(Xwy)=0    XXw=Xy    w=(XX)1Xy\nabla_w L(w) = \frac{2}{n}X^\top(Xw - y) = 0 \;\Rightarrow\; X^\top X w = X^\top y \;\Rightarrow\; w^* = (X^\top X)^{-1}X^\top y
SymbolMeaning
XXdesign matrix, one row per example, one column per feature (plus a bias column)
wwweight vector
yytargets
(XX)1X(X^\top X)^{-1}X^\topthe pseudo-inverse of XX, from Linear Algebra

Why gradient descent is still used

The normal equation requires inverting XXX^\top X, a d×dd \times d matrix — cost O(d3)O(d^3). For millions of features, or when XXX^\top X is singular (perfectly collinear features), the closed form is infeasible or undefined, and Gradient Descent becomes the practical choice.

Assumptions and what breaks when they fail

Four scatter plots with visibly different shapes that all share the same fitted line and summary statistics
Anscombe's quartet: four datasets with identical means, variances, correlation and regression line. Summary statistics alone cannot tell them apart — which is the entire argument for plotting your data first.
  • Linearity: the true relationship is (approximately) linear in the features — fails on curved relationships, fixed by polynomial features below.
  • Independence: errors aren't correlated across examples — fails for time series with autocorrelated residuals.
  • Homoscedasticity: constant error variance — fails when noise grows with the magnitude of yy (visible as a funnel in a residual plot, see Evaluation Metrics for Regression).
  • Normal residuals: needed for classical confidence intervals on coefficients, not for the point estimate itself.

Multicollinearity and the condition number

When features are highly correlated, XXX^\top X is nearly singular — its inverse becomes numerically unstable, and small changes in the data produce wildly different coefficient estimates even though predictions barely change. The condition number of XXX^\top X (ratio of largest to smallest eigenvalue) quantifies this instability; Regularization: Ridge, Lasso, Elastic Net is the standard fix.

Polynomial and basis expansion

Linear regression on engineered features [x,x2,x3,][x, x^2, x^3, \ldots] can fit curves while the model itself remains linear in its parameters — the "linear" in linear regression refers to linearity in ww, not in xx.

Interpreting coefficients (and the units trap)

A coefficient wiw_i says "holding all other features fixed, a one-unit increase in feature ii changes y^\hat y by wiw_i." The trap: comparing raw coefficient magnitudes across features with different units (dollars vs. years) is meaningless — standardise features first if you want to compare their relative importance.

Residual diagnostics

Plot residuals against fitted values and against each feature. A random scatter around zero confirms the assumptions; a curved pattern means missing non-linearity; a funnel shape means heteroscedasticity.

Code: normal equation vs. gradient descent, and multicollinearity's instability

linear_regression_demo.py
import numpy as np
from sklearn.linear_model import LinearRegression

rng = np.random.default_rng(0)
n, d = 200, 3
X = rng.normal(size=(n, d))
true_w = np.array([2.0, -1.0, 0.5])
y = X @ true_w + rng.normal(scale=0.1, size=n)

# --- Normal equation ---
X_bias = np.hstack([X, np.ones((n, 1))])
w_closed = np.linalg.pinv(X_bias.T @ X_bias) @ X_bias.T @ y
print("normal equation weights (+bias):", w_closed)

# --- Gradient descent ---
def gd_fit(X, y, lr=0.05, steps=500):
w = np.zeros(X.shape[1])
for _ in range(steps):
w -= lr * (2 / len(y)) * X.T @ (X @ w - y)
return w

w_gd = gd_fit(X_bias, y)
print("gradient descent weights (+bias):", w_gd, " <- should match normal equation")

# --- sklearn, for comparison ---
sk_model = LinearRegression().fit(X, y)
print("sklearn:", sk_model.coef_, sk_model.intercept_)

# --- Multicollinearity: near-duplicate features destabilise coefficients ---
X_collinear = np.hstack([X, X[:, [0]] + rng.normal(scale=1e-3, size=(n, 1))]) # near-copy of col 0
for trial in range(3):
noise = rng.normal(scale=1e-4, size=X_collinear.shape)
w_unstable = np.linalg.pinv((X_collinear + noise).T @ (X_collinear + noise)) @ (X_collinear + noise).T @ y
print(f"trial {trial}, tiny perturbation -> coefficients: {w_unstable}")

The multicollinearity block is the point: adding a near-duplicate column and perturbing the data by a tiny amount produces wildly different coefficient estimates each trial — direct evidence of the instability, even though predictions on held-out data barely change.

When to reach for this

Data sizeany, scales well
Feature countlow-to-moderate without regularisation, any with it
Interpretabilityhighest of any model family
Training costO(d3)O(d^3) closed form, or cheap with gradient descent
Inference costone dot product — essentially free

See also