Home / LA 101 / Module 7 / Lesson 2
Stories Mode

QR Decomposition

Factor any matrix A into an orthogonal Q and an upper triangular R. QR decomposition is the numerical backbone of least-squares solvers and eigenvalue algorithms — and it is far more numerically stable than the normal equations approach.

~18 min read M7 · L2 Intermediate

What is QR Decomposition?

Every matrix A with linearly independent columns can be factored into a product A = QR, where Q has orthonormal columns and R is upper triangular with positive diagonal entries. This factorization exists for any m × n matrix with m ≥ n and rank n — that is, for any matrix whose columns are linearly independent. Unlike LU decomposition, which requires a square matrix, QR works for tall rectangular matrices too, making it the natural tool for overdetermined least-squares problems.

The orthogonal factor Q captures the geometry of A's column space: its columns form an orthonormal basis for that space. The upper triangular factor R captures the "scaling and shearing" needed to go from the standard orthonormal basis to A's actual columns. Together they encode everything about A in a form that is exceptionally well-conditioned for numerical computation.

QR decomposition appears in three major applications: solving least-squares problems, computing eigenvalues via the QR algorithm, and orthogonalizing a set of vectors. In all three, the orthogonality of Q is the key — it means Q⁻¹ = Qᵀ, so matrix-vector products with Q or Qᵀ are perfectly conditioned and can never amplify errors.

The Q and R Factors

For an m × n matrix A with m ≥ n and linearly independent columns, the QR factorization writes A = QR where:

QR Factorization
A = QR, \quad Q^T Q = I_n, \quad R = \begin{pmatrix} r_{11} & r_{12} & \cdots & r_{1n} \\ 0 & r_{22} & \cdots & r_{2n} \\ \vdots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & r_{nn} \end{pmatrix}, \quad r_{kk} > 0
A is m × n, Q is m × n with orthonormal columns (QᵀQ = Iₙ), and R is n × n upper triangular with positive diagonal. The columns of Q form an orthonormal basis for the column space of A. When m = n, Q is a square orthogonal matrix (QQᵀ = QᵀQ = I) and A = QR is the full factorization.

There is also a "full" QR factorization where Q is extended to a full m × m orthogonal matrix by appending m − n additional orthonormal columns (spanning the left null space of A), and R is extended to an m × n matrix by padding with rows of zeros. Both forms are useful, but the "thin" or "economy" QR (with Q being m × n) is the one most commonly used in practice.

Computing QR: Gram-Schmidt Process

The conceptually simplest way to compute QR is the Gram-Schmidt process, which directly constructs the orthonormal columns of Q one at a time. Recall from Module 5 that Gram-Schmidt takes a set of linearly independent vectors and produces an orthonormal basis for their span. Applied to the columns a₁, a₂, …, aₙ of A, it produces the columns q₁, q₂, …, qₙ of Q.

The process is iterative. At step k, we take aₖ, subtract off its projections onto all previously constructed basis vectors q₁, …, q_{k−1}, and normalize the remainder:

Gram-Schmidt Step
\tilde{e}_k = a_k - \sum_{i=1}^{k-1}(q_i^T a_k)\,q_i, \quad q_k = \frac{\tilde{e}_k}{\|\tilde{e}_k\|}, \quad r_{ik} = q_i^T a_k,\; r_{kk} = \|\tilde{e}_k\|
At each step k, form the residual ẽₖ by subtracting from aₖ its projections onto all previous q₁, …, q_{k−1}. Then normalize: qₖ = ẽₖ / ‖ẽₖ‖. The entries rᵢₖ = qᵢᵀaₖ fill the k-th column of R above the diagonal, and rₖₖ = ‖ẽₖ‖ fills the diagonal. The result is A = QR.

Reading off the entries of R from the Gram-Schmidt steps: the diagonal entry rₖₖ = ‖ẽₖ‖ is the norm of the residual at step k, and the off-diagonal entries rᵢₖ = qᵢᵀaₖ are the projection coefficients. The column a₁, a₂, …, aₙ can be recovered from q₁, q₂, …, qₙ via the upper triangular matrix R, confirming that A = QR.

Classical vs. Modified Gram-Schmidt

