Understanding matrix rank — the hidden dimension of neural network layers
A linear layer in a neural network is a matrix. A 1024 × 1024 weight matrix has just over a million parameters and looks like it should be able to do a million parameters’ worth of work. Often it can’t. The transformation it performs may live in a 50-dimensional subspace, no matter how many parameters you pour into it. The shape on disk and the expressive capacity it actually delivers are two different numbers — and the second one is called rank.
This article is about that gap. We start with what a matrix does to a point cloud in 2D, work up to the formal definitions of rank and SVD, and then look at why this one property quietly determines how big neural networks can be, how small we can compress them, and why deep transformers stay expressive at all.
The math stays light. Every formal step is preceded by a numeric or visual example, and proofs are skipped in favour of the geometric picture. By the end, the word “rank” will mean a specific picture — not a definition you memorise.
Rung 2 of the linear-algebra guided map — it assumes the dot products of cosine similarity and feeds the PCA, factorisation, and latent-bottleneck articles above it.
The hidden bottleneck
Take a 1024 × 1024 linear layer somewhere in the middle of a trained network. It has 1,048,576 parameters. Now do a singular value decomposition and look at the singular values — we’ll get to what those are shortly, but for now treat them as a sorted list of “how much work each independent direction is doing.” A common shape in practice: the first 50 or so are large, the next few hundred shrink rapidly, and the tail is essentially zero.
The layer’s 1024 → 1024 mapping, in other words, lives in a roughly 50-dimensional subspace of the output. The other ~974 dimensions are linear combinations of the first 50; they carry no new information. A 1024 × 50 matrix followed by a 50 × 1024 matrix — just over 100,000 parameters — would produce the same mapping. The original layer was paying ten times the storage and compute for the same transformation.
The number that captures this gap is the matrix’s rank (or, in this messier real-world version, its effective rank). The rest of this article is about what rank is, how to read it off a matrix, and why neural networks are full of layers whose rank is much smaller than their shape suggests.
A matrix is a transformation
Before we can talk about rank, we need a sharper picture of what a matrix actually does. Forget for a moment that matrices are grids of numbers. A matrix is a function — it takes a vector in and produces a vector out:
For a 2 × 2 matrix, that function takes a 2D point and returns a 2D point. Apply it to every point on a circle and you get a new shape — usually an ellipse, but sometimes a line, and in degenerate cases a single point.
The shape of that output is what rank measures. A 2 × 2 matrix that turns a circle into a full ellipse has rank 2: both input dimensions made it through to the output. A matrix that crushes the same circle onto a line has rank 1: one dimension survived, the other was annihilated. A matrix that maps everything to the origin has rank 0.
That picture is what the rest of the article formalises. Before we get there, it’s worth seeing it move.
Demo: rank as a geometric collapse
Drag the sliders. Each one is one entry of a 2 × 2 matrix W. The grey circle on the left is the input — every point on the unit circle. The coloured shape on the right is what W does to it. The bars below the matrix are the two singular values of W — the lengths of the ellipse’s two axes. The rank shown beneath them is just the count of singular values that aren’t (numerically) zero.
A few things to try:
- Set
Wto the identity matrix. The output is the same circle. Both singular values are 1. Rank 2. - Stretch one direction by pulling a diagonal slider. The output becomes an ellipse. Singular values become unequal. Still rank 2.
- Set the second column equal to the first. The two columns now point in the same direction — they are linearly dependent. The output ellipse collapses to a line. The smaller singular value drops to zero. Rank is now 1.
- Set every entry to zero. Output collapses to the origin. Both singular values are zero. Rank 0.
The thing the demo is teaching is that rank is not really about the numbers in the matrix; it’s about the geometric shape of the output. Rank counts how many dimensions of the input survive the trip through W. When two columns of W point in the same direction, one of them is redundant — the matrix has fewer genuinely independent directions than its shape suggests.
Linear independence and the column space
Let’s put a name to what we just saw. The columns of a matrix are vectors. For a 2 × 2 matrix
the columns are and . When you multiply W by an input vector , you get
The output is a weighted combination of the columns. So the set of all possible outputs — every vector W can produce, over every possible input — is exactly the set of all weighted combinations of and . That set is called the column space of W.
If and point in different directions, their combinations sweep out the entire plane — the column space is all of . If they point in the same direction (one is a scalar multiple of the other), all combinations lie on a single line — the column space is one-dimensional. If they’re both zero, the column space is just the origin.
Two vectors are linearly independent if neither is a scalar multiple of the other. More generally, a set of vectors is linearly independent if no one of them can be written as a combination of the others. The rank of a matrix is the number of linearly independent columns it has — equivalently, the dimension of its column space.
A worked example. Take
The second column is twice the first. The third column is three times the first. Only one column is genuinely “new”; the other two carry no information that the first doesn’t already. M has rank 1 despite being a 3 × 3 matrix with 9 non-zero entries.
Rank, formally
A few facts about rank that fall out of the column-space picture, stated without proof:
- Row rank equals column rank. The number of linearly independent rows of a matrix is always equal to the number of linearly independent columns. This is not obvious from the definition; it’s a theorem. But it means “the rank” is unambiguous — you can count rows or count columns, you’ll get the same answer.
- Maximum rank is
min(m, n). A matrix with shape(m, n)can have at mostmin(m, n)independent columns, because you only havemin(m, n)directions available in the smaller of the two spaces. A1024 × 50matrix has rank at most 50, no matter what numbers you put in it. - Full rank vs. rank-deficient. A matrix is full rank if its rank equals
min(m, n). Otherwise it is rank-deficient. Most matrices you generate randomly are full rank. Most matrices that mean something — learned weights, real-world data — are rank-deficient in practice.
The last point is the one this article is built around. The geometry says: a layer’s effective dimensionality is whatever its rank is. And in practice, trained layers tend to have much smaller rank than their shape advertises.
Eigenvectors: directions the matrix leaves alone
A general matrix turns a vector two ways at once — it changes the vector’s length and its direction. To see this, take
and feed it the vector :
The output has swung to the other side of the horizontal axis and changed length — it differs from the input in both orientation and magnitude. That is the typical case: feed a square matrix almost any vector and it comes back rotated and rescaled at the same time.
But for every square matrix there are a few special directions where nothing rotational happens — the matrix only stretches or shrinks. Send a vector that lies along one of these directions through and you get back a vector pointing the same way, just longer or shorter. (It may also be flipped to point the opposite way along the same line through the origin, which still counts as the same direction.) These directions are characteristic of the matrix — which is where the name eigen comes from, German for “own” or “characteristic.” The directions themselves are the matrix’s eigenvectors, and the scalar each one is stretched by is its eigenvalue.
Formally, a non-zero vector is an eigenvector of a square matrix if
for some scalar . Multiplying by does the same thing as multiplying by the number — the vector stays on its own line through the origin; only its length, and possibly its sign, changes.
The cleanest case is when those special directions line up with the coordinate axes. Take the diagonal matrix
The vector is sent to — same direction, scaled by 2. The vector is sent to — same direction, scaled by 3. So and are eigenvectors with eigenvalues 2 and 3. Every other vector acts on is a combination of those two, and gets stretched unequally along the two axes — turning a circle into an ellipse, exactly the picture the demo earlier was showing.
Most matrices don’t line their eigenvectors up with the axes so conveniently. A neat way to see where they actually point, due to Anand Avati’s Stanford lectures, is to take every unit vector — the whole circle — and multiply each one by the matrix. The output vectors fan out into an ellipse, and the eigenvectors are the directions that didn’t swing off their own line; they fall along the ellipse’s axes.
Two cases are worth contrasting with the buttons. The non-symmetric matrix — the same one from the worked example above — has eigenvalues and (the negative one flips its eigenvector to point the opposite way), and its two eigenvectors are not perpendicular. Now switch to the symmetric matrix , the kind that is mirror-equal across its main diagonal. Its eigenvectors snap to exactly apart, lying along the major and minor axes of the ellipse. That is not a coincidence of this example: a real symmetric matrix always has real eigenvalues and orthogonal eigenvectors. (Push and apart with the sliders and watch the angle drift away from ; spin up the rotation preset and the eigenvalues go complex — a pure rotation leaves no vector on its own line at all.) This orthogonality is exactly what makes the covariance matrix in PCA, and in SVD, so well-behaved — both are symmetric by construction, so their eigenvectors form a clean perpendicular frame.
That symmetry is not an accident of the example; it is built into how a covariance matrix is formed. Stack your data as an m × n matrix (m samples, n features), centre each column, and the product is symmetric by construction — its entry is the covariance between features and , the same number as entry . For two features — say the heights and weights of three people — it is a 2 × 2 symmetric matrix whose diagonal holds each feature’s variance and whose off-diagonal holds their covariance: large and positive when the features rise together, near zero when they don’t. Its two eigenvectors are therefore orthogonal, and they are precisely the principal components of the data — the directions of greatest variance, each tagged with how much variance (its eigenvalue) lies along it. That is the whole of PCA, and the PCA article builds it out with an interactive covariance demo.
That picture generalises. A diagonalisable n × n matrix has n linearly independent eigenvectors, and the matrix factors as
where the columns of are the eigenvectors and is diagonal with the eigenvalues on its diagonal. The matrix’s whole behaviour collapses to a three-step recipe: express the input in the eigenvector basis, scale each coordinate by its eigenvalue, transform back. Rank reads off directly — it is the number of non-zero eigenvalues. Zero eigenvalues are directions the matrix annihilates, the same collapse the column-space picture described.
Eigendecomposition only works for square matrices (and not all of them — some lack a full set of independent eigenvectors). Most matrices in a neural network are rectangular: a 768 × 3072 projection has no eigenvalues in the usual sense. SVD, in the next section, is the generalisation that works on any matrix. The two are tightly connected: the singular values of are the square roots of the eigenvalues of , and the columns of and in the SVD are the eigenvectors of and respectively. SVD is eigendecomposition with the input promoted to a symmetric square matrix first.
The reason this is worth a section of its own is that the same handful of eigen-structures keep showing up across machine learning:
- PCA. The principal components of a dataset are the eigenvectors of its covariance matrix, sorted by eigenvalue. The largest eigenvalues point along the directions of greatest variance — exactly the few directions PCA keeps. Eigenvectors of the covariance matrix and singular vectors of the centred data matrix are the same vectors arrived at two ways.
- Spectral methods on graphs. Community detection, graph clustering, and node embeddings (Laplacian eigenmaps, normalised cuts) all hinge on the top eigenvectors of an adjacency or Laplacian matrix. The eigenvalues say how separable each cluster is; the eigenvectors say which nodes belong to it.
- Rank collapse in transformers. “Attention loses rank with depth” is, mechanically, “the dominant eigenvalue of the repeated attention operator pulls every token toward a single direction.” The residual stream and feed-forward sublayers are what stop that eigenvalue from running away.
- Optimisation diagnostics. The eigenvalues of the loss Hessian — its spectrum — describe the local curvature. The ratio of the top to the bottom eigenvalue is the condition number; second-order methods, learning-rate schedules, and sharpness-aware training all read this spectrum directly.
Once “this matrix has an interesting spectrum” becomes a thought you can have, the same lens fits PCA, spectral clustering, transformer depth dynamics, and Hessian-based optimisation. Eigenvectors are how a matrix tells you which directions in its domain actually matter to it; eigenvalues are how loudly it says so.
SVD: the rank microscope
To measure rank, we need a tool that turns a matrix into a list of “how much each independent direction is contributing.” That tool is the singular value decomposition. Any real matrix W of shape (m, n) can be written as
where:
- is
(m, m), an orthogonal matrix — its columns are perpendicular unit vectors. Orthogonal matrices are exactly the rotations and reflections of space; they don’t stretch or shrink, they just spin. - is
(m, n), diagonal with non-negative entries on the diagonal and zeros everywhere else. These are the singular values. - is
(n, n), also orthogonal.
Geometrically, W is doing three things in sequence: rotate the input (), stretch each axis by the corresponding singular value (), then rotate again (). That decomposition is what the demo above is showing, even though it doesn’t draw the intermediate rotations — the final ellipse’s axis lengths are the singular values, and the axis directions are the columns of .
The rank reads directly off : it is the number of non-zero singular values. Zero singular values mean some directions get scaled to zero — annihilated — and the output dimensionality drops accordingly.
A worked example. The rank-1 matrix from earlier:
One non-zero singular value. Rank 1. The SVD agrees with the column inspection from earlier — as it must.
Effective rank — the spectrum, not the number
Pure rank — the count of non-zero singular values — is a clean definition, but in practice it’s almost useless on its own. Real matrices, especially those produced by training, almost never have exact zeros in their singular value spectrum. They have a decay: large values at the top, then a smooth fall-off, and a long tail of tiny but non-zero values. Strictly speaking, such a matrix is full rank. Functionally, it isn’t.
The number people actually care about is effective rank: how many singular values are large enough to matter. Different ways to formalise this:
- Threshold rank: count the singular values above some cutoff, e.g. .
- Energy rank: the smallest
ksuch that captures, say, 99% of . This is the “how many directions do we need to keep to preserve 99% of the matrix” question. - Stable rank: . A scalar that summarises the whole spectrum in one number.
When someone says “this 1024×1024 layer is effectively rank 50,” they are using one of these definitions. The exact choice rarely matters; what matters is the shape of the singular value plot. A trained layer’s spectrum tells you, at a glance, how much of its parameter budget is doing real work.
Neural layers under the rank lens
Here is the payoff. A linear layer y = Wx with W of shape (out, in) has out × in parameters and rank at most min(out, in). If W’s effective rank is r — and r is much smaller than min(out, in) — then the SVD tells us we can approximate W as
where B is (out, r) and A is (r, in). The parameter count goes from out × in to r × (out + in). For (1024, 1024) with r = 50, that’s 10× fewer parameters. The trained layer was always “really” two small matrices in a trench coat; we just hadn’t measured it.
This single observation — learned matrices have low effective rank — is the seed of three large research areas:
- LoRA and low-rank fine-tuning. Instead of updating the full weight matrix during fine-tuning, learn a low-rank update with
rin the single or double digits. Works because fine-tuning updates are empirically very low rank: you’re not relearning the whole transformation, you’re nudging it along a few directions. - Pruning and low-rank compression. Truncate the SVD to the top
ksingular values and you’ve compressed the layer with bounded approximation error. Magnitude pruning, structured pruning, and tensor decomposition methods are all variations on this theme. - Rank collapse in deep transformers. Stack many attention layers without residual connections and token representations converge toward a one-dimensional subspace — the network’s effective rank drops to 1 across depth, and it loses the ability to distinguish positions. Residual connections, LayerNorm, and feed-forward sublayers are partly what keep the rank healthy across depth. (See “Attention is not all you need: pure attention loses rank doubly exponentially with depth”, Dong et al. 2021.)
Each of these deserves its own article and will get one. The point of this one is the lens itself: once you start seeing every weight matrix as “shape × effective rank” rather than just “shape,” a lot of seemingly disconnected results in modern deep learning start to look like variations on the same observation.
Where to next
If this article gave you a working picture of rank, the natural follow-ups on this site are:
- LLM inference optimization techniques — quantization and low-rank decomposition as production-time exploits of the same effect.
- Inside a transformer block — where rank collapse is a live concern and where the residual / LayerNorm / FFN machinery earns its keep.
- Context assembly strategies — which sits one level up, on how to use the resulting model effectively.
The matrix is a transformation. The rank is the dimensionality of what survives. Every neural network is built out of these two ideas; once you see them, you can’t un-see them.