AI Knowledge Tree

Least squares & the Moore–Penrose pseudo-inverse

Derive the normal equations from the residual, interpret the solution as a projection, and build the pseudo-inverse from the SVD.

Most real systems are overdetermined: more equations than unknowns, and no exact solution exists. The least-squares criterion picks the xx that makes AxAx as close to bb as possible, and the geometry is a projection.

The least-squares problem

Given A∈Rm×nA \in \mathbb{R}^{m \times n} with m>nm > n and b∈Rmb \in \mathbb{R}^m, find

x^=arg⁡min⁡x∈Rn∥Ax−b∥22.\hat{x} = \arg\min_{x \in \mathbb{R}^n} \lVert Ax - b\rVert_2^2.

The objective ∥Ax−b∥2\lVert Ax - b\rVert^2 is a quadratic in xx (it opens up: A⊤AA^\top A is PSD). Its minimum is where the gradient is zero.

Derivation via the gradient

Expand:

∥Ax−b∥2=x⊤A⊤Ax−2b⊤Ax+b⊤b.\lVert Ax - b\rVert^2 = x^\top A^\top A x - 2b^\top Ax + b^\top b.

Taking the gradient with respect to xx and setting it to zero:

∇x∥Ax−b∥2=2A⊤Ax−2A⊤b=0,\nabla_x \lVert Ax - b\rVert^2 = 2A^\top A x - 2A^\top b = 0,

giving the normal equations:[1]

A⊤A x^=A⊤b.A^\top A\, \hat{x} = A^\top b.

If AA has full column rank (nn), A⊤AA^\top A is invertible, and the unique solution is x^=(A⊤A)−1A⊤b\hat{x} = (A^\top A)^{-1} A^\top b.

Geometric interpretation

Ax^A\hat{x} is the projection of bb onto col⁡(A)\operatorname{col}(A): it is the point in the column space closest to bb. The residual r=b−Ax^r = b - A\hat{x} is orthogonal to every column of AA:

A⊤(b−Ax^)=A⊤b−A⊤Ax^=0,A^\top(b - A\hat{x}) = A^\top b - A^\top A\hat{x} = 0,

which is exactly the normal equations rewritten. The projection matrix onto col⁡(A)\operatorname{col}(A) is

P=A(A⊤A)−1A⊤,P2=P,P⊤=P.P = A(A^\top A)^{-1}A^\top, \qquad P^2 = P, \quad P^\top = P.

Any symmetric idempotent matrix is a projection; these two properties characterize projections completely.

Numerical route: QR is preferable

Forming A⊤AA^\top A squares the condition number: κ(A⊤A)=κ(A)2\kappa(A^\top A) = \kappa(A)^2. The QR route avoids this. Write A=QRA = QR (thin QR, Q∈Rm×nQ \in \mathbb{R}^{m \times n}, R∈Rn×nR \in \mathbb{R}^{n \times n} upper triangular). The normal equations become

R⊤Q⊤QRx^=R⊤Q⊤b  ⟹  Rx^=Q⊤b,R^\top Q^\top Q R\hat{x} = R^\top Q^\top b \implies R\hat{x} = Q^\top b,

a triangular system solved by backward substitution.

The Moore–Penrose pseudo-inverse

When AA does not have full column rank, the normal equations have infinitely many solutions. The minimum-norm solution (smallest ∥x∥2\lVert x\rVert_2 among all minimizers of ∥Ax−b∥2\lVert Ax - b\rVert_2) is given by the Moore–Penrose pseudo-inverse A+A^+[2]:

x^=A+b.\hat{x} = A^+ b.

Construction from SVD. Let A=UΣV⊤A = U\Sigma V^\top with rank rr. Define

A+=VΣ+U⊤,A^+ = V\Sigma^+ U^\top,

where Σ+\Sigma^+ replaces each nonzero singular value σi\sigma_i by 1/σi1/\sigma_i and leaves zeros alone.

Properties:

  • If AA has full column rank: A+=(A⊤A)−1A⊤A^+ = (A^\top A)^{-1}A^\top (the standard formula).
  • If AA has full row rank: A+=A⊤(AA⊤)−1A^+ = A^\top(AA^\top)^{-1} (a right inverse).
  • AA+A=AA A^+ A = A, A+AA+=A+A^+ A A^+ = A^+, and both AA+A A^+ and A+AA^+ A are symmetric.
Least squares projects the target b orthogonally onto the column space; the residual is perpendicular to it, which is exactly the normal equations.
Least squares projects the target b orthogonally onto the column space; the residual is perpendicular to it, which is exactly the normal equations.

Check it on arrays

python · numpy
import numpy as np

rng = np.random.default_rng(7)

m, n = 50, 5
A = rng.normal(size=(m, n))
b = rng.normal(size=m)

# Normal equations (full column rank here)
ATA = A.T @ A
ATb = A.T @ b
x_normal = np.linalg.solve(ATA, ATb)

# QR route (numerically preferable)
Q, R = np.linalg.qr(A)
x_qr = np.linalg.solve(R, Q.T @ b)

# Built-in lstsq (uses SVD internally)
x_lstsq, _, _, _ = np.linalg.lstsq(A, b, rcond=None)

print("normal eq residual:", np.linalg.norm(A @ x_normal - b))
print("QR residual:", np.linalg.norm(A @ x_qr - b))
print("lstsq residual:", np.linalg.norm(A @ x_lstsq - b))   # same
print("solutions agree:", np.allclose(x_qr, x_lstsq, atol=1e-10))