The classical Gram-Schmidt process as described above is mathematically correct but numerically unstable when run in floating-point arithmetic: rounding errors in the projection steps can cause the computed vectors to lose orthogonality, especially when columns are nearly parallel. The modified Gram-Schmidt reorders the projections to subtract each projection as soon as it is computed, rather than all at once. It produces the same result in exact arithmetic but is much more numerically stable, because errors introduced in one projection do not propagate into subsequent ones.

For most practical work, the modified Gram-Schmidt process offers a good balance of simplicity and numerical quality. But when very high accuracy is required — as in eigenvalue computation — Householder reflections provide even stronger guarantees.

Computing QR: Householder Reflections

The Householder reflection approach is the method used in production numerical libraries (LAPACK, NumPy, MATLAB). Instead of building Q column by column as in Gram-Schmidt, it builds Q as a product of elementary orthogonal matrices applied from the left to A.

A Householder reflector H is an orthogonal, symmetric matrix of the form H = I − 2vvᵀ / (vᵀv), where v is called the Householder vector. Geometrically, H reflects any vector across the hyperplane perpendicular to v. By choosing v appropriately at each step, we can zero out all entries below the diagonal in a given column of A.

Householder Reflector
H = I - \frac{2vv^T}{v^T v}, \quad H^T H = I, \quad H^2 = I, \quad Hx = \|x\|\,e_1
The Householder matrix H = I − 2vvᵀ/(vᵀv) is orthogonal (HᵀH = I) and symmetric (H = Hᵀ), so H² = I. The vector v is chosen so that Hx = ‖x‖e₁ for a given target vector x — that is, H reflects x onto the first coordinate axis, zeroing all other components. Applying n such reflections H₁, H₂, …, Hₙ from the left to A eventually produces R = Hₙ⋯H₁A, and then Q = H₁⋯Hₙ.

The Householder approach has two key advantages over Gram-Schmidt. First, it is numerically stable: each Householder reflector is an exact orthogonal transformation, so no orthogonality is lost due to rounding. Second, it is efficient: working with vvᵀ implicitly (without forming the full n×n matrix H) makes each step cost O(mn) rather than O(mn²). In practice, LAPACK stores the Householder vectors and applies them lazily, making the overall factorization cost about 2mn² − 2n³/3 flops.

Computing QR: Givens Rotations

A third approach builds Q as a product of Givens rotations — elementary orthogonal matrices that rotate two coordinates at a time. A Givens rotation G(i, j, θ) affects only rows i and j, rotating them by angle θ so that a target entry becomes zero. This is the surgical scalpel version: while Householder reflections zero out an entire column below the diagonal in one step, Givens rotations zero out one entry at a time.

Givens rotations shine when A is sparse: if most entries of A are already zero, it is wasteful to apply a full Householder reflector (which modifies the entire column). Givens rotations touch only the two rows involved in each zero-creation, preserving sparsity much better. They are the method of choice for banded matrices and for updating an existing QR factorization when one row of A changes.

Application: Least-Squares via QR

The primary motivation for QR decomposition in applications is solving overdetermined least-squares problems: given an m × n matrix A with m > n and a vector b ∈ ℝᵐ, find x ∈ ℝⁿ that minimizes ‖Ax − b‖².

The standard approach — the normal equations AᵀAx = Aᵀb — computes AᵀA, which doubles the condition number of the problem (κ(AᵀA) = κ(A)²) and can be catastrophically inaccurate when A is ill-conditioned. The QR approach avoids forming AᵀA entirely.

Least Squares via QR
\min_x \|Ax - b\|^2 = \min_x \|QRx - b\|^2 \;\Rightarrow\; Rx = Q^T b \text{ (back substitution)}
Substitute A = QR into ‖Ax − b‖² = ‖QRx − b‖². Since Q has orthonormal columns, left-multiplying by Qᵀ preserves norms: ‖QRx − b‖² = ‖Rx − Qᵀb‖² + ‖(I − QQᵀ)b‖². The second term is fixed, so minimizing over x requires solving the upper triangular system Rx = Qᵀb by back substitution — O(n²) work after the factorization.

The QR approach costs 2mn² − 2n³/3 flops to factorize (compared to mn² for forming AᵀA and n³/3 for its Cholesky factorization), but the reduction in condition number from κ(A)² to κ(A) is usually worth the extra cost. When A is nearly rank-deficient or the data is noisy, the QR approach can give correct answers where the normal equations produce garbage.

