Skip to content
DataLeaf

Posts

Least squares, three ways

The normal equations, QR, and the SVD solve the same problem with very different accuracy. The difference is the square of a condition number.

Linear least squares asks for the coefficients β^\hat\beta that minimize ∥Xβ−y∥2\lVert X\beta - y \rVert_2 for a tall matrix X∈ℝm×pX \in \mathbb{R}^{m \times p}. Setting the gradient to zero gives the normal equations,

X⊤Xβ^=X⊤y, X^\top X \hat\beta = X^\top y,

and in NumPy they take one line:

python
beta = np.linalg.solve(X.T @ X, X.T @ y)

That line is short, fast, and the least accurate of the three standard methods. This note measures how much accuracy it gives up, explains why, and says when the loss does not matter.

An experiment with a known answer

#

Polynomial fitting is the classic way to make a least-squares problem hard. On m=100m = 100 equally spaced points ti∈[0,1]t_i \in [0, 1], the columns 1,t,t2,…,tp−11, t, t^2, \dots, t^{p-1} of the monomial basis look more and more alike as pp grows, and the matrix drifts towards rank deficiency.

To isolate the solver, I chose the right-hand side so that the exact solution is known: β=(1,…,1)\beta = (1, \dots, 1) and y=Xβy = X\beta, with a residual of zero. Any error in β^\hat\beta then comes from floating-point arithmetic, not from the data.

python
import numpy as np

def errors(p, m=100):
    t = np.linspace(0.0, 1.0, m)
    X = np.vander(t, p, increasing=True)
    beta = np.ones(p)
    y = X @ beta
    rel = lambda b: np.linalg.norm(b - beta) / np.linalg.norm(beta)

    normal = np.linalg.solve(X.T @ X, X.T @ y)
    Q, R = np.linalg.qr(X)
    qr = np.linalg.solve(R, Q.T @ y)
    svd = np.linalg.lstsq(X, y, rcond=None)[0]
    return np.linalg.cond(X), rel(normal), rel(qr), rel(svd)

np.linalg.qr computes a Householder factorization, and np.linalg.lstsq calls LAPACK’s SVD-based solver. The relative errors in the coefficients:

Columns ppCondition number κ(X)\kappa(X)Normal equationsQRSVD
41.2×1021.2 \times 10^{2}9.4×10−139.4 \times 10^{-13}3.9×10−153.9 \times 10^{-15}2.0×10−152.0 \times 10^{-15}
63.7×1033.7 \times 10^{3}1.1×10−101.1 \times 10^{-10}8.8×10−148.8 \times 10^{-14}7.3×10−147.3 \times 10^{-14}
81.2×1051.2 \times 10^{5}7.5×10−87.5 \times 10^{-8}4.1×10−124.1 \times 10^{-12}3.7×10−123.7 \times 10^{-12}
103.7×1063.7 \times 10^{6}3.0×10−53.0 \times 10^{-5}1.8×10−101.8 \times 10^{-10}6.3×10−116.3 \times 10^{-11}
121.2×1081.2 \times 10^{8}1.9×10−11.9 \times 10^{-1}6.9×10−106.9 \times 10^{-10}5.3×10−95.3 \times 10^{-9}

With twelve columns the normal equations return coefficients that are wrong in the first digit, while QR and the SVD still agree with the truth to eight or nine digits. Plotting every pp from 2 to 14 against the condition number shows two straight lines with different slopes.

Relative error of the three methods against the condition number of X, on logarithmic axes. The normal equations follow the square of the condition number; QR and the SVD follow the condition number itself.
Figure 1. Relative error in the coefficients against the condition number κ(X). Dashed guides show κu and κ²u, with u = 2⁻⁵³.

Why the normal equations lose twice as many digits

#

The condition number κ2(A)=σmax⁡(A)/σmin⁡(A)\kappa_2(A) = \sigma_{\max}(A) / \sigma_{\min}(A) measures how much a matrix can amplify relative perturbations. Forming X⊤XX^\top X squares it.