# Pseudo-inverse via SVD: also handles rank-deficient A
U, s, Vt = np.linalg.svd(A, full_matrices=False)
A_plus = Vt.T @ np.diag(1.0 / s) @ U.T
x_pinv = A_plus @ b
print("pinv agrees with lstsq:", np.allclose(x_pinv, x_lstsq, atol=1e-10))

# Residual is orthogonal to col(A):
r = b - A @ x_lstsq
print("A^T r (should be ~0):", np.round(A.T @ r, 8))

All four routes agree on the solution; the residual is orthogonal to every column of AA.

Exercises

Exercise 1. Solve the least-squares problem with A=(111)A = \begin{pmatrix} 1 \\ 1 \\ 1 \end{pmatrix} and b=(246)b = \begin{pmatrix} 2 \\ 4 \\ 6 \end{pmatrix} by the normal equations, and state what the scalar x^\hat{x} represents geometrically.

Solution

Step 1. Form the normal equation A⊤A x^=A⊤bA^\top A\,\hat{x} = A^\top b. Here A⊤A=1+1+1=3A^\top A = 1 + 1 + 1 = 3 and A⊤b=2+4+6=12A^\top b = 2 + 4 + 6 = 12.

Step 2. Solve the scalar equation:

3x^=12  ⟹  x^=4.3\hat{x} = 12 \implies \hat{x} = 4.

Step 3. Since the single column of AA is the all-ones vector, Ax^A\hat{x} is the constant vector closest to bb. Projecting onto the all-ones direction returns the mean of the entries of bb, and indeed (2+4+6)/3=4(2 + 4 + 6)/3 = 4. The least-squares fit of a constant to data is the sample mean.

Exercise 2. Show directly from the definition that the projection matrix P=A(A⊤A)−1A⊤P = A(A^\top A)^{-1}A^\top (with AA of full column rank) is idempotent (P2=PP^2 = P) and symmetric (P⊤=PP^\top = P).

Solution

Step 1 (idempotent). Multiply PP by itself and cancel the inner (A⊤A)(A⊤A)−1=I(A^\top A)(A^\top A)^{-1} = I:

P2=A(A⊤A)−1A⊤A(A⊤A)−1⏟= IA⊤=A(A⊤A)−1A⊤=P.P^2 = A(A^\top A)^{-1}\underbrace{A^\top A(A^\top A)^{-1}}_{=\,I}A^\top = A(A^\top A)^{-1}A^\top = P.

Step 2 (symmetric). Transpose, using (XYZ)⊤=Z⊤Y⊤X⊤(XYZ)^\top = Z^\top Y^\top X^\top and the fact that A⊤AA^\top A is symmetric, so its inverse is too:

P⊤=(A(A⊤A)−1A⊤)⊤=A((A⊤A)−1)⊤A⊤=A(A⊤A)−1A⊤=P.P^\top = \left(A(A^\top A)^{-1}A^\top\right)^\top = A\left((A^\top A)^{-1}\right)^\top A^\top = A(A^\top A)^{-1}A^\top = P.

Both properties hold, so PP is an orthogonal projection: applying it once lands in col⁡(A)\operatorname{col}(A), and applying it again changes nothing.

Exercise 3 (code). Build a rank-deficient AA (repeat a column so the column rank is below the number of columns). The normal equations are then singular. Verify that the SVD pseudo-inverse A+bA^+ b still returns a least-squares solution and that, among all minimizers, it has the smallest ℓ2\ell^2 norm.

Solution
python · numpy
import numpy as np

rng = np.random.default_rng(3)
m = 30
c = rng.normal(size=m)
A = np.column_stack([c, 2 * c, rng.normal(size=m)])   # col 2 = 2*col 1: rank 2
b = rng.normal(size=m)

# Pseudo-inverse via SVD (drops the zero singular value).
U, s, Vt = np.linalg.svd(A, full_matrices=False)
tol = 1e-10
s_inv = np.where(s > tol, 1.0 / s, 0.0)
A_plus = Vt.T @ np.diag(s_inv) @ U.T
x_pinv = A_plus @ b

# It minimizes the residual: the residual is orthogonal to col(A).
r = b - A @ x_pinv
assert np.allclose(A.T @ r, 0.0, atol=1e-8)

# Any other minimizer adds a null-space vector; that only grows the norm.
null = Vt[-1]                       # right singular vector with sigma ~ 0
x_other = x_pinv + 0.7 * null
assert np.allclose(A @ x_other, A @ x_pinv, atol=1e-8)   # same fit
assert np.linalg.norm(x_pinv) < np.linalg.norm(x_other)  # pinv is minimum-norm
print("pinv norm:", round(float(np.linalg.norm(x_pinv)), 4),
      "other:", round(float(np.linalg.norm(x_other)), 4))

Adding any multiple of the null-space direction leaves the fit Ax^A\hat{x} untouched but strictly increases ∥x∥2\lVert x\rVert_2, so the pseudo-inverse solution is the unique minimum-norm minimizer.

With overdetermined systems handled, the next lesson builds the calculus for differentiating expressions involving matrices, the prerequisite for understanding backpropagation.


References

  1. [1]Trefethen, L. N., & Bau, D. (1997). Numerical Linear Algebra. SIAM. The normal equations, the projection view, and the QR route to least squares (Lectures 11, 18-19).↩
  2. [2]Golub, G. H., & Van Loan, C. F. (2013). Matrix Computations (4th ed.). Johns Hopkins University Press. The Moore-Penrose pseudo-inverse and its SVD construction (doi:10.56021/9781421407944).↩