SafeZone AI Learn
Learn/ Mathematical Foundations/ Linear Algebra for ML · lesson 3 of 6

The singular value decomposition

Every matrix — square or not, symmetric or not — is a rotation, a stretch, and another rotation. Eckart–Young makes truncating it the best possible compression, and you can watch it compress an image rank by rank.

The spectral theorem was magnificent and narrow: it demanded symmetry. Data matrices are rectangular; weight matrices are whatever training made them. The singular value decomposition is the theorem with the asterisk removed — every matrix factors into rotate → stretch → rotate — and it is, without much competition, the most useful single fact in applied linear algebra: PCA is an SVD, LoRA truncates one implicitly, recommender systems factorize by it, and the best-rank-kk theorem it carries is the mathematical license for the word “compression” in half of ML.

The statement

For any ARm×nA \in \mathbb{R}^{m \times n}:

A=UΣVA = U \Sigma V^\top

with UU (m×mm \times m) and VV (n×nn \times n) orthogonal, and Σ\Sigma diagonal with non-negative entries σ1σ20\sigma_1 \ge \sigma_2 \ge \cdots \ge 0 — the singular values. Geometrically: VV^\top rotates the input space, Σ\Sigma stretches along perpendicular axes (padding or dropping dimensions if mnm \ne n), UU rotates the output space. Shear does not exist — what looked like shear in lesson 1’s widget was only ever a stretch caught between two rotations. The unit sphere maps to an ellipsoid whose axes are the columns of UU, with lengths σi\sigma_i.

Where it comes from: AAA^\top A is symmetric and positive semidefinite, so the spectral theorem hands us orthonormal eigenvectors viv_i with eigenvalues λi0\lambda_i \ge 0. Define σi=λi\sigma_i = \sqrt{\lambda_i} and ui=Avi/σiu_i = A v_i / \sigma_i; a short computation (exercise 1) shows the uiu_i are themselves orthonormal, and A=iσiuiviA = \sum_i \sigma_i u_i v_i^\top follows. Two corollaries you have already used without the receipts: the singular values of XX are the djd_j in ridge regression’s shrinkage factors dj2/(dj2+λ)d_j^2/(d_j^2+\lambda), and κ(XX)=(σmax/σmin)2\kappa(X^\top X) = (\sigma_{\max}/\sigma_{\min})^2 — the “conditioning squared” warning from the Linear Regression lesson, now a one-line proof.

The outer-product reading, and Eckart–Young

The decomposition rewrites as a sum of rank-one layers:

A=i=1rσiuiviA = \sum_{i=1}^{r} \sigma_i\, u_i v_i^\top

— each layer a full-size matrix built from one column and one row, weighted by σi\sigma_i. Since the weights are sorted, truncating the sum keeps the most important structure, and the remarkable fact is that this greedy move is optimal:

Eckart–Young theorem. Among ALL matrices of rank k\le k, the truncated SVD Ak=ikσiuiviA_k = \sum_{i \le k} \sigma_i u_i v_i^\top minimizes AB\lVert A - B \rVert (in Frobenius and spectral norms), with error AAkF2=i>kσi2\lVert A - A_k \rVert_F^2 = \sum_{i > k} \sigma_i^2.

“Best possible rank-kk approximation” is a strong claim over an enormous set, and the SVD just is it. Storage tells the practical story: a rank-kk version of an m×nm \times n matrix needs k(m+n+1)k(m + n + 1) numbers instead of mnmn. Whether that is a bargain depends entirely on how fast the σi\sigma_i decay — which is a property of the data, and the widget lets you inspect it directly:

At k = 1 you get the image’s “average structure” — one column profile times one row profile. Slide upward: the gradient and the diagonal line snap in early (they are nearly rank-1 objects), the text’s fine corners arrive last. Around k = 10–14 the reconstruction is visually done at a fraction of the storage — read the energy-kept percentage against Eckart–Young’s error formula: it is exactly Σσᵢ² of the kept bars over the total. The spectrum’s shape is the lesson: fast early decay = structure = compressible; a flat spectrum would mean noise, and noise is incompressible. That sentence, applied to datasets instead of pictures, is why PCA works when it works and fails when it fails.

The SVD in the ML you already know

PCA is the SVD of centred data. Centre the data matrix XX (rows = samples); its covariance is Σ=XX/n\Sigma = X^\top X / n, whose eigenvectors (= right singular vectors of XX) are the principal components — perpendicular directions of maximal variance, with variances σi2/n\sigma_i^2/n. Projecting onto the top kk is Eckart–Young applied to data: the kk-dimensional view that loses least. (The next lesson builds the projection geometry; the Unsupervised module will use it in anger, including its failure modes.)

LoRA is a rank bet, and the SVD is why it’s plausible. The RL track’s fine-tuning lesson wrote updates as ΔW=BA\Delta W = BA with rank rr. The empirical finding that motivates it — measured fine-tuning updates have rapidly-decaying singular spectra — is precisely “the widget’s bar chart, but for weight changes.” When the bet holds, a rank-16 update captures almost everything a full update would; Eckart–Young says a low-rank representation can; the spectrum decides whether it does.

Recommenders, embeddings, denoising. Latent-factor recommendation approximates the (sparse) user–item matrix by a low-rank product — users and items each get a kk-vector whose inner product predicts affinity (lesson 1’s similarity, again). Classical LSA embedded words by SVD of word–document counts a decade before word2vec. And keeping top-kk while discarding the small-σ\sigma tail is a denoiser whenever signal is structured and noise is not — the flat-tail intuition from the widget, used in production.

Numerics. The pseudoinverse A+=VΣ+UA^+ = V \Sigma^+ U^\top solves least squares even for rank-deficient designs (np.linalg.lstsq is an SVD under the hood), and σmax/σmin\sigma_{\max}/\sigma_{\min} is the condition number — the quantity this curriculum has been paying taxes to since the gradient-descent lesson.

import numpy as np

A = np.random.randn(48, 96)
U, s, Vt = np.linalg.svd(A, full_matrices=False)

k = 10
A_k = U[:, :k] * s[:k] @ Vt[:k]                      # best rank-k, by theorem
err = np.linalg.norm(A - A_k, "fro") ** 2
np.testing.assert_allclose(err, np.sum(s[k:] ** 2))  # Eckart–Young, verified

storage = k * (A.shape[0] + A.shape[1] + 1) / A.size # the compression ratio

Exercises

Work these before the next lesson

  1. Complete the construction: with vi,λiv_i, \lambda_i from AAA^\top A and ui=Avi/σiu_i = Av_i/\sigma_i, show uiuj=δiju_i^\top u_j = \delta_{ij} and hence A=iσiuiviA = \sum_i \sigma_i u_i v_i^\top. Where did positive semidefiniteness of AAA^\top A get used?
    Solution

    Worked solutions are part of Premiumunlock all of them for £5/month →

  2. 5 more exercises — each with a worked solution — are part of Premium. Unlock everything for £5/month →

References

  • C. Eckart & G. Young, “The approximation of one matrix by another of lower rank”, Psychometrika 1936.
  • G. Strang, “The Fundamental Theorem of Linear Algebra”, American Mathematical Monthly 1993 — the four subspaces, SVD-first.
  • L. Trefethen & D. Bau, Numerical Linear Algebra, lectures 4–5 — the standard rigorous treatment.
  • Y. Koren, R. Bell, C. Volinsky, “Matrix Factorization Techniques for Recommender Systems”, IEEE Computer 2009 — the Netflix-era application.