6.3 Why Production PCA Uses Singular Value Decomposition (SVD) Instead of Forming XᵀX

If you open the source code of sklearn.decomposition.PCA in Python, prcomp in R, or pca in MATLAB, you will discover something surprising: none of them compute C=1nXTXC = \frac{1}{n}X^T X and call an eigenvalue solver! Instead, they compute the Singular Value Decomposition (SVD) directly on the centered data matrix X=UΣVTX = U \Sigma V^T.

Why do numerical linear algebraists avoid forming XTXX^T X in production software? There are two decisive reasons: floating-point numerical stability (avoiding squaring the condition number) and high-dimensional computational efficiency when d≫nd \gg n.

In this Article

1. The Exact Algebraic Dictionary Between SVD (X = UΣVᵀ) and PCA

Let X∈Rn×dX \in \mathbb{R}^{n \times d} be the centered data matrix with rank r≤min⁡(n,d)r \le \min(n, d). Its thin Singular Value Decomposition is:

X=UΣVT=∑k=1rσkuleft,kvkTX = U \Sigma V^T = \sum_{k=1}^r \sigma_k \mathbf{u}_{\text{left},k} \mathbf{v}_k^T

where U∈Rn×rU \in \mathbb{R}^{n \times r} has orthonormal columns (UTU=IrU^T U = I_r), Σ=diag(σ1,…,σr)\Sigma = \text{diag}(\sigma_1, \dots, \sigma_r) has singular values σ1≥⋯≥σr>0\sigma_1 \ge \dots \ge \sigma_r > 0, and V∈Rd×rV \in \mathbb{R}^{d \times r} has orthonormal columns (VTV=IrV^T V = I_r). Substituting X=UΣVTX = U\Sigma V^T into C=1nXTXC = \frac{1}{n}X^T X gives:

  • Covariance Spectral Form: C=1nVΣUTUΣVT=V(Σ2n)VTC = \frac{1}{n}V\Sigma U^T U \Sigma V^T = V \left(\frac{\Sigma^2}{n}\right) V^T
  • Principal Axes (Eigenvectors of CC): The columns of VV (right singular vectors of XX).
  • Eigenvalues of CC: λk=σk2n\lambda_k = \frac{\sigma_k^2}{n} (or σk2n−1\frac{\sigma_k^2}{n-1} for sample covariance).
  • Projected Principal Component Scores ZZ: Z=XV=(UΣVT)V=UΣZ = X V = (U \Sigma V^T) V = U \Sigma.
  • Rank-kk Approximation (Eckart–Young Theorem): X^k=UkΣkVkT=XVkVkT\hat{X}_k = U_k \Sigma_k V_k^T = X V_k V_k^T.

2. Reason 1: Forming XᵀX Squares the Condition Number (Losing Precision)

In IEEE 754 double-precision floating-point arithmetic, numbers have about 1616 decimal digits of accuracy (machine epsilon ϵmach≈2.22×10−16\epsilon_{\text{mach}} \approx 2.22 \times 10^{-16}). The sensitivity of a matrix XX to rounding errors is governed by its condition number κ(X)=σmax⁡(X)/σmin⁡(X)\kappa(X) = \sigma_{\max}(X) / \sigma_{\min}(X).

When you explicitly multiply XTXX^T X, the singular values square, which squares the condition number:

κ(XTX)=σmax⁡2σmin⁡2=(κ(X))2\kappa(X^T X) = \frac{\sigma_{\max}^2}{\sigma_{\min}^2} = \big(\kappa(X)\big)^2

If your data matrix has moderate collinearity with κ(X)=108\kappa(X) = 10^8, a direct SVD on XX computes singular values and vectors cleanly with 88 digits of accuracy. Explicitly forming XTXX^T X balloons the condition number to κ(XTX)=1016≈1/ϵmach\kappa(X^T X) = 10^{16} \approx 1/\epsilon_{\text{mach}}, wiping out the smaller eigenvalues completely into floating-point roundoff noise!

3. Reason 2: When Features d ≫ Samples n (Genomics, Images, NLP)

Suppose you analyze gene expression for n=200n = 200 patients across d=50,000d = 50,000 genes. Look at the memory and runtime difference:

   NAIVE COVARIANCE PATH (C = (1/n) X^T X):
   Forms a 50,000 x 50,000 matrix C (2.5 billion entries = 20 GB RAM!)
   Eigendecomposition costs O(d^3) ~ 1.25 x 10^14 operations!

   THIN / RANDOMIZED SVD PATH ON X (200 x 50,000):
   At most r = 200 non-zero singular values exist!
   Thin SVD costs O(n^2 d) ~ 2 x 10^9 operations (60,000x FASTER!) and needs only 80 MB RAM!

4. Worked Numerical Example: Läuchli's Precision Loss Matrix

Consider the classic numerical analysis matrix X=[11ϵ00ϵ]X = \begin{bmatrix} 1 & 1 \\ \epsilon & 0 \\ 0 & \epsilon \end{bmatrix} where ϵ=10−8\epsilon = 10^{-8}.

  1. Exact Product XTXX^T X:

    XTX=[1+ϵ2111+ϵ2]X^T X = \begin{bmatrix} 1 + \epsilon^2 & 1 \\ 1 & 1 + \epsilon^2 \end{bmatrix}

    Its true eigenvalues are 2+ϵ22 + \epsilon^2 and ϵ2=10−16\epsilon^2 = 10^{-16}, with orthogonal eigenvectors (1,1)T/2(1, 1)^T/\sqrt{2} and (−1,1)T/2(-1, 1)^T/\sqrt{2}.

  2. What happens in 64-bit Floating Point when you form XTXX^T X:

    Because 1+10−161 + 10^{-16} rounds to exactly 1.01.0 in IEEE 754 float64, the computer stores fl(XTX)=[1111]\text{fl}(X^T X) = \begin{bmatrix} 1 & 1 \\ 1 & 1 \end{bmatrix}, losing the second eigenvalue ϵ2\epsilon^2 completely (reporting 00 instead of 10−1610^{-16})! By contrast, running Householder bidiagonalization + SVD directly on XX never adds 1+ϵ21 + \epsilon^2 and preserves both singular values σ1=2+ϵ2\sigma_1 = \sqrt{2 + \epsilon^2} and σ2=ϵ=10−8\sigma_2 = \epsilon = 10^{-8} to full precision.

5. Active Recall Check and Key Takeaways

Quick Check: Test Your Understanding

Question: Given the thin SVD X=UΣVTX = U \Sigma V^T of a centered data matrix, how can you compute the n×kn \times k matrix of top-kk principal component scores ZkZ_k without multiplying XVkX V_k?

Answer: Since Zk=XVk=(UΣVT)Vk=UkΣkZ_k = X V_k = (U \Sigma V^T) V_k = U_k \Sigma_k, you simply scale the first kk columns of UU by the top kk singular values σ1,…,σk\sigma_1, \dots, \sigma_k!

Take a Quiz Based on This Article

Test your understanding with AI-generated questions tailored to this content

Adaptive Learning with SynLearn

Explore this article through guided practice that adapts to your answers

✓Step-by-step concepts & lessons
✓Active recall & adaptive feedback
✓Personalized spaced repetition
svd
singular-value-decomposition
numerical-stability
condition-number
pca
scikit-learn