Theorem — Conditioning of the normal equations
If XX has full column rank with singular values σ1≥⋯≥σp>0\sigma_1 \ge \dots \ge \sigma_p > 0, then κ2(X⊤X)=κ2(X)2\kappa_2(X^\top X) = \kappa_2(X)^2.
Proof.
Write the thin singular value decomposition X=UΣV⊤X = U \Sigma V^\top, where UU has orthonormal columns. Then X⊤X=VΣ2V⊤X^\top X = V \Sigma^2 V^\top, a symmetric positive definite matrix whose eigenvalues, and so whose singular values, are σ12,…,σp2\sigma_1^2, \dots, \sigma_p^2. Hence κ2(X⊤X)=σ12/σp2=κ2(X)2\kappa_2(X^\top X) = \sigma_1^2 / \sigma_p^2 = \kappa_2(X)^2.
End of proof

A backward-stable solver for a square system with matrix AA returns a solution with relative error of order κ(A) u\kappa(A)\,u, where u=2−53≈1.1×10−16u = 2^{-53} \approx 1.1 \times 10^{-16} is the unit roundoff of double precision. Solving the normal equations is such a solve with A=X⊤XA = X^\top X. Householder QR and the SVD never form that product: they work on XX itself, and for a problem with a small residual their error is of order κ(X) u\kappa(X)\,u.1

∥β^−β∥∥β∥≈{κ(X)2 unormal equations,κ(X) uQR and SVD, small residual. \frac{\lVert \hat\beta - \beta \rVert}{\lVert \beta \rVert} \approx \begin{cases} \kappa(X)^2\, u & \text{normal equations,} \\ \kappa(X)\, u & \text{QR and SVD, small residual.} \end{cases}

The estimates are upper bounds up to modest constants, and the measured errors sit at or below the dashed guides in the figure. Each factor of ten in κ(X)\kappa(X) costs QR about one decimal digit and the normal equations about two.

When the residual is large, even the best algorithm inherits a term proportional to κ(X)2\kappa(X)^2 times the relative size of the residual. That term belongs to the problem, not to the method, so no choice of solver removes it.2

When the normal equations are fine

#

None of this makes the normal equations wrong. They are the right tool more often than the table suggests.

  • The matrix is well conditioned. With κ(X)=100\kappa(X) = 100, the normal equations lose about four digits and still deliver twelve. Standardized predictors with little collinearity are often in this range.
  • The data do not fit in memory. X⊤XX^\top X and X⊤yX^\top y can be accumulated in one pass over the rows, in p×pp \times p storage, and solved at the end.
  • Speed matters more than the last digits. For m≫pm \gg p, forming X⊤XX^\top X costs about mp2m p^2 operations; Householder QR costs about 2mp22 m p^2.

Change the basis before changing the solver

#

The cheapest fix is often in the model rather than the algorithm. The monomials tkt^k on [0,1][0, 1] are a notoriously poor basis. Moving the same points to [−1,1][-1, 1] brings the condition number of the twelve-column matrix from 1.2×1081.2 \times 10^{8} down to 6.9×1036.9 \times 10^{3}, and a Chebyshev basis on [−1,1][-1, 1] brings it to 2.92.9. At that point all three methods agree to the last digit, and the normal equations are as good as any.

The general lesson is that accuracy is decided twice: once when the problem is posed, by the condition number, and once when it is solved, by whether the algorithm squares it.


  1. Lloyd N. Trefethen and David Bau III, Numerical Linear Algebra (SIAM, 1997), Lectures 18 and 19, analyse the conditioning of least-squares problems and the stability of these three algorithms. ↩︎

  2. Nicholas J. Higham, Accuracy and Stability of Numerical Algorithms, 2nd edition (SIAM, 2002), Chapter 20, gives the perturbation theory, including the residual term. ↩︎