Chapter 0 · Section 0.10 · 95 min

Linear algebra for machine learning

Take the matrix [2112]\begin{bmatrix}2 & 1\\ 1 & 2\end{bmatrix} and multiply it into the vector (1,0)(1, 0), then multiply the result by the same matrix again, twenty times in all. Two things happen. The vector swings around until it points along (1,1)(1, 1), and after that every multiplication makes it three times longer, to many decimal places, so by the end it is about 2.5 billion times longer than it started. Start from almost any other vector and the same thing happens.

That small experiment contains most of this section. The direction the vector settles into is an eigenvector, the factor of three is its eigenvalue, and the procedure itself is power iteration, the algorithm that estimates the spectral norm inside spectral normalization. Swap "twenty multiplications" for "twenty steps of a recurrent network" and you have the reason RNN gradients explode or vanish.

The rest of the book keeps asking questions of this kind. Why do gradients through fifty steps of an RNN die (§3.3)? Why can LoRA fine-tune a 4096×40964096 \times 4096 matrix by training only 65,536 numbers (§14.5)? Why does the Muon optimizer throw away the singular values of its update (§8.6)? What exactly does PCA keep (§1.6)? Each one is a question about what a matrix does to directions. We will answer them with a handful of ideas (eigenvalues, the singular value decomposition, norms, and conditioning), building each from a 2×22 \times 2 picture you can draw, to a proof, to NumPy, to the weight matrices of a trained Transformer.

Python · cell 1

A matrix is a map you can draw

A matrix A∈R2×2\mathbf{A} \in \R^{2 \times 2} sends each vector x\mathbf{x} to Ax\mathbf{A}\mathbf{x}, and its columns tell you where the two basis vectors go. For our matrix, e1=(1,0)\mathbf{e}_1 = (1, 0) lands on the first column (2,1)(2, 1) and e2=(0,1)\mathbf{e}_2 = (0, 1) on the second column (1,2)(1, 2). Every other vector follows by linearity, A(x1e1+x2e2)=x1Ae1+x2Ae2\mathbf{A}(x_1\mathbf{e}_1 + x_2\mathbf{e}_2) = x_1\mathbf{A}\mathbf{e}_1 + x_2\mathbf{A}\mathbf{e}_2, so the whole map is fixed by two arrows.

A good way to see a matrix is to watch what it does to the unit circle. A linear map sends the circle to an ellipse (flattened to a line segment if the matrix is singular), and the unit square to a parallelogram whose area is ∣det⁡A∣|\det\mathbf{A}|. For our matrix the determinant is 2⋅2−1⋅1=32 \cdot 2 - 1 \cdot 1 = 3, so areas triple. A negative determinant means the map also flips orientation, like a mirror.

The widget below lets you set the four entries and watch the circle deform. It also draws two special pairs of directions, which the rest of this section explains. The eigenvectors are the directions that the map only stretches, without turning. The singular vectors are the directions on the circle that land on the axes of the ellipse.

What does a 2 by 2 matrix do to the unit circle, and which directions are special?
The dashed circle maps to the shaded ellipse. Solid lines are the ellipse's axes σ₁u₁ and σ₂u₂, and the open dots on the circle are the right singular vectors v₁ and v₂ that land on them. Long dashed lines are the real eigenvectors. Click anywhere to choose a start vector, then run power iteration.
Loading interactive figure…

The shear leaves exactly one direction unturned, the xx axis, and the ellipse's axes point somewhere else entirely. The rotation turns every direction, so it has no real eigenvectors at all, yet its "ellipse" is the circle itself, with every direction an axis. Eigenvectors and the axes of the ellipse are different objects, and they agree only for special matrices. We take them one at a time.

Eigenvectors, the directions a matrix only stretches

An eigenvector of a square matrix A∈Rn×n\mathbf{A} \in \R^{n \times n} is a nonzero vector q\mathbf{q} that A\mathbf{A} maps to a multiple of itself, and the multiple λ\lambda is its eigenvalue,

Aq=λq,q≠0.\mathbf{A}\mathbf{q} = \lambda\mathbf{q}, \qquad \mathbf{q} \neq \mathbf{0} .

In plain words, along an eigenvector the matrix acts like the single number λ\lambda. It stretches (if ∣λ∣>1|\lambda| > 1), shrinks (if ∣λ∣<1|\lambda| < 1), or flips (if λ<0\lambda < 0), and never turns.

How do we find them? Rewrite the equation as (A−λI)q=0(\mathbf{A} - \lambda\mathbf{I})\mathbf{q} = \mathbf{0}. A nonzero solution exists exactly when A−λI\mathbf{A} - \lambda\mathbf{I} is singular, that is, when det⁡(A−λI)=0\det(\mathbf{A} - \lambda\mathbf{I}) = 0. For a 2×22 \times 2 matrix [abcd]\begin{bmatrix}a & b\\ c & d\end{bmatrix} this determinant is (a−λ)(d−λ)−bc(a - \lambda)(d - \lambda) - bc, which expands to

λ2−(tr⁡A) λ+det⁡A=0,λ=tr⁡A±(tr⁡A)2−4det⁡A2,\lambda^2 - (\operatorname{tr}\mathbf{A})\,\lambda + \det\mathbf{A} = 0, \qquad \lambda = \frac{\operatorname{tr}\mathbf{A} \pm \sqrt{(\operatorname{tr}\mathbf{A})^2 - 4\det\mathbf{A}}}{2},

where tr⁡A=a+d\operatorname{tr}\mathbf{A} = a + d is the trace. Comparing with (λ−λ1)(λ−λ2)=λ2−(λ1+λ2)λ+λ1λ2(\lambda - \lambda_1)(\lambda - \lambda_2) = \lambda^2 - (\lambda_1 + \lambda_2)\lambda + \lambda_1\lambda_2 shows that the eigenvalues add up to the trace and multiply to the determinant. Both facts hold for n×nn \times n matrices too.

A worked example. For A=[2112]\mathbf{A} = \begin{bmatrix}2 & 1\\ 1 & 2\end{bmatrix} the trace is 4 and the determinant is 3, so λ2−4λ+3=(λ−3)(λ−1)=0\lambda^2 - 4\lambda + 3 = (\lambda - 3)(\lambda - 1) = 0 and the eigenvalues are 3 and 1. For λ=3\lambda = 3, A−3I=[−111−1]\mathbf{A} - 3\mathbf{I} = \begin{bmatrix}-1 & 1\\ 1 & -1\end{bmatrix}, whose null space is spanned by (1,1)(1, 1), so q1=(1,1)/2\mathbf{q}_1 = (1, 1)/\sqrt2. For λ=1\lambda = 1, A−I\mathbf{A} - \mathbf{I} has every entry equal to 1, and q2=(1,−1)/2\mathbf{q}_2 = (1, -1)/\sqrt2. Now the opening experiment makes sense. The starting vector (1,0)(1, 0) is (q1+q2)/2(\mathbf{q}_1 + \mathbf{q}_2)/\sqrt2. After kk multiplications it is (3kq1+1kq2)/2(3^k\mathbf{q}_1 + 1^k\mathbf{q}_2)/\sqrt2, so the q1\mathbf{q}_1 part wins by a factor of 3k3^k, and the tangent of the angle to q1\mathbf{q}_1 is exactly (1/3)k(1/3)^k.

Three other 2×22 \times 2 matrices show everything that can go wrong.

  • A rotation by 90 degrees, [0−110]\begin{bmatrix}0 & -1\\ 1 & 0\end{bmatrix}, has trace 0 and determinant 1, so λ2+1=0\lambda^2 + 1 = 0 and λ=±i\lambda = \pm i. No real direction survives a quarter turn unturned. The eigenvalues are complex, of absolute value 1, because a rotation neither stretches nor shrinks.
  • A shear, [1101]\begin{bmatrix}1 & 1\\ 0 & 1\end{bmatrix}, has (λ−1)2=0(\lambda - 1)^2 = 0, a double eigenvalue of 1, but A−I=[0100]\mathbf{A} - \mathbf{I} = \begin{bmatrix}0 & 1\\ 0 & 0\end{bmatrix} has only a one-dimensional null space, the xx axis. There is one eigenvector where we needed two. Such a matrix is called defective.
  • A triangular matrix, [3045]\begin{bmatrix}3 & 0\\ 4 & 5\end{bmatrix}, has eigenvalues 3 and 5 (for a triangular matrix they are the diagonal entries). Its eigenvectors are (1,−2)/5(1, -2)/\sqrt5 and (0,1)(0, 1), which meet at about 27 degrees instead of 90. Real eigenvalues, but skewed eigenvectors. We will meet this matrix again.

Diagonalization and powers

If A\mathbf{A} has nn linearly independent eigenvectors, collect them as the columns of Q\mathbf{Q} and the eigenvalues in the diagonal matrix Λ=diag⁡(λ1,…,λn)\boldsymbol\Lambda = \operatorname{diag}(\lambda_1, \dots, \lambda_n). The nn equations Aqi=λiqi\mathbf{A}\mathbf{q}_i = \lambda_i\mathbf{q}_i say, column by column, AQ=QΛ\mathbf{A}\mathbf{Q} = \mathbf{Q}\boldsymbol\Lambda. Multiplying on the right by Q−1\mathbf{Q}^{-1} gives the eigendecomposition

A=QΛQ−1,Ak=QΛkQ−1.\mathbf{A} = \mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^{-1}, \qquad \mathbf{A}^k = \mathbf{Q}\boldsymbol\Lambda^k\mathbf{Q}^{-1} .

