JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Low-Rank Approximation: PCA and Compression

The SVD doesn't just factor a matrix — it ranks it, piece by piece, from most important to least. Keep the top few pieces and you have thrown away the noise while keeping the picture. This is the single idea behind image compression, PCA, recommender systems, and noise removal.

The SVD as a stack of ranked rank-1 pictures

In the last guide you met the singular value decomposition: every real m-by-n matrix A factors as A = U S V^T, with U and V orthogonal and S diagonal holding the singular values sigma_1 >= sigma_2 >= ... >= 0, sorted largest first. That factorization is true and complete, but there is a way to read it that turns it into a tool. Multiply it out and A is not one block — it is a sum: A = sigma_1 u_1 v_1^T + sigma_2 u_2 v_2^T + ... , where u_i and v_i are the columns of U and V.

Stare at one term. The outer product u_i v_i^T is an m-by-n matrix, yet it is the simplest possible nonzero matrix: every row is a copy of v_i scaled differently, every column a copy of u_i scaled differently. It has rank 1 — it carries one direction's worth of information. So the SVD says: A is built by stacking rank-1 pictures, and sigma_i is the brightness knob on picture i. Because the sigmas are sorted, the first term is the loudest single pattern in A, the second is the loudest pattern left after removing the first, and so on down to a long tail of nearly-dark pictures that contribute almost nothing.

Truncate, and Eckart-Young promises it is the best

Now do the obvious thing. Keep only the first k terms and throw the rest away: A_k = sigma_1 u_1 v_1^T + ... + sigma_k u_k v_k^T. This A_k is a rank-k matrix — the best k rank-1 pictures, at full brightness, summed. It is your low-rank approximation, and the natural worry is: is chopping off the tail a good approximation, or did I just get lucky on this example? The answer is a theorem, and it is unusually clean.

The Eckart-Young theorem says A_k is the best possible rank-k approximation to A — no other rank-k matrix gets closer. And the error you pay is exactly the brightness of the pictures you threw away: in the spectral norm, the gap ||A - A_k||_2 equals sigma_{k+1}, the first singular value you discarded. So the singular values are not just sorting labels; they are an exact, readable error budget. If sigma_{k+1} is tiny, your truncation is nearly perfect; if the sigmas decay slowly, no low-rank approximation can be good and the data genuinely needs many dimensions.

Why this compresses, and where it does not

Count the storage and the magic appears. The full m-by-n matrix needs m times n numbers. But A_k is built from k vectors u_i (length m), k vectors v_i (length n), and k singular values — that is k times (m + n + 1) numbers. For a 1000-by-1000 image kept at rank 50, you store about 50 times 2001, roughly a hundred thousand numbers instead of a million: a tenfold shrink while the picture still looks right, because the discarded sigmas were tiny. This is the literal mechanism behind SVD image compression, and the same arithmetic explains why a recommender system stores a few latent factors per user and per item instead of a giant ratings grid.

There is a second, subtler payoff: truncation denoises. Real measurements are signal in the top few directions plus a wide, faint spray of random noise spread across all the tiny singular values. Cutting the tail throws away mostly noise while keeping mostly signal — which is exactly the truncated-SVD idea you will see used to stabilize ill-posed inverse problems. The same cut that compresses also cleans.

PCA: the SVD wearing a statistician's hat

Principal Component Analysis is the most famous application of all this, and it is literally a truncated SVD with one bookkeeping step in front. Suppose you have N data points, each a row of measurements — patients by lab values, customers by purchases. Stack them as a matrix, then center it: subtract each column's mean so every feature has average zero. PCA asks for the directions in feature space along which the centered data varies the most; the first principal component is the single direction capturing the largest spread, the second the largest spread perpendicular to the first, and so on.

Here is the connection. Those directions of maximum variance are eigenvectors of the covariance matrix — and the covariance is proportional to A^T A for the centered data A. You could form A^T A and run an eigensolver on it, since it is a symmetric eigenproblem. But the right hands-on lesson from this whole rung is: don't. The right singular vectors v_i of A are exactly those eigenvectors, and the squared singular values sigma_i^2 are the variances along them, with no need to ever form A^T A. The principal components are just the v_i; projecting your data onto the top k of them is precisely the rank-k truncation in disguise.

When the matrix is too big for even the SVD

A full SVD of a dense m-by-n matrix costs on the order of O(m n^2) work — the same cubic-flavored price as the dense eigensolvers earlier in this rung, computed by Golub-Kahan bidiagonalization followed by an implicit QR-style iteration on the bidiagonal form. For a modest matrix that is fine. But modern data is enormous — millions of rows and columns — and you often want only the top k singular triples, with k far smaller than n. Computing the entire SVD just to keep the top 50 directions is wasteful, and may not even fit in memory.

Two escape routes both lean on ideas from this rung. The classical one is Krylov: the Lanczos/Arnoldi machinery you met for large sparse eigenproblems applies to A^T A (or to a clever symmetric embedding of A) and extracts the top few singular triples with only matrix-vector products — perfect for sparse or matrix-free A. The modern crowd-pleaser is randomized SVD: multiply A by a small random matrix to sketch its dominant column space, then do a tiny exact SVD inside that sketch.

It sounds reckless to randomly sketch a matrix, but it is well founded: with a sketch only slightly wider than k, the randomized SVD returns a rank-k approximation that, with high probability, is nearly as good as the Eckart-Young optimum, at cost roughly O(m n k) instead of O(m n^2). The catch is honest — it is a probabilistic guarantee, randomized methods give a good answer with high probability rather than a certainty, and pseudorandom number generators are deterministic so a fixed seed makes the run reproducible. When the singular values decay fast it is spectacularly accurate; when they decay slowly you take a few extra sketch columns and an optional correction step to recover quality.

Closing the rung: one decomposition, a dozen applications

Look back at the staircase you just climbed. You learned why eigenvalues cannot be found by solving the characteristic polynomial, met the power method and inverse iteration, watched the QR algorithm become the workhorse, saw the symmetric eigenproblem's extra gifts, and met Krylov solvers for the truly large. The SVD braided all of it together — and this guide showed that the single act of truncating a sorted SVD, blessed as optimal by Eckart-Young, is the same move whether you call it compression, denoising, regularization, or PCA.

Low-rank approximation in three honest lines

  U, s, Vt = svd(A)          # s sorted: s[0] >= s[1] >= ... >= 0
  k = number of s[i] above your tolerance      # read the elbow
  A_k = U[:, :k]  @  diag(s[:k])  @  Vt[:k, :] # best rank-k matrix

  # Eckart-Young:  ||A - A_k||_2  =  s[k]   (the first dropped value)
  # PCA:           columns of V[:, :k] are the principal components,
  #                s[i]^2 / (N-1) is the variance along component i.
  # Storage:       k*(m + n + 1) numbers instead of m*n.
Compression, PCA, and a guaranteed error bound all fall out of the same truncated SVD; only the choice of k and the way you read the output differ.

If you carry one thing forward, let it be the reframing: a matrix is not a static grid of numbers but a ranked sum of simple patterns, and the singular values tell you, honestly and in advance, how much is lost by keeping only the important ones. That single sentence connects the abstract eigenvalue machinery of this rung to the most-used data tool on the planet — and it does so while staying truthful about lossiness, conditioning, floating-point, and the probabilistic small print of the fast algorithms.