Application: The QR Algorithm for Eigenvalues

QR decomposition is also the engine of the most widely used algorithm for computing all eigenvalues of a matrix: the QR algorithm (not to be confused with QR decomposition itself). The basic iteration is remarkably simple:

  1. Start with A₀ = A.
  2. At each step k: compute the QR factorization Aₖ = QₖRₖ.
  3. Form Aₖ₊₁ = RₖQₖ (reverse the product).
  4. Repeat until Aₖ converges to an upper triangular (or nearly triangular) matrix.
QR Iteration
A_k = Q_k R_k \;\Rightarrow\; A_{k+1} = R_k Q_k = Q_k^T A_k Q_k \quad (\text{similar to } A)
The sequence A₀, A₁, A₂, … converges to an upper triangular (Schur) form whose diagonal entries are the eigenvalues of A. All matrices in the sequence are similar to A₀ = A (because Aₖ₊₁ = RₖQₖ = Qₖᵀ(QₖRₖ)Qₖ = QₖᵀAₖQₖ), so they share the same eigenvalues. In practice, the iteration is accelerated with shifts and deflation to converge in O(n) steps rather than O(n²).

The QR algorithm with shifts is the method of choice for dense eigenvalue problems and is implemented in LAPACK's dgeev (general matrices) and dsyev (symmetric matrices). For symmetric matrices, the sequence converges to a diagonal matrix, directly revealing all eigenvalues. The QR algorithm requires O(n³) work per iteration but typically converges in O(1) iterations per eigenvalue after deflation, giving an overall cost of O(n³).

Numerical Stability: Why QR Beats the Normal Equations

The condition number of a linear system measures how much the solution can change relative to perturbations in the data. For the least-squares problem min ‖Ax − b‖², the relevant condition number is κ(A) — the ratio of the largest to smallest singular value of A. Solving via the normal equations introduces AᵀA, whose condition number is κ(A)². This squaring can be catastrophic: if κ(A) = 10⁶ (a mild degree of ill-conditioning for real data), then κ(AᵀA) = 10¹², and about 12 digits of accuracy are lost before you even start solving.

QR decomposition avoids this squaring. Because Q is orthogonal, the system Rx = Qᵀb has condition number κ(R) = κ(A), not κ(A)². The transformation Qᵀb cannot make anything worse — orthogonal transformations preserve all lengths and angles exactly. This is the fundamental reason why QR decomposition is the preferred method for least-squares computation in any numerically sensitive application.

Condition Number Comparison
\kappa(A^T A) = \kappa(A)^2 \gg \kappa(R) = \kappa(A)
The condition number of the normal equations AᵀA is κ(AᵀA) = κ(A)², while the condition number of the QR system Rx = Qᵀb is κ(R) = κ(A). For ill-conditioned data matrices, the QR approach loses only half as many digits of accuracy as the normal equations approach.

Engineering Implication

QR decomposition is the algorithm behind numpy.linalg.lstsq, MATLAB's backslash operator for overdetermined systems, and scipy.linalg.qr. Whenever you fit a model to data — linear regression, polynomial fitting, exponential fitting — you are solving a least-squares problem, and a well-implemented solver uses QR decomposition. The QR algorithm for eigenvalues is the engine of numpy.linalg.eig, scipy.linalg.eigh, and every structural vibration analysis and quantum chemistry code that needs eigenvalues of dense matrices. In signal processing, QR-based algorithms appear in adaptive filtering (RLS), direction-of-arrival estimation (MUSIC algorithm), and beamforming — wherever a covariance matrix must be updated incrementally and efficiently.

Key Takeaways

QR decomposition factors A = QR into an orthogonal Q and an upper triangular R. It can be computed via Gram-Schmidt (conceptually clear, modified version numerically acceptable), Householder reflections (numerically stable, used in LAPACK), or Givens rotations (best for sparse or banded matrices). For least-squares problems, QR avoids squaring the condition number: solving Rx = Qᵀb costs only κ(A) in condition versus κ(A)² for the normal equations. The QR algorithm — iteratively computing QR factorizations and reversing the product — converges to the eigenvalues of any matrix, making QR decomposition the backbone of dense eigenvalue computation worldwide.