The second identity follows because the inner factors cancel in pairs, A2=QΛQ−1QΛQ−1=QΛ2Q−1\mathbf{A}^2 = \mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^{-1}\mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^{-1} = \mathbf{Q}\boldsymbol\Lambda^2\mathbf{Q}^{-1}, and so on. In plain words, change to the eigenvector coordinates, where the matrix is a separate scalar on each axis, raise each scalar to the kk-th power, and change back. Powers of a matrix are powers of its eigenvalues.

So the long-run behavior of Ak\mathbf{A}^k is set by the spectral radius ρ(A)=max⁡i∣λi∣\rho(\mathbf{A}) = \max_i |\lambda_i|. If ρ(A)<1\rho(\mathbf{A}) < 1, every component shrinks and Ak→0\mathbf{A}^k \to \mathbf{0}. If ρ(A)>1\rho(\mathbf{A}) > 1, the component along the largest eigenvalue grows without bound. You have already used this. Gradient descent on a quadratic in §0.6 multiplies the error by I−ηA\mathbf{I} - \eta\mathbf{A} every step, whose eigenvalues are 1−ηλi1 - \eta\lambda_i, and the stability condition η<2/λmax⁡\eta < 2/\lambda_{\max} is exactly ρ(I−ηA)<1\rho(\mathbf{I} - \eta\mathbf{A}) < 1.

Python · cell 2
Warm-up

Eigenvalues and eigenvector of a symmetric 2-by-2, by hand

For the symmetric matrix [abbc]\begin{bmatrix}a & b\\ b & c\end{bmatrix}, implement eig_sym_2x2(a, b, c) returning (lam1, lam2, v1) with lam1 >= lam2 and v1 a unit eigenvector (shape (2,)) for lam1. Use the closed form, without np.linalg. It must work when b=0b = 0, including when c>ac > a.

Hidden tests, hints, and AI help, from $1.99 a month.

Symmetric matrices and the spectral theorem

The rotation, the shear, and the triangular matrix all misbehave in some way. Symmetric matrices, with A=A⊤\mathbf{A} = \mathbf{A}^\top, never do, and they are everywhere in machine learning. Covariance matrices, Hessians, Gram matrices X⊤X\mathbf{X}^\top\mathbf{X}, and kernel matrices are all symmetric. Their good behavior is a theorem.

The spectral theorem. Every real symmetric matrix A∈Rn×n\mathbf{A} \in \R^{n \times n} can be written as

A=QΛQ⊤=∑i=1nλi qiqi⊤,Q⊤Q=I,\mathbf{A} = \mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^\top = \sum_{i=1}^{n} \lambda_i\, \mathbf{q}_i\mathbf{q}_i^\top, \qquad \mathbf{Q}^\top\mathbf{Q} = \mathbf{I},

with real eigenvalues λi\lambda_i and orthonormal eigenvectors qi\mathbf{q}_i (the columns of Q\mathbf{Q}). In plain words, a symmetric matrix is a rotation into a special set of perpendicular axes, a separate stretch along each axis, and a rotation back. Since Q\mathbf{Q} is orthogonal, its inverse is its transpose, and the second form writes A\mathbf{A} as a weighted sum of nn rank-one matrices qiqi⊤\mathbf{q}_i\mathbf{q}_i^\top, each of which projects onto one axis.

∂ Proof of the spectral theorem

Three steps. Throughout, A\mathbf{A} is real and symmetric, and a bar denotes complex conjugation.

1. Every eigenvalue is real. Suppose Aq=λq\mathbf{A}\mathbf{q} = \lambda\mathbf{q} with q≠0\mathbf{q} \neq \mathbf{0}, allowing λ\lambda and q\mathbf{q} to be complex. Multiply on the left by qˉ⊤\bar{\mathbf{q}}^\top to get qˉ⊤Aq=λ qˉ⊤q\bar{\mathbf{q}}^\top\mathbf{A}\mathbf{q} = \lambda\,\bar{\mathbf{q}}^\top\mathbf{q}. Conjugating the eigen-equation gives Aqˉ=λˉqˉ\mathbf{A}\bar{\mathbf{q}} = \bar\lambda\bar{\mathbf{q}} (since A\mathbf{A} is real), and transposing it gives qˉ⊤A=λˉqˉ⊤\bar{\mathbf{q}}^\top\mathbf{A} = \bar\lambda\bar{\mathbf{q}}^\top (since A⊤=A\mathbf{A}^\top = \mathbf{A}). Multiply that on the right by q\mathbf{q}, so qˉ⊤Aq=λˉ qˉ⊤q\bar{\mathbf{q}}^\top\mathbf{A}\mathbf{q} = \bar\lambda\,\bar{\mathbf{q}}^\top\mathbf{q}. The two expressions for the same number give (λ−λˉ) qˉ⊤q=0(\lambda - \bar\lambda)\,\bar{\mathbf{q}}^\top\mathbf{q} = 0. Since qˉ⊤q=∑j∣qj∣2>0\bar{\mathbf{q}}^\top\mathbf{q} = \sum_j |q_j|^2 > 0, we get λ=λˉ\lambda = \bar\lambda, so λ\lambda is real. A real eigenvalue makes A−λI\mathbf{A} - \lambda\mathbf{I} a real singular matrix, so a real eigenvector exists too.

2. Eigenvectors for different eigenvalues are orthogonal. Let Aq1=λ1q1\mathbf{A}\mathbf{q}_1 = \lambda_1\mathbf{q}_1 and Aq2=λ2q2\mathbf{A}\mathbf{q}_2 = \lambda_2\mathbf{q}_2 with λ1≠λ2\lambda_1 \neq \lambda_2. Then λ1q1⊤q2=(Aq1)⊤q2=q1⊤A⊤q2=q1⊤Aq2=λ2q1⊤q2\lambda_1\mathbf{q}_1^\top\mathbf{q}_2 = (\mathbf{A}\mathbf{q}_1)^\top\mathbf{q}_2 = \mathbf{q}_1^\top\mathbf{A}^\top\mathbf{q}_2 = \mathbf{q}_1^\top\mathbf{A}\mathbf{q}_2 = \lambda_2\mathbf{q}_1^\top\mathbf{q}_2. So (λ1−λ2)q1⊤q2=0(\lambda_1 - \lambda_2)\mathbf{q}_1^\top\mathbf{q}_2 = 0, which forces q1⊤q2=0\mathbf{q}_1^\top\mathbf{q}_2 = 0.

3. There is a full orthonormal basis of eigenvectors, even with repeated eigenvalues. Induct on nn. For n=1n = 1 there is nothing to prove. For general nn, the characteristic polynomial det⁡(A−λI)\det(\mathbf{A} - \lambda\mathbf{I}) has at least one complex root, which by step 1 is real, with a real unit eigenvector q1\mathbf{q}_1. Let SS be the (n−1)(n-1)-dimensional subspace of vectors orthogonal to q1\mathbf{q}_1. The key observation is that A\mathbf{A} maps SS into itself. If x⊥q1\mathbf{x} \perp \mathbf{q}_1, then q1⊤Ax=(Aq1)⊤x=λ1q1⊤x=0\mathbf{q}_1^\top\mathbf{A}\mathbf{x} = (\mathbf{A}\mathbf{q}_1)^\top\mathbf{x} = \lambda_1\mathbf{q}_1^\top\mathbf{x} = 0, so Ax⊥q1\mathbf{A}\mathbf{x} \perp \mathbf{q}_1 as well. Choose an orthonormal basis of SS, the columns of B∈Rn×(n−1)\mathbf{B} \in \R^{n \times (n-1)}. Then B⊤AB\mathbf{B}^\top\mathbf{A}\mathbf{B} is a symmetric (n−1)×(n−1)(n-1) \times (n-1) matrix that represents A\mathbf{A} on SS, and by the induction hypothesis it has an orthonormal basis of eigenvectors w2,…,wn\mathbf{w}_2, \dots, \mathbf{w}_n. The vectors qi=Bwi\mathbf{q}_i = \mathbf{B}\mathbf{w}_i are orthonormal, orthogonal to q1\mathbf{q}_1, and eigenvectors of A\mathbf{A} (because ABwi\mathbf{A}\mathbf{B}\mathbf{w}_i lies in SS, it equals BB⊤ABwi=λiBwi\mathbf{B}\mathbf{B}^\top\mathbf{A}\mathbf{B}\mathbf{w}_i = \lambda_i\mathbf{B}\mathbf{w}_i). Together with q1\mathbf{q}_1 they form the basis. ∎

The Rayleigh quotient

How much does a symmetric matrix stretch a given direction? The Rayleigh quotient answers it,

R(x)=x⊤Axx⊤x.R(\mathbf{x}) = \frac{\mathbf{x}^\top\mathbf{A}\mathbf{x}}{\mathbf{x}^\top\mathbf{x}} .

Expand x=∑iciqi\mathbf{x} = \sum_i c_i\mathbf{q}_i in the eigenvector basis. Orthonormality makes the cross terms vanish, so x⊤Ax=∑iλici2\mathbf{x}^\top\mathbf{A}\mathbf{x} = \sum_i \lambda_i c_i^2 and x⊤x=∑ici2\mathbf{x}^\top\mathbf{x} = \sum_i c_i^2, and

R(x)=∑iλici2∑ici2,λmin⁡≤R(x)≤λmax⁡.R(\mathbf{x}) = \frac{\sum_i \lambda_i c_i^2}{\sum_i c_i^2}, \qquad \lambda_{\min} \le R(\mathbf{x}) \le \lambda_{\max} .

In plain words, the Rayleigh quotient is a weighted average of the eigenvalues, with weights ci2c_i^2 saying how much of x\mathbf{x} lies along each eigenvector. So it can never leave the range of the eigenvalues, and it reaches λmax⁡\lambda_{\max} exactly at the top eigenvector. This gives the most useful characterization of the extreme eigenvalues, λmax⁡=max⁡x≠0R(x)\lambda_{\max} = \max_{\mathbf{x} \neq \mathbf{0}} R(\mathbf{x}) and λmin⁡=min⁡x≠0R(x)\lambda_{\min} = \min_{\mathbf{x} \neq \mathbf{0}} R(\mathbf{x}).

When A\mathbf{A} is a Hessian, R(x)R(\mathbf{x}) is the curvature of the loss along direction x\mathbf{x}, and λmax⁡\lambda_{\max} is the curvature of the steepest direction, often called the sharpness. §0.6 showed that gradient descent is stable only if η<2/λmax⁡\eta < 2/\lambda_{\max}. Cohen et al. (2021) found empirically that in full-batch training of neural networks, the sharpness rises until it reaches about 2/η2/\eta and then hovers there, a regime they called the edge of stability.

Python · cell 3

Positive definite matrices

A symmetric matrix is positive definite (PD) if x⊤Ax>0\mathbf{x}^\top\mathbf{A}\mathbf{x} > 0 for every x≠0\mathbf{x} \neq \mathbf{0}, and positive semidefinite (PSD) if x⊤Ax≥0\mathbf{x}^\top\mathbf{A}\mathbf{x} \ge 0. Geometrically, the quadratic x⊤Ax\mathbf{x}^\top\mathbf{A}\mathbf{x} is a bowl that curves upward in every direction, and its level set x⊤Ax=1\mathbf{x}^\top\mathbf{A}\mathbf{x} = 1 is an ellipse with axes along the eigenvectors and half-lengths 1/λi1/\sqrt{\lambda_i}.

Several conditions are equivalent, and each is useful in a different place.

  • All eigenvalues are positive. By the Rayleigh quotient, x⊤Ax≥λmin⁡∥x∥2\mathbf{x}^\top\mathbf{A}\mathbf{x} \ge \lambda_{\min}\lVert\mathbf{x}\rVert^2, which is positive for every nonzero x\mathbf{x} exactly when λmin⁡>0\lambda_{\min} > 0.
  • A Cholesky factor exists, A=LL⊤\mathbf{A} = \mathbf{L}\mathbf{L}^\top with L\mathbf{L} lower triangular and a positive diagonal. You used it in §0.4 to sample from a multivariate Gaussian. Trying a Cholesky factorization is also the standard numerical test for positive definiteness, since it fails partway through if the matrix is not PD and costs a small fraction of an eigendecomposition.
  • It is a Gram matrix of independent vectors, A=B⊤B\mathbf{A} = \mathbf{B}^\top\mathbf{B} with B\mathbf{B} of full column rank.

That last form shows where PSD matrices come from. For any X∈RN×d\mathbf{X} \in \R^{N \times d}, v⊤X⊤Xv=∥Xv∥2≥0\mathbf{v}^\top\mathbf{X}^\top\mathbf{X}\mathbf{v} = \lVert\mathbf{X}\mathbf{v}\rVert^2 \ge 0, so every Gram matrix is PSD, and it is PD exactly when no nonzero v\mathbf{v} has Xv=0\mathbf{X}\mathbf{v} = \mathbf{0}. That fails whenever there are more features than examples (d>Nd > N), which is why the least-squares matrix X⊤X\mathbf{X}^\top\mathbf{X} can be singular. A covariance matrix is PSD for the same reason, since v⊤Σv=Var⁡(v⊤x)≥0\mathbf{v}^\top\boldsymbol\Sigma\mathbf{v} = \operatorname{Var}(\mathbf{v}^\top\mathbf{x}) \ge 0, a variance. And adding λI\lambda\mathbf{I} shifts every eigenvalue up by λ\lambda without changing the eigenvectors, because (A+λI)qi=(λi+λ)qi(\mathbf{A} + \lambda\mathbf{I})\mathbf{q}_i = (\lambda_i + \lambda)\mathbf{q}_i. That is the one-line reason ridge regression in §0.4 always has a unique solution. Finally, at a strict local minimum the Hessian is PSD, and at a saddle point it has eigenvalues of both signs (§0.6).

Python · cell 4

The singular value decomposition

Eigenvectors need a square matrix, and even then they can be complex, missing, or skewed. The singular value decomposition (SVD) works for every matrix, of any shape, with no exceptions. It says that every matrix M∈Rm×n\mathbf{M} \in \R^{m \times n} has an orthonormal basis v1,…,vn\mathbf{v}_1, \dots, \mathbf{v}_n of its input space and an orthonormal basis u1,…,um\mathbf{u}_1, \dots, \mathbf{u}_m of its output space such that

Mvi=σiui,σ1≥σ2≥⋯≥0,equivalentlyM=UΣV⊤=∑i=1kσi uivi⊤,\mathbf{M}\mathbf{v}_i = \sigma_i\mathbf{u}_i, \qquad \sigma_1 \ge \sigma_2 \ge \dots \ge 0, \qquad \text{equivalently}\qquad \mathbf{M} = \mathbf{U}\boldsymbol\Sigma\mathbf{V}^\top = \sum_{i=1}^{k}\sigma_i\,\mathbf{u}_i\mathbf{v}_i^\top ,

where k=min⁡(m,n)k = \min(m, n), U∈Rm×m\mathbf{U} \in \R^{m \times m} and V∈Rn×n\mathbf{V} \in \R^{n \times n} are orthogonal, and Σ∈Rm×n\boldsymbol\Sigma \in \R^{m \times n} holds the singular values σi\sigma_i on its diagonal and zeros elsewhere. In plain words, every linear map is a rotation of the input (V⊤\mathbf{V}^\top), a stretch of each axis by σi\sigma_i (which also drops or pads dimensions to change the shape), and a rotation into the output (U\mathbf{U}). The vi\mathbf{v}_i are the right singular vectors, the ui\mathbf{u}_i the left singular vectors.

In two dimensions this is the ellipse in the widget. The right singular vectors are the two perpendicular directions on the unit circle that land on the ellipse's axes, the left singular vectors point along those axes, and the singular values are the semi-axis lengths. The number of nonzero singular values is the rank rr. The first rr left singular vectors span the column space (everything M\mathbf{M} can output), and the last n−rn - r right singular vectors span the null space (everything it sends to zero). In code you almost always want the thin SVD, which keeps only kk columns, U∈Rm×k\mathbf{U} \in \R^{m \times k}, Σ∈Rk×k\boldsymbol\Sigma \in \R^{k \times k}, V∈Rn×k\mathbf{V} \in \R^{n \times k}.

∂ Why the SVD exists, from the spectral theorem

The matrix M⊤M∈Rn×n\mathbf{M}^\top\mathbf{M} \in \R^{n \times n} is symmetric and PSD, since x⊤M⊤Mx=∥Mx∥2≥0\mathbf{x}^\top\mathbf{M}^\top\mathbf{M}\mathbf{x} = \lVert\mathbf{M}\mathbf{x}\rVert^2 \ge 0. By the spectral theorem, M⊤M=VΛV⊤\mathbf{M}^\top\mathbf{M} = \mathbf{V}\boldsymbol\Lambda\mathbf{V}^\top with orthonormal vi\mathbf{v}_i and eigenvalues λ1≥⋯≥λn≥0\lambda_1 \ge \dots \ge \lambda_n \ge 0. Define σi=λi\sigma_i = \sqrt{\lambda_i}.

Note that ∥Mvi∥2=vi⊤M⊤Mvi=λi\lVert\mathbf{M}\mathbf{v}_i\rVert^2 = \mathbf{v}_i^\top\mathbf{M}^\top\mathbf{M}\mathbf{v}_i = \lambda_i. For each ii with σi>0\sigma_i > 0, define ui=Mvi/σi\mathbf{u}_i = \mathbf{M}\mathbf{v}_i/\sigma_i. These are orthonormal, because

ui⊤uj=vi⊤M⊤Mvjσiσj=λj vi⊤vjσiσj=δij.\mathbf{u}_i^\top\mathbf{u}_j = \frac{\mathbf{v}_i^\top\mathbf{M}^\top\mathbf{M}\mathbf{v}_j}{\sigma_i\sigma_j} = \frac{\lambda_j\,\mathbf{v}_i^\top\mathbf{v}_j}{\sigma_i\sigma_j} = \delta_{ij} .

For ii with σi=0\sigma_i = 0, ∥Mvi∥2=0\lVert\mathbf{M}\mathbf{v}_i\rVert^2 = 0, so Mvi=0=σiui\mathbf{M}\mathbf{v}_i = \mathbf{0} = \sigma_i\mathbf{u}_i for any choice of ui\mathbf{u}_i. Complete the u\mathbf{u}'s to an orthonormal basis of Rm\R^m (by Gram-Schmidt). Now Mvi=σiui\mathbf{M}\mathbf{v}_i = \sigma_i\mathbf{u}_i holds for every ii, which in matrix form is MV=UΣ\mathbf{M}\mathbf{V} = \mathbf{U}\boldsymbol\Sigma. Multiply on the right by V⊤\mathbf{V}^\top. ∎

The proof also shows the connection to eigenvalues. The squared singular values of M\mathbf{M} are the eigenvalues of M⊤M\mathbf{M}^\top\mathbf{M} (and of MM⊤\mathbf{M}\mathbf{M}^\top, apart from extra zeros), the right singular vectors are its eigenvectors, and the left singular vectors are the eigenvectors of MM⊤\mathbf{M}\mathbf{M}^\top.

A worked example you can check by hand. Take the triangular matrix M=[3045]\mathbf{M} = \begin{bmatrix}3 & 0\\ 4 & 5\end{bmatrix} again. Then M⊤M=[25202025]\mathbf{M}^\top\mathbf{M} = \begin{bmatrix}25 & 20\\ 20 & 25\end{bmatrix}, with eigenvalues 4545 and 55 and eigenvectors v1=(1,1)/2\mathbf{v}_1 = (1, 1)/\sqrt2 and v2=(1,−1)/2\mathbf{v}_2 = (1, -1)/\sqrt2. So σ1=45=35≈6.708\sigma_1 = \sqrt{45} = 3\sqrt5 \approx 6.708 and σ2=5≈2.236\sigma_2 = \sqrt5 \approx 2.236. The left singular vectors are u1=Mv1/σ1=(1,3)/10\mathbf{u}_1 = \mathbf{M}\mathbf{v}_1/\sigma_1 = (1, 3)/\sqrt{10} and u2=(3,−1)/10\mathbf{u}_2 = (3, -1)/\sqrt{10}. As a check, σ1σ2=15=∣det⁡M∣\sigma_1\sigma_2 = 15 = |\det\mathbf{M}|, the area scaling.

Compare with the eigenvalues, 3 and 5. The matrix stretches some direction by 6.7, far more than its largest eigenvalue suggests, because its eigenvectors are skewed. For a symmetric matrix the two decompositions agree (the singular values are ∣λi∣|\lambda_i| and the singular vectors are eigenvectors, up to sign), but in general they answer different questions. Eigenvalues govern what happens after many repeated applications, Mk\mathbf{M}^k. Singular values govern what one application can do. One inequality always holds, ρ(M)≤σ1\rho(\mathbf{M}) \le \sigma_1, since ∣λ∣ ∥q∥=∥Mq∥≤σ1∥q∥|\lambda|\,\lVert\mathbf{q}\rVert = \lVert\mathbf{M}\mathbf{q}\rVert \le \sigma_1\lVert\mathbf{q}\rVert for any eigenpair.

Python · cell 5

Matrix norms

How big is a matrix? There are several honest answers, and the three that matter most are all functions of the singular values.

  • The spectral norm, ∥M∥2=max⁡x≠0∥Mx∥/∥x∥=σ1\lVert\mathbf{M}\rVert_2 = \max_{\mathbf{x} \neq \mathbf{0}} \lVert\mathbf{M}\mathbf{x}\rVert/\lVert\mathbf{x}\rVert = \sigma_1, the largest stretch of any direction (also called the operator norm). To see that it equals σ1\sigma_1, write ∥Mx∥2/∥x∥2=x⊤M⊤Mx/x⊤x\lVert\mathbf{M}\mathbf{x}\rVert^2/\lVert\mathbf{x}\rVert^2 = \mathbf{x}^\top\mathbf{M}^\top\mathbf{M}\mathbf{x}/\mathbf{x}^\top\mathbf{x}, a Rayleigh quotient of M⊤M\mathbf{M}^\top\mathbf{M}, whose maximum is its top eigenvalue σ12\sigma_1^2.
  • The Frobenius norm, ∥M∥F=∑ijMij2=∑iσi2\lVert\mathbf{M}\rVert_F = \sqrt{\sum_{ij} M_{ij}^2} = \sqrt{\sum_i \sigma_i^2}, the Euclidean length of all entries. The second equality holds because ∑ijMij2=tr⁡(M⊤M)\sum_{ij} M_{ij}^2 = \operatorname{tr}(\mathbf{M}^\top\mathbf{M}), and the trace of a symmetric matrix is the sum of its eigenvalues, here the σi2\sigma_i^2.
  • The nuclear norm, ∥M∥∗=∑iσi\lVert\mathbf{M}\rVert_* = \sum_i \sigma_i, the sum of all stretches.

In plain words, the spectral norm is the worst case over directions, the Frobenius norm is a root-mean-square over directions times a constant, and the nuclear norm is the total. All three are unchanged by rotations on either side, ∥Q1MQ2∥=∥M∥\lVert\mathbf{Q}_1\mathbf{M}\mathbf{Q}_2\rVert = \lVert\mathbf{M}\rVert for orthogonal Q1,Q2\mathbf{Q}_1, \mathbf{Q}_2, because rotations do not change singular values.

For a matrix of rank rr they are tied together by ∥M∥2≤∥M∥F≤r ∥M∥2\lVert\mathbf{M}\rVert_2 \le \lVert\mathbf{M}\rVert_F \le \sqrt r\,\lVert\mathbf{M}\rVert_2 and ∥M∥F≤∥M∥∗≤r ∥M∥F\lVert\mathbf{M}\rVert_F \le \lVert\mathbf{M}\rVert_* \le \sqrt r\,\lVert\mathbf{M}\rVert_F (the upper bounds are Cauchy-Schwarz on the rr nonzero singular values). The ratio

srank⁡(M)=∥M∥F2∥M∥22=∑iσi2σ12∈[1,r]\operatorname{srank}(\mathbf{M}) = \frac{\lVert\mathbf{M}\rVert_F^2}{\lVert\mathbf{M}\rVert_2^2} = \frac{\sum_i \sigma_i^2}{\sigma_1^2} \in [1, r]

is the stable rank, a count of "how many directions really matter" that, unlike the rank, does not jump when tiny singular values appear or vanish. The spectral norm is also submultiplicative, ∥AB∥2≤∥A∥2∥B∥2\lVert\mathbf{A}\mathbf{B}\rVert_2 \le \lVert\mathbf{A}\rVert_2\lVert\mathbf{B}\rVert_2, since stretching by at most σ1(B)\sigma_1(\mathbf{B}) and then at most σ1(A)\sigma_1(\mathbf{A}) stretches by at most their product.

normin singular valueswhat it measureswhere you meet it
spectral ∥⋅∥2\lVert\cdot\rVert_2σ1\sigma_1largest stretch, the Lipschitz constant of x↦Mx\mathbf{x} \mapsto \mathbf{M}\mathbf{x}RNN gradient bounds (§3.3), spectral normalization, σReparam (§5.7), Muon (§8.6)
Frobenius ∥⋅∥F\lVert\cdot\rVert_F∑σi2\sqrt{\sum\sigma_i^2}total energy, the length of the entries as one vectorweight decay, low-rank approximation error, gradient clipping (§0.6)
nuclear ∥⋅∥∗\lVert\cdot\rVert_*∑σi\sum\sigma_itotal stretch, the tightest convex stand-in for ranklow-rank matrix recovery, the dual of the spectral norm in Muon

The spectral norm deserves one more sentence, because it bounds how much a whole network can amplify a perturbation. With activations whose slopes are at most 1 (ReLU and tanh, for example), a stack of linear layers satisfies ∥f(x)−f(y)∥≤∏l∥Wl∥2 ∥x−y∥\lVert f(\mathbf{x}) - f(\mathbf{y})\rVert \le \prod_l \lVert\mathbf{W}_l\rVert_2\,\lVert\mathbf{x} - \mathbf{y}\rVert. Spectral normalization (Miyato et al., 2018) divides each weight matrix by an estimate of its spectral norm, so every layer is at most 1-Lipschitz, which stabilized GAN training. The σReparam fix for attention entropy collapse in §5.7 uses the same estimate.

Python · cell 6

Low-rank approximation and the Eckart-Young theorem

The SVD writes a matrix as a sum of rank-one pieces, M=∑iσiuivi⊤\mathbf{M} = \sum_i \sigma_i\mathbf{u}_i\mathbf{v}_i^\top, ordered from the largest stretch to the smallest. The obvious way to compress it is to keep the first rr pieces,

Mr=∑i=1rσi uivi⊤=U:,:r Σ:r,:r V:,:r⊤,\mathbf{M}_r = \sum_{i=1}^{r}\sigma_i\,\mathbf{u}_i\mathbf{v}_i^\top = \mathbf{U}_{:, :r}\,\boldsymbol\Sigma_{:r, :r}\,\mathbf{V}_{:, :r}^\top ,

the truncated SVD. It needs r(m+n+1)r(m + n + 1) numbers instead of mnmn. The Eckart-Young theorem says that nothing of rank rr does better.

The Eckart-Young theorem (Eckart & Young, 1936, for the Frobenius norm, and Mirsky, 1960, for every rotation-invariant norm). For every matrix B\mathbf{B} of rank at most rr,

∥M−B∥2≥σr+1,∥M−B∥F2≥∑i>rσi2,\lVert\mathbf{M} - \mathbf{B}\rVert_2 \ge \sigma_{r+1}, \qquad \lVert\mathbf{M} - \mathbf{B}\rVert_F^2 \ge \sum_{i > r}\sigma_i^2,

and the truncated SVD Mr\mathbf{M}_r achieves both bounds. In plain words, the best rank-rr approximation keeps the rr largest stretches, and its error is exactly what was thrown away, the next singular value in the spectral norm and the root of the sum of the remaining squared singular values in the Frobenius norm.

The equality part needs no work. M−Mr=∑i>rσiuivi⊤\mathbf{M} - \mathbf{M}_r = \sum_{i > r}\sigma_i\mathbf{u}_i\mathbf{v}_i^\top is itself written as an SVD, with singular values σr+1,σr+2,…\sigma_{r+1}, \sigma_{r+2}, \dots, so its spectral norm is σr+1\sigma_{r+1} and its Frobenius norm is ∑i>rσi2\sqrt{\sum_{i>r}\sigma_i^2}. The lower bounds are the real content.

∂ Proof of the Eckart-Young theorem

The spectral norm. Let B∈Rm×n\mathbf{B} \in \R^{m \times n} have rank at most rr. Its null space has dimension at least n−rn - r. The span of the top r+1r + 1 right singular vectors, v1,…,vr+1\mathbf{v}_1, \dots, \mathbf{v}_{r+1}, has dimension r+1r + 1. Two subspaces of Rn\R^n whose dimensions add up to more than nn must share a nonzero vector, so there is a unit vector w=∑i≤r+1civi\mathbf{w} = \sum_{i \le r+1} c_i\mathbf{v}_i with ∑ci2=1\sum c_i^2 = 1 and Bw=0\mathbf{B}\mathbf{w} = \mathbf{0}. Then

∥M−B∥22≥∥(M−B)w∥2=∥Mw∥2=∥∑i≤r+1ciσiui∥2=∑i≤r+1ci2σi2≥σr+12.\lVert\mathbf{M} - \mathbf{B}\rVert_2^2 \ge \lVert(\mathbf{M} - \mathbf{B})\mathbf{w}\rVert^2 = \lVert\mathbf{M}\mathbf{w}\rVert^2 = \Big\lVert\sum_{i \le r+1} c_i\sigma_i\mathbf{u}_i\Big\rVert^2 = \sum_{i \le r+1} c_i^2\sigma_i^2 \ge \sigma_{r+1}^2 .

A consequence, Weyl's inequality for singular values. For any matrices X,Y\mathbf{X}, \mathbf{Y} of the same shape and indices i,j≥1i, j \ge 1, σi+j−1(X+Y)≤σi(X)+σj(Y)\sigma_{i+j-1}(\mathbf{X} + \mathbf{Y}) \le \sigma_i(\mathbf{X}) + \sigma_j(\mathbf{Y}). To prove it, let Xi−1\mathbf{X}_{i-1} and Yj−1\mathbf{Y}_{j-1} be the truncated SVDs of ranks i−1i - 1 and j−1j - 1. Their sum has rank at most i+j−2i + j - 2, so by the spectral-norm bound just proved, applied to X+Y\mathbf{X} + \mathbf{Y},

σi+j−1(X+Y)≤∥X+Y−Xi−1−Yj−1∥2≤∥X−Xi−1∥2+∥Y−Yj−1∥2=σi(X)+σj(Y).\sigma_{i+j-1}(\mathbf{X} + \mathbf{Y}) \le \lVert\mathbf{X} + \mathbf{Y} - \mathbf{X}_{i-1} - \mathbf{Y}_{j-1}\rVert_2 \le \lVert\mathbf{X} - \mathbf{X}_{i-1}\rVert_2 + \lVert\mathbf{Y} - \mathbf{Y}_{j-1}\rVert_2 = \sigma_i(\mathbf{X}) + \sigma_j(\mathbf{Y}) .

The Frobenius norm. Apply Weyl with X=M−B\mathbf{X} = \mathbf{M} - \mathbf{B}, Y=B\mathbf{Y} = \mathbf{B}, and j=r+1j = r + 1. Since B\mathbf{B} has rank at most rr, σr+1(B)=0\sigma_{r+1}(\mathbf{B}) = 0, so σi+r(M)≤σi(M−B)\sigma_{i+r}(\mathbf{M}) \le \sigma_i(\mathbf{M} - \mathbf{B}) for every ii. Square and sum over ii,

∥M−B∥F2=∑i≥1σi(M−B)2≥∑i≥1σi+r(M)2=∑k>rσk2.∎\lVert\mathbf{M} - \mathbf{B}\rVert_F^2 = \sum_{i \ge 1}\sigma_i(\mathbf{M} - \mathbf{B})^2 \ge \sum_{i \ge 1}\sigma_{i+r}(\mathbf{M})^2 = \sum_{k > r}\sigma_k^2 . \qquad ∎

The fraction of the squared Frobenius norm that the rank-rr approximation keeps, ∑i≤rσi2/∑iσi2\sum_{i \le r}\sigma_i^2 / \sum_i\sigma_i^2, is often called the energy it captures, and one minus it is the squared relative error. So everything about how compressible a matrix is lives in how fast its singular values fall. The cell builds a 60×4060 \times 40 matrix whose singular values decay like 0.8i0.8^i, checks that the truncated SVD's errors are exactly the predicted tails, and then tilts the kept subspace slightly in 2,000 random ways. Every tilt is worse.

Python · cell 7
Core

Best low-rank approximation and its error

Implement three functions.

  • low_rank(M, r) returns the best rank-r approximation of M (shape (m, n)) in the Frobenius and spectral norms.
  • low_rank_errors(s, r) takes the singular values s of a matrix (descending) and returns (spectral_error, frobenius_error) of its best rank-r approximation, from the singular values alone, without building any matrix. For r >= len(s) both are 0.
  • rank_for_energy(s, frac) returns the smallest r whose best rank-r approximation keeps at least the fraction frac of the squared Frobenius norm.
Hidden tests, hints, and AI help, from $1.99 a month.

How low rank is a real model's weight matrix?

Random matrices are not compressible. The singular values of an m×nm \times n Gaussian matrix spread fairly evenly over a band (the Marchenko-Pastur law describes the shape), so a small rank keeps only a small share of the energy. Trained weights are different, and how different depends on the matrix. The widget computes the full spectrum of every weight matrix of a real trained Transformer, the two-layer character-level GPT that Chapter 6 trains on Shakespeare's sonnets, and compares each with a random Gaussian matrix of the same shape and Frobenius norm.

How much of a trained weight matrix lives in a few directions?
Loading interactive figure…

The differences are large. The learned position embeddings (a 128×64128 \times 64 matrix) have a stable rank of 1.4 and 99% of their energy in eight directions. Adjacent positions have an average cosine similarity of 0.98, so the 128 vectors trace a smooth curve through a few dimensions, and position 0, whose vector is about twice as long as the rest, supplies much of the top direction. The query and key matrices of the first layer keep 71% and 83% of their energy at rank 8, against 38% for a random matrix, which suggests that this model's attention compares characters along only a few directions. The value and output matrices sit much closer to random. At real scale the same questions matter in two ways. Trained weight matrices of large models have heavy-tailed spectra rather than a few dominant directions (Martin & Mahoney, 2021), so they compress poorly by plain truncation. But the change that fine-tuning makes is often very low rank (Aghajanyan et al., 2021, could fine-tune RoBERTa to 90% of full performance on one task with only 200 parameters), which is the bet LoRA makes.

Power iteration

The opening experiment was an algorithm. Power iteration finds the top eigenvector of a matrix by multiplying a random vector by it over and over, normalizing each time so nothing overflows,

xk+1=Axk∥Axk∥,λ^k=R(xk)=xk⊤Axk.\mathbf{x}_{k+1} = \frac{\mathbf{A}\mathbf{x}_k}{\lVert\mathbf{A}\mathbf{x}_k\rVert}, \qquad \hat\lambda_k = R(\mathbf{x}_k) = \mathbf{x}_k^\top\mathbf{A}\mathbf{x}_k .

Why does it work, and how fast? Take A\mathbf{A} symmetric with eigenvalues ordered ∣λ1∣>∣λ2∣≥…|\lambda_1| > |\lambda_2| \ge \dots and write the start as x0=∑iciqi\mathbf{x}_0 = \sum_i c_i\mathbf{q}_i. Normalization only rescales, so xk\mathbf{x}_k points along

Akx0=∑iciλikqi=λ1k(c1q1+∑i≥2ci(λiλ1)kqi).\mathbf{A}^k\mathbf{x}_0 = \sum_i c_i\lambda_i^k\mathbf{q}_i = \lambda_1^k\Big(c_1\mathbf{q}_1 + \sum_{i \ge 2} c_i\Big(\frac{\lambda_i}{\lambda_1}\Big)^k\mathbf{q}_i\Big) .

Every term but the first shrinks by at least ∣λ2/λ1∣|\lambda_2/\lambda_1| per step, so the tangent of the angle between xk\mathbf{x}_k and q1\mathbf{q}_1 is at most ∣λ2/λ1∣k|\lambda_2/\lambda_1|^k times its starting value. In plain words, each multiplication amplifies the top direction more than any other, and the error shrinks geometrically at a rate set by the gap between the two largest eigenvalues. The eigenvalue estimate converges even faster. The Rayleigh quotient is a weighted average of eigenvalues with weights proportional to ci2λi2kc_i^2\lambda_i^{2k}, so its error is of order (λ2/λ1)2k(\lambda_2/\lambda_1)^{2k}, the square of the vector's error. This is a general feature of Rayleigh quotients for symmetric matrices, a first-order error in the vector gives only a second-order error in the eigenvalue.

Python · cell 8

Three ways power iteration fails are worth knowing. If ∣λ1∣=∣λ2∣|\lambda_1| = |\lambda_2| (eigenvalues 33 and −3-3, say) the direction never settles. If the start has c1=0c_1 = 0 exactly, it converges to the wrong eigenvector, although a random start makes this a probability-zero event and rounding error rescues it anyway. And if the gap is small, it is slow. The number of steps to gain a factor of ee is 1/ln⁡(λ1/λ2)1/\ln(\lambda_1/\lambda_2), about λ1/(λ1−λ2)\lambda_1/(\lambda_1 - \lambda_2), so a gap of 1% needs about a hundred steps per factor of ee.

The same loop gives the spectral norm of any matrix M\mathbf{M}, by running it on M⊤M\mathbf{M}^\top\mathbf{M} without ever forming that product, alternating u←Mv/∥Mv∥\mathbf{u} \leftarrow \mathbf{M}\mathbf{v}/\lVert\mathbf{M}\mathbf{v}\rVert and v←M⊤u/∥M⊤u∥\mathbf{v} \leftarrow \mathbf{M}^\top\mathbf{u}/\lVert\mathbf{M}^\top\mathbf{u}\rVert, with σ1≈u⊤Mv\sigma_1 \approx \mathbf{u}^\top\mathbf{M}\mathbf{v}. Spectral normalization runs a single step of this per training step and keeps u\mathbf{u} between steps, since the weights change little, and the σReparam fix of §5.7 is built on the same estimate. And since a Hessian-vector product costs about as much as a gradient (§0.3), power iteration with Hessian-vector products finds the sharpness of a network with billions of parameters without ever forming its Hessian.

To get the top kk eigenvectors at once, multiply a block of kk vectors and re-orthonormalize them with a QR factorization each step, which keeps them from all collapsing onto q1\mathbf{q}_1. This is orthogonal iteration (or subspace iteration), and it converges at the rate ∣λk+1/λk∣|\lambda_{k+1}/\lambda_k|. A final Rayleigh-Ritz step, an eigendecomposition of the small k×kk \times k matrix X⊤AX\mathbf{X}^\top\mathbf{A}\mathbf{X}, rotates the block into the best individual eigenvector estimates. Production solvers refine the same ideas. Lanczos methods (scipy.sparse.linalg.eigsh) reuse every vector the iteration produces, and randomized SVD (Halko, Martinsson & Tropp, 2011, implemented as torch.svd_lowrank) uses one random block multiplication plus a few power steps to get the top singular vectors of a huge matrix.

Interview

Power iteration and orthogonal iteration

For a symmetric positive semidefinite matrix A (a covariance, say), implement

  • power_iteration(A, iters, rng) returning (lam, v), the top eigenvalue (as a Rayleigh quotient) and a unit eigenvector, starting from rng.normal(size=n);
  • top_k_eigh(A, k, iters, rng) returning (lams, V) with lams of shape (k,) in descending order and V of shape (n, k) with orthonormal columns, by orthogonal iteration with a QR step every iteration and a Rayleigh-Ritz step at the end.

Do not call np.linalg.eig, eigh, or svd on A itself. (You may use np.linalg.eigh on the small k×kk \times k matrix in the Rayleigh-Ritz step.)

Hidden tests, hints, and AI help, from $1.99 a month.

Condition numbers

The condition number of an invertible matrix is the ratio of its largest to its smallest stretch,

κ(A)=σmax⁡σmin⁡=∥A∥2 ∥A−1∥2,\kappa(\mathbf{A}) = \frac{\sigma_{\max}}{\sigma_{\min}} = \lVert\mathbf{A}\rVert_2\,\lVert\mathbf{A}^{-1}\rVert_2 ,

and it is infinite for a singular matrix. For a symmetric positive definite matrix it is λmax⁡/λmin⁡\lambda_{\max}/\lambda_{\min}, the same κ\kappa that set the speed of gradient descent in §0.6. It has a second meaning, just as important, which is how much a matrix amplifies errors.

Solve Ax=b\mathbf{A}\mathbf{x} = \mathbf{b}, but with the right-hand side slightly wrong, b+δb\mathbf{b} + \delta\mathbf{b} (from measurement noise, or just rounding). The solution moves by δx=A−1δb\delta\mathbf{x} = \mathbf{A}^{-1}\delta\mathbf{b}, so ∥δx∥≤∥δb∥/σmin⁡\lVert\delta\mathbf{x}\rVert \le \lVert\delta\mathbf{b}\rVert/\sigma_{\min}. Meanwhile ∥b∥=∥Ax∥≤σmax⁡∥x∥\lVert\mathbf{b}\rVert = \lVert\mathbf{A}\mathbf{x}\rVert \le \sigma_{\max}\lVert\mathbf{x}\rVert, so 1/∥x∥≤σmax⁡/∥b∥1/\lVert\mathbf{x}\rVert \le \sigma_{\max}/\lVert\mathbf{b}\rVert. Multiplying the two inequalities,

∥δx∥∥x∥≤κ(A) ∥δb∥∥b∥.\frac{\lVert\delta\mathbf{x}\rVert}{\lVert\mathbf{x}\rVert} \le \kappa(\mathbf{A})\,\frac{\lVert\delta\mathbf{b}\rVert}{\lVert\mathbf{b}\rVert} .

In plain words, a relative error in the data can come back κ\kappa times larger in the answer. The bound is tight, reached when b\mathbf{b} lies along the top left singular vector and δb\delta\mathbf{b} along the bottom one. A practical rule follows. You lose about log⁡10κ\log_{10}\kappa significant digits. Float64 carries about 16 digits, so a matrix with κ=1012\kappa = 10^{12} leaves you four. Float32 carries about 7 and bfloat16 under 3 (§0.9), so a solve with κ=1000\kappa = 1000 in bfloat16 returns noise.

This is why you should never solve least squares by forming X⊤X\mathbf{X}^\top\mathbf{X} (the "normal equations") when accuracy matters. The singular values of X⊤X\mathbf{X}^\top\mathbf{X} are σi2\sigma_i^2, so κ(X⊤X)=κ(X)2\kappa(\mathbf{X}^\top\mathbf{X}) = \kappa(\mathbf{X})^2, and squaring the condition number doubles the digits lost. np.linalg.lstsq works with X\mathbf{X} directly through the SVD. Ridge regularization helps for the same reason, κ(X⊤X+λI)=(σ12+λ)/(σn2+λ)\kappa(\mathbf{X}^\top\mathbf{X} + \lambda\mathbf{I}) = (\sigma_1^2 + \lambda)/(\sigma_n^2 + \lambda), which a modest λ\lambda can bring down by orders of magnitude.

Python · cell 9

The error grows with κ\kappa and stays below the bound κ εmach\kappa\,\varepsilon_{\text{mach}}, where εmach≈2.2×10−16\varepsilon_{\text{mach}} \approx 2.2 \times 10^{-16} is the float64 rounding error. At n=12n = 12 the Hilbert matrix has κ≈1016\kappa \approx 10^{16}, every digit is gone, and the "solution" is 10% wrong even though nothing went wrong in the code. In the polynomial fit, the normal equations lose seven orders of magnitude of accuracy that lstsq keeps.

Conditioning shows up throughout training. Badly scaled input features make a linear model's Hessian X⊤X/N\mathbf{X}^\top\mathbf{X}/N ill-conditioned, which is why standardizing features speeds up gradient descent. Adam's per-parameter scaling is a crude diagonal attempt to reduce the condition number. And Jordan, who introduced Muon, observed that the updates SGD with momentum and Adam produce for Transformer weight matrices have very high condition numbers, dominated by a few directions, which Muon fixes by setting every singular value of the update to 1 (§8.6).

Projections and least squares

Projecting a vector onto a line is the most basic linear-algebra operation in machine learning. For a unit vector u\mathbf{u}, the closest point to x\mathbf{x} on the line through u\mathbf{u} is (u⊤x) u=uu⊤x(\mathbf{u}^\top\mathbf{x})\,\mathbf{u} = \mathbf{u}\mathbf{u}^\top\mathbf{x}, and what remains, (I−uu⊤)x(\mathbf{I} - \mathbf{u}\mathbf{u}^\top)\mathbf{x}, is perpendicular to u\mathbf{u}. For a subspace with an orthonormal basis given by the columns of Q∈Rn×k\mathbf{Q} \in \R^{n \times k}, add up the pieces, P=QQ⊤\mathbf{P} = \mathbf{Q}\mathbf{Q}^\top.

If the subspace is spanned by the columns of a general matrix A∈Rn×k\mathbf{A} \in \R^{n \times k} of full column rank, find the closest point Aw\mathbf{A}\mathbf{w} to x\mathbf{x} by requiring the residual to be perpendicular to every column, A⊤(x−Aw)=0\mathbf{A}^\top(\mathbf{x} - \mathbf{A}\mathbf{w}) = \mathbf{0}. That gives w=(A⊤A)−1A⊤x\mathbf{w} = (\mathbf{A}^\top\mathbf{A})^{-1}\mathbf{A}^\top\mathbf{x} and

P=A(A⊤A)−1A⊤,P2=P,P⊤=P.\mathbf{P} = \mathbf{A}(\mathbf{A}^\top\mathbf{A})^{-1}\mathbf{A}^\top, \qquad \mathbf{P}^2 = \mathbf{P}, \qquad \mathbf{P}^\top = \mathbf{P} .

In plain words, projecting twice is the same as projecting once, and the projection is symmetric. Its eigenvalues are therefore only 0 and 1 (from P2=P\mathbf{P}^2 = \mathbf{P}, any eigenvalue satisfies λ2=λ\lambda^2 = \lambda), with 1 on the subspace and 0 on its orthogonal complement, and its trace is the dimension kk. Look again at the equation for w\mathbf{w}. It is the least-squares normal equation. So least squares is a projection, of the targets y\mathbf{y} onto the column space of the features, and the fitted values are Py\mathbf{P}\mathbf{y}.

The SVD gives the general version. The pseudoinverse M+=VΣ+U⊤\mathbf{M}^+ = \mathbf{V}\boldsymbol\Sigma^+\mathbf{U}^\top, where Σ+\boldsymbol\Sigma^+ inverts the nonzero singular values and leaves the zeros, returns the minimum-norm least-squares solution w=M+y\mathbf{w} = \mathbf{M}^+\mathbf{y} even when M\mathbf{M} is rank deficient, and MM+\mathbf{M}\mathbf{M}^+ is the projection onto its column space.

Python · cell 10

The last two lines remove a single direction from a vector, which is a real technique. Removing a "gender direction" from word embeddings was an early debiasing method (Bolukbasi et al., 2016), and projecting one learned direction out of a model's internal activations is how researchers delete a concept the network represents, the idea behind activation steering. Every PCA plot is a projection onto two directions, and the output of an attention head always lies in the span of its value vectors.

Whitening

Whitening transforms data so that its features are uncorrelated with unit variance, its covariance becoming I\mathbf{I}. Center the data X∈RN×d\mathbf{X} \in \R^{N \times d} (rows are examples) to Xc\mathbf{X}_c, and let C=Xc⊤Xc/N=QΛQ⊤\mathbf{C} = \mathbf{X}_c^\top\mathbf{X}_c/N = \mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^\top be its sample covariance. In this subsection W∈Rd×d\mathbf{W} \in \R^{d \times d} is a whitening matrix, applied to each example as z=Wxc\mathbf{z} = \mathbf{W}\mathbf{x}_c, so the whitened data are Z=XcW⊤\mathbf{Z} = \mathbf{X}_c\mathbf{W}^\top with covariance WCW⊤\mathbf{W}\mathbf{C}\mathbf{W}^\top. Any W\mathbf{W} with WCW⊤=I\mathbf{W}\mathbf{C}\mathbf{W}^\top = \mathbf{I} whitens. Two choices are standard,

WPCA=Λ−1/2Q⊤,WZCA=QΛ−1/2Q⊤=C−1/2.\mathbf{W}_{\text{PCA}} = \boldsymbol\Lambda^{-1/2}\mathbf{Q}^\top, \qquad \mathbf{W}_{\text{ZCA}} = \mathbf{Q}\boldsymbol\Lambda^{-1/2}\mathbf{Q}^\top = \mathbf{C}^{-1/2} .

Both work, since for instance WPCACWPCA⊤=Λ−1/2Q⊤QΛQ⊤QΛ−1/2=I\mathbf{W}_{\text{PCA}}\mathbf{C}\mathbf{W}_{\text{PCA}}^\top = \boldsymbol\Lambda^{-1/2}\mathbf{Q}^\top\mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^\top\mathbf{Q}\boldsymbol\Lambda^{-1/2} = \mathbf{I}. In plain words, PCA whitening rotates the data onto its principal axes and rescales each axis to unit variance. ZCA whitening does the same and then rotates back, so the features keep their original orientation.

In fact every whitening matrix is one of these times a rotation. If W1\mathbf{W}_1 and W2\mathbf{W}_2 both whiten, then R=W2W1−1\mathbf{R} = \mathbf{W}_2\mathbf{W}_1^{-1} satisfies RR⊤=W2W1−1W1−⊤W2⊤=W2CW2⊤=I\mathbf{R}\mathbf{R}^\top = \mathbf{W}_2\mathbf{W}_1^{-1}\mathbf{W}_1^{-\top}\mathbf{W}_2^\top = \mathbf{W}_2\mathbf{C}\mathbf{W}_2^\top = \mathbf{I}, using W1−1W1−⊤=(W1⊤W1)−1=C\mathbf{W}_1^{-1}\mathbf{W}_1^{-\top} = (\mathbf{W}_1^\top\mathbf{W}_1)^{-1} = \mathbf{C}, which is the whitening condition for W1\mathbf{W}_1 rearranged. So the choice among whitenings is a choice of rotation, and ZCA is special. It is the whitening that moves the data the least.

∂ ZCA is the whitening closest to the original data

For a whitening matrix W\mathbf{W}, the mean squared distance between whitened and original data is

1N∥XcW⊤−Xc∥F2=tr⁡(WCW⊤)−2tr⁡(WC)+tr⁡(C)=d−2tr⁡(WC)+tr⁡(C),\frac1N\lVert\mathbf{X}_c\mathbf{W}^\top - \mathbf{X}_c\rVert_F^2 = \operatorname{tr}(\mathbf{W}\mathbf{C}\mathbf{W}^\top) - 2\operatorname{tr}(\mathbf{W}\mathbf{C}) + \operatorname{tr}(\mathbf{C}) = d - 2\operatorname{tr}(\mathbf{W}\mathbf{C}) + \operatorname{tr}(\mathbf{C}),

so minimizing it means maximizing tr⁡(WC)\operatorname{tr}(\mathbf{W}\mathbf{C}). Every whitening matrix is W=RC−1/2\mathbf{W} = \mathbf{R}\mathbf{C}^{-1/2} for an orthogonal R\mathbf{R}, so tr⁡(WC)=tr⁡(RC1/2)\operatorname{tr}(\mathbf{W}\mathbf{C}) = \operatorname{tr}(\mathbf{R}\mathbf{C}^{1/2}). Write C1/2=∑iλi qiqi⊤\mathbf{C}^{1/2} = \sum_i \sqrt{\lambda_i}\,\mathbf{q}_i\mathbf{q}_i^\top. Then tr⁡(RC1/2)=∑iλi qi⊤Rqi≤∑iλi\operatorname{tr}(\mathbf{R}\mathbf{C}^{1/2}) = \sum_i\sqrt{\lambda_i}\,\mathbf{q}_i^\top\mathbf{R}\mathbf{q}_i \le \sum_i\sqrt{\lambda_i}, because qi⊤Rqi≤∥qi∥ ∥Rqi∥=1\mathbf{q}_i^\top\mathbf{R}\mathbf{q}_i \le \lVert\mathbf{q}_i\rVert\,\lVert\mathbf{R}\mathbf{q}_i\rVert = 1. Equality holds for R=I\mathbf{R} = \mathbf{I}, which is ZCA. Kessy, Lewin & Strimmer (2018) compare this and four other natural whitenings in detail. ∎

Two practical notes. Divide by λi+ϵ\sqrt{\lambda_i + \epsilon} rather than λi\sqrt{\lambda_i}, because directions with nearly zero variance are mostly noise, and whitening would blow that noise up to unit size. And whitening is everywhere once you look for it. BatchNorm and LayerNorm (§0.7) are whitening with a diagonal C\mathbf{C}, rescaling each feature without decorrelating them. The Mahalanobis distance of §0.4 is the ordinary distance after ZCA whitening. Whitening sentence embeddings before comparing them with cosine similarity is a cheap fix for their anisotropy (Su et al., 2021), as §1.9 shows. And Muon's update is a whitened gradient. If the gradient is G=UΣV⊤\mathbf{G} = \mathbf{U}\boldsymbol\Sigma\mathbf{V}^\top (thin SVD, full rank), then (GG⊤)−1/2G=UΣ−1U⊤UΣV⊤=UV⊤(\mathbf{G}\mathbf{G}^\top)^{-1/2}\mathbf{G} = \mathbf{U}\boldsymbol\Sigma^{-1}\mathbf{U}^\top\mathbf{U}\boldsymbol\Sigma\mathbf{V}^\top = \mathbf{U}\mathbf{V}^\top.

Python · cell 11
Core

PCA and ZCA whitening

Implement whiten(X, method="zca", eps=0.0) for data X of shape (N, d), returning (Z, W, mu) where mu is the mean (shape (d,)), W is the (d, d) whitening matrix, and Z = (X - mu) @ W.T. Use the covariance with divisor NN and the eigenvalues λi+ϵ\lambda_i + \epsilon. For method="pca", W is Λ−1/2Q⊤\boldsymbol\Lambda^{-1/2}\mathbf{Q}^\top with the eigenvalues in descending order, so the first output coordinate is the direction of largest variance. For method="zca", W is QΛ−1/2Q⊤\mathbf{Q}\boldsymbol\Lambda^{-1/2}\mathbf{Q}^\top.

Hidden tests, hints, and AI help, from $1.99 a month.

PCA is the same decomposition again

Principal component analysis, which §1.6 uses to draw embedding spaces, is the spectral theorem applied to C\mathbf{C} and the SVD applied to Xc\mathbf{X}_c, and the two agree. If Xc=UΣV⊤\mathbf{X}_c = \mathbf{U}\boldsymbol\Sigma\mathbf{V}^\top, then C=Xc⊤Xc/N=V(Σ2/N)V⊤\mathbf{C} = \mathbf{X}_c^\top\mathbf{X}_c/N = \mathbf{V}(\boldsymbol\Sigma^2/N)\mathbf{V}^\top. So the principal directions are the right singular vectors of the centered data, and the variance along direction ii is σi2/N\sigma_i^2/N. By the Rayleigh quotient, the top direction is the unit vector v\mathbf{v} that maximizes the variance v⊤Cv\mathbf{v}^\top\mathbf{C}\mathbf{v} of the projected data. By Eckart-Young, projecting onto the top kk directions gives the best rank-kk approximation of the data. Maximum variance and minimum reconstruction error are the same choice. The latent semantic analysis of §1.4 is the truncated SVD of a word co-occurrence matrix.

Where this shows up in modern models

Gradients through a recurrence

Backpropagating through T−tT - t steps of a recurrent network multiplies the gradient by T−tT - t Jacobians, each diag⁡(ϕ′(⋅)) Whh\operatorname{diag}(\phi'(\cdot))\,\mathbf{W}_{hh} (§0.8). If the activation's slope is at most γ\gamma, submultiplicativity bounds the whole product by (γ ∥Whh∥2)T−t(\gamma\,\lVert\mathbf{W}_{hh}\rVert_2)^{T-t}, so gradients must vanish when γσ1<1\gamma\sigma_1 < 1. In the long run, ∥Wk∥21/k→ρ(W)\lVert\mathbf{W}^k\rVert_2^{1/k} \to \rho(\mathbf{W}) (Gelfand's formula), so the spectral radius decides whether a linear recurrence eventually explodes. But for matrices with skewed eigenvectors the short run can look very different. The matrix below has both eigenvalues equal to 0.5, yet it more than triples a vector in one step, and the norms of its powers stay above 1 for the first four steps before they decay.

Python · cell 12

The last line is the idea behind orthogonal initialization (Saxe et al., 2014). An orthogonal matrix has every singular value equal to 1, so its powers neither shrink nor grow any vector, and gradients pass through many linear steps unchanged. §3.3 carries out the full analysis for trained RNNs.

Attention

The attention scores of one head are XWQWK⊤X⊤/dk\mathbf{X}\mathbf{W}_Q\mathbf{W}_K^\top\mathbf{X}^\top/\sqrt{d_k}, where WQ,WK∈Rd×dk\mathbf{W}_Q, \mathbf{W}_K \in \R^{d \times d_k}. The d×dd \times d matrix WQWK⊤\mathbf{W}_Q\mathbf{W}_K^\top that defines how tokens are compared has rank at most dkd_k, so each head compares tokens along only dkd_k directions, and multi-head attention (§4.5) is a sum of hh low-rank bilinear forms instead of one full-rank one. The attention matrix itself is row-stochastic (every row is a softmax, so it is nonnegative and sums to 1). Its rows sum to 1, so A1=1\mathbf{A}\mathbf{1} = \mathbf{1} and 1 is an eigenvalue, and no eigenvalue is larger in absolute value. Repeated averaging pulls every token's vector toward the same mixture, and Dong, Cordonnier & Loukas (2021) proved that a stack of pure attention layers, without residual connections or MLPs, converges to a rank-one output doubly exponentially fast in depth. The residual stream of §5.1 is part of what prevents it.

One more rank fact limits every language model. The logits for NN contexts over a vocabulary of VV tokens are HE⊤\mathbf{H}\mathbf{E}^\top, with hidden states H∈RN×d\mathbf{H} \in \R^{N \times d} and output embeddings E∈RV×d\mathbf{E} \in \R^{V \times d}, so the logit matrix has rank at most dd even though it is N×VN \times V. Yang et al. (2018) called this the softmax bottleneck and argued that natural language's true log-probability matrix has much higher rank than dd.

Python · cell 13

LoRA

LoRA (Hu et al., 2021) freezes a pretrained weight W0∈Rdout×din\mathbf{W}_0 \in \R^{d_{\text{out}} \times d_{\text{in}}} and learns an update ΔW=BA\Delta\mathbf{W} = \mathbf{B}\mathbf{A} with B∈Rdout×r\mathbf{B} \in \R^{d_{\text{out}} \times r} and A∈Rr×din\mathbf{A} \in \R^{r \times d_{\text{in}}}, so the update has rank at most rr and costs r(din+dout)r(d_{\text{in}} + d_{\text{out}}) parameters. For a 4096×40964096 \times 4096 projection with r=8r = 8 that is 65,536 instead of 16.8 million. Eckart-Young tells you exactly what you give up. If full fine-tuning would have made the update ΔW⋆\Delta\mathbf{W}^\star, the best LoRA could hope for leaves an error of ∑i>rσi(ΔW⋆)2\sqrt{\sum_{i > r}\sigma_i(\Delta\mathbf{W}^\star)^2}. In the LoRA paper, ranks from 1 to 8 performed about equally well when adapting GPT-3 175B's query and value projections on the two tasks where they compared ranks, which suggests those updates have a few dominant directions. §14.5 measures the spectra of real fine-tuning updates.

Muon

Muon (§8.6) replaces the momentum matrix G=UΣV⊤\mathbf{G} = \mathbf{U}\boldsymbol\Sigma\mathbf{V}^\top by UV⊤\mathbf{U}\mathbf{V}^\top, all singular values set to 1. The norms of this section explain why that is a principled step. Among all updates O\mathbf{O} with spectral norm at most 1, the one that decreases a linearized loss the most maximizes ⟨G,O⟩=tr⁡(G⊤O)\langle\mathbf{G}, \mathbf{O}\rangle = \operatorname{tr}(\mathbf{G}^\top\mathbf{O}). Expanding G\mathbf{G} gives ⟨G,O⟩=∑iσi ui⊤Ovi≤∑iσi=∥G∥∗\langle\mathbf{G}, \mathbf{O}\rangle = \sum_i\sigma_i\,\mathbf{u}_i^\top\mathbf{O}\mathbf{v}_i \le \sum_i\sigma_i = \lVert\mathbf{G}\rVert_*, since a matrix of spectral norm at most 1 cannot give ∣u⊤Ov∣>1|\mathbf{u}^\top\mathbf{O}\mathbf{v}| > 1 for unit vectors. The bound is reached at O=UV⊤\mathbf{O} = \mathbf{U}\mathbf{V}^\top. So UV⊤\mathbf{U}\mathbf{V}^\top is steepest descent when step size is measured in the spectral norm, and the nuclear norm is the spectral norm's dual. Muon computes it with a few matrix multiplications (Newton-Schulz iterations) instead of an SVD, because matrix multiplications are what GPUs do fastest.

Compressing a layer without changing its outputs

Truncating the SVD of a weight matrix minimizes the error in the weights. What you care about is the error in the layer's outputs on real inputs, and when the inputs are far from isotropic the two goals differ. Directions the inputs rarely use can be cut freely, and directions they use heavily must be kept. Whitening the inputs turns the second problem into the first, which is the core of activation-aware compression methods such as SVD-LLM (Wang et al., 2024). The last exercise derives it.

Research

Activation-aware low-rank compression

A linear layer computes Y=XW⊤\mathbf{Y} = \mathbf{X}\mathbf{W}^\top for weights W∈Rdout×din\mathbf{W} \in \R^{d_{\text{out}} \times d_{\text{in}}} and calibration inputs X∈RN×din\mathbf{X} \in \R^{N \times d_{\text{in}}} (full column rank). Implement activation_aware_lowrank(W, X, r) returning M\mathbf{M} of rank at most rr that minimizes the output error ∥XW⊤−XM⊤∥F\lVert\mathbf{X}\mathbf{W}^\top - \mathbf{X}\mathbf{M}^\top\rVert_F.

Derive it first. With X⊤X=LL⊤\mathbf{X}^\top\mathbf{X} = \mathbf{L}\mathbf{L}^\top (Cholesky), show that ∥XD⊤∥F=∥DL∥F\lVert\mathbf{X}\mathbf{D}^\top\rVert_F = \lVert\mathbf{D}\mathbf{L}\rVert_F for any D\mathbf{D}, and then that the answer is M=(WL)r L−1\mathbf{M} = (\mathbf{W}\mathbf{L})_r\,\mathbf{L}^{-1}, where (⋅)r(\cdot)_r is the truncated SVD.

Hidden tests, hints, and AI help, from $1.99 a month.

In PyTorch

Everything above has a direct equivalent in torch.linalg, which runs on GPUs and supports batches of matrices (a leading batch dimension is decomposed matrix by matrix).

🔥 In PyTorchfor a machine with PyTorch

Which decomposition, when

decompositionNumPy / PyTorchneedscost for n×nn \times nuse it for
Cholesky LL⊤\mathbf{L}\mathbf{L}^\topcholeskysymmetric PDn3/3n^3/3testing PD, solving with covariances, sampling Gaussians
symmetric eigen QΛQ⊤\mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^\topeigh, eigvalshsymmetricabout 9n39n^3 with vectorscovariances, Hessians, PCA, whitening
general eigen QΛQ−1\mathbf{Q}\boldsymbol\Lambda\mathbf{Q}^{-1}eigsquare (may be complex)about 25n325n^3stability of recurrences, spectral radius
QRqrany43n3\tfrac43 n^3orthonormal bases, projections, orthogonal iteration
SVD UΣV⊤\mathbf{U}\boldsymbol\Sigma\mathbf{V}^\topsvd, svdvalsanyabout 20n320n^3 with vectorsnorms, rank, low-rank approximation, pseudoinverse
iterative (power, Lanczos, randomized)eigsh, svd_lowrankonly products Ax\mathbf{A}\mathbf{x}a few dozen productstop few eigen or singular pairs of huge matrices

The costs are the standard flop counts for dense matrices from Golub and Van Loan's Matrix Computations, rounded. What matters is the order. Cholesky is the cheapest by far, and an SVD with vectors is an order of magnitude more expensive, which is why you should never compute a full SVD when you only need a norm estimate.

Read more

Watch next

🎬 Eigenvectors and eigenvalues | Chapter 14, Essence of linear algebra · 3Blue1BrownEigenvectors as the directions a transformation only stretches, drawn the way this section starts.
🎬 SVD Visualized, Singular Value Decomposition explained | SEE Matrix , Chapter 3 #SoME2 · Visual KernelRotate, stretch, rotate, animated so you can watch each factor act on the plane.
🎬 Singular Value Decomposition (the SVD) · MIT OpenCourseWareGilbert Strang on the SVD as rotation times stretch times rotation, in fourteen minutes.