Three completely different questions — which direction has most variance, which subspace loses least information, and what does the SVD of the data matrix say — all have the same answer. That coincidence is PCA, and it is the most useful thing the spectral theorem does.
Data \(\vx_1,\dots,\vx_n\in\RR^d\), stacked as rows of \(\mX\in\RR^{n\times d}\). First, centre: subtract the mean of each column, giving \(\mX_c\) with \(\frac1n\sum_i\vx_i=\vzero\). The sample covariance is then
\[\mS = \frac{1}{n}\mX_c^\top\mX_c \in \RR^{d\times d},\]
symmetric and positive semi-definite, so the spectral theorem applies: \(\mS=\mQ\Lambda\mQ^\top\) with orthonormal eigenvectors and non-negative eigenvalues (Phase A Lecture 11).
Centring is not cosmetic. Without it, the largest "principal component" of a dataset whose mean is far from the origin will simply point at the mean, because \(\frac1n\|\mX\vu\|^2\) then measures second moment, not variance. You would spend your first component describing where the data is rather than how it varies. Every PCA implementation centres; if you write your own, centre first.
Question: which unit direction \(\vu\) makes the projected data most spread out?
A completely different question: which \(k\)-dimensional subspace, when we project the data onto it and back, loses the least? Remarkably, the same answer.
Every real matrix factors as \(\mX_c = \mU\mathbf{\Sigma}\mV^\top\) with \(\mU,\mV\) orthonormal and \(\mathbf{\Sigma}\) diagonal with non-negative entries \(\sigma_1\ge\sigma_2\ge\cdots\). Then
\[\mS = \frac1n\mX_c^\top\mX_c = \frac1n\mV\mathbf{\Sigma}^\top\mU^\top\mU\mathbf{\Sigma}\mV^\top = \mV\left(\frac{\mathbf{\Sigma}^2}{n}\right)\mV^\top,\]
using \(\mU^\top\mU=\mI\). Comparing with \(\mS=\mQ\Lambda\mQ^\top\) and matching the (unique, up to sign and ties) eigendecomposition:
A covariance matrix has eigenvalues \(\{40, 25, 20, 10, 4, 1\}\).
1. Total \(=40+25+20+10+4+1=100\). First two: \(65/100 = \mathbf{65\%}\).
2. Cumulative: 40, 65, 85, 95, 99, 100. So \(k=4\) reaches 95%, and \(k=3\) only reaches 85%. Four components are needed for 90%.
3. Reconstruction error at \(k=3\) is \(\sum_{j>3}\lambda_j = 10+4+1 = \mathbf{15}\), which is 15% of the total variance \(\tr(\mS)=\mathbf{100}\). (Total variance is the trace, which equals the sum of the eigenvalues — Phase A Lecture 11.)
4. No, not really. The spectrum decays slowly: 40, 25, 20 are all comparable, and there is no sharp elbow. Genuinely low-dimensional data looks like \(\{80, 15, 2, 1, 1, 1\}\) — a big gap and then a flat floor. Here you need two-thirds of the components for 95% of the variance, which is barely a reduction.
What you can say: there is some structure (the top component is 40× the bottom one), and dropping the last two costs 5%, which may well be worth it for denoising. But do not describe this as "the data is really 2-dimensional".
Prove that the two derivations give the same answer, by showing directly that
\[ \argmin_{\mU_k}\ \frac1n\sum_i\|\vx_i-\mU_k\mU_k^\top\vx_i\|^2 \;=\; \argmax_{\mU_k}\ \tr(\mU_k^\top\mS\mU_k). \]Then explain why \(\tr(\mS)=\sum_j\lambda_j\) is the "total variance", and what that means for the interpretation of the explained-variance ratio.
Equivalence. Let \(\mP=\mU_k\mU_k^\top\), which is a projection: \(\mP^2=\mP\) and \(\mP^\top=\mP\). For each point, the projection and residual are orthogonal:
\[(\mP\vx)^\top(\vx-\mP\vx) = \vx^\top\mP\vx - \vx^\top\mP^\top\mP\vx = \vx^\top\mP\vx-\vx^\top\mP\vx = 0,\]using \(\mP^\top\mP=\mP^2=\mP\). So Pythagoras gives \(\|\vx\|^2=\|\mP\vx\|^2+\|\vx-\mP\vx\|^2\). Averaging over \(i\):
\[\underbrace{\frac1n\sum_i\|\vx_i\|^2}_{=\,\tr(\mS),\ \text{fixed}} = \frac1n\sum_i\|\mP\vx_i\|^2 + J(\mU_k).\]The left-hand side does not involve \(\mU_k\), so minimising \(J\) is exactly maximising the middle term. And \(\|\mP\vx\|^2 = \vx^\top\mU_k\mU_k^\top\vx = \|\mU_k^\top\vx\|^2\), whose average is \(\tr(\mU_k^\top\mS\mU_k)\) by the cyclic property of the trace. ∎
Why \(\tr(\mS)\) is the total variance. The diagonal entries \(S_{jj}\) are the individual feature variances, so \(\tr(\mS)=\sum_j\Var(x_j)\). And the trace equals the sum of the eigenvalues (Phase A Lecture 11's \(\lambda_1+\lambda_2=\tr\mA\), in general dimension). So
\[\sum_{j}\Var(x_j) = \sum_j \lambda_j.\]The total variance is invariant under rotation — PCA redistributes it among orthogonal directions without creating or destroying any. That is what makes the ratio \(\sum_{j\le k}\lambda_j/\sum_j\lambda_j\) a meaningful "fraction explained": the denominator is a conserved quantity.
The interpretive caveat. It is a fraction of variance, not a fraction of information, and the two come apart badly in at least three ways. If you standardised, every feature contributes exactly 1 to the total, so \(\tr(\mS)=d\) and the ratio partly reflects your standardisation choice. If a feature is pure noise with large amplitude, it inflates the denominator and makes every ratio look worse. And if the signal you care about is a low-variance direction (the last figure in the code block), a component explaining 2% of the variance may carry 100% of what matters. "95% of variance explained" is a statement about geometry, never about utility.
Whitening. Define \(\vz_i = \Lambda_k^{-1/2}\mQ_k^\top\vx_i\).
1. The covariance of the whitened scores is
\[\frac1n\sum_i \vz_i\vz_i^\top = \Lambda_k^{-1/2}\mQ_k^\top\left(\frac1n\sum_i\vx_i\vx_i^\top\right)\mQ_k\Lambda_k^{-1/2} = \Lambda_k^{-1/2}\big(\mQ_k^\top\mS\mQ_k\big)\Lambda_k^{-1/2}.\]Since the columns of \(\mQ_k\) are eigenvectors, \(\mS\mQ_k=\mQ_k\Lambda_k\), so \(\mQ_k^\top\mS\mQ_k=\Lambda_k\). Hence the covariance is \(\Lambda_k^{-1/2}\Lambda_k\Lambda_k^{-1/2}=\mI_k\). ∎ (\(\Lambda_k^{-1/2}\) exists because the retained eigenvalues are positive.)
2. Two reasons, both from Phase A.
Conditioning. After whitening the covariance is \(\mI\), so \(\kappa=1\). By Lecture 03, gradient descent then converges in \(O(1)\) iterations instead of \(O(\kappa)\), and the zig-zag disappears entirely. Whitening is the strongest possible preconditioner for a quadratic problem — it is the Newton step, applied to the data instead of the gradient.
Isotropic distance. Euclidean distance in whitened space equals Mahalanobis distance in the original space (Phase A Lecture 14, exercise 3). Any algorithm that uses raw distances — \(k\)-means, \(k\)-NN, RBF kernels — is implicitly assuming isotropy, and whitening makes that assumption true.
3. The danger. Whitening divides by \(\sqrt{\lambda_j}\). A direction with \(\lambda_j\approx0\) is one in which the data barely varies at all — which usually means it is pure measurement noise. Dividing by a tiny number amplifies that noise to the same scale as the genuine signal, and can amplify it by orders of magnitude.
Concretely, with \(\lambda_{\min}=10^{-6}\) and \(\lambda_{\max}=1\), whitening multiplies the noisiest direction by 1000 relative to the strongest. You have "improved" the conditioning from \(10^6\) to \(1\) by promoting noise to first-class status.
The standard fixes: whiten only the top \(k\) components (discarding the rest, as the formula above does); or use \(\Lambda^{-1/2}\) with a floor, \((\Lambda+\epsilon\mI)^{-1/2}\), which is ridge regularisation applied to whitening. This is exactly the same trade-off as Lecture 06's shrinkage factors, viewed from the other side — there we shrank small-eigenvalue directions, here we must be careful not to inflate them.
Coding. Investigate when PCA helps a downstream classifier and when it hurts.
import numpy as np
rng = np.random.default_rng(0)
sig = lambda z: 1/(1+np.exp(-np.clip(z,-500,500)))
def logistic(X, y, T=3000, lr=0.3, lam=1e-3):
Xb = np.column_stack([np.ones(len(y)), X]); w = np.zeros(Xb.shape[1])
for _ in range(T):
g = Xb.T @ (sig(Xb@w) - y) / len(y); g[1:] += lam*w[1:]
w -= lr*g
return w
def acc(X, y, w):
return float((( sig(np.column_stack([np.ones(len(y)),X])@w) >= .5) == y).mean())
def make(kind, n=1500, d=50, seed=0):
r = np.random.default_rng(seed)
y = r.integers(0, 2, n).astype(float)
scales = np.logspace(1, -1, d) # variance 10 down to 0.1
X = r.normal(size=(n, d)) * scales
j = 0 if kind == "high" else d-1 # which direction carries the label
X[:, j] += 2.0*scales[j]*(2*y-1)
return X, y
for kind in ("high", "low"):
Xtr, ytr = make(kind, seed=1); Xte, yte = make(kind, seed=2)
mu = Xtr.mean(0); Zc = Xtr - mu
l, Q = np.linalg.eigh(Zc.T@Zc/len(Zc)); o = np.argsort(l)[::-1]; l, Q = l[o], Q[:,o]
row = []
for k in (1, 2, 5, 10, 25, 50):
w = logistic(Zc@Q[:,:k], ytr)
row.append((k, acc((Xte-mu)@Q[:,:k], yte, w), l[:k].sum()/l.sum()))
print(f"signal in a {kind}-variance direction:")
for k, a, ev in row:
print(f" k={k:3d} test acc {a:.4f} variance explained {ev:6.1%}")
# LDA direction: Sigma^-1 (mu1 - mu0)
m1, m0 = Xtr[ytr==1].mean(0), Xtr[ytr==0].mean(0)
Sw = np.cov(Xtr.T) + 1e-6*np.eye(Xtr.shape[1])
v = np.linalg.solve(Sw, m1-m0); v /= np.linalg.norm(v)
w = logistic((Xtr@v)[:,None], ytr)
print(f" LDA, k=1 test acc {acc((Xte@v)[:,None], yte, w):.4f}\\n")
1. Signal in a high-variance direction. Accuracy is already near its ceiling at \(k=1\) and stays flat as \(k\) grows. PCA has done exactly what you hoped: reduced 50 dimensions to 1 with no loss. Note that \(k=1\) explains only a modest share of total variance and yet captures all the signal — variance explained and accuracy are not the same axis.
2. Signal in a low-variance direction. Accuracy at \(k=1\) is around chance, and stays near chance until \(k\) approaches 50, at which point it jumps. The discriminative direction is the last principal component, so any aggressive PCA truncation destroys the model. If you had followed "keep 95% of the variance" you would have discarded the only useful direction and concluded the problem was unlearnable.
3. LDA gets near-ceiling accuracy with \(k=1\) in both cases, because \(\mS_w^{-1}(\vm_1-\vm_0)\) is constructed from the labels: it finds the direction maximising between-class separation relative to within-class scatter, wherever that direction happens to sit in the spectrum. This is not magic — it is simply using information PCA is not given.
4. The rule. Unsupervised dimensionality reduction is safe exactly when the variance structure of the inputs is aligned with the structure of the target — and you cannot check that without looking at the target.
Practical consequences:
Next: PCA finds directions. Lecture 09 finds groups — k-means, its probabilistic upgrade to Gaussian mixtures, and the EM algorithm that fits them, which is one of the most reused ideas in the subject.