Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

The Maths You Actually Need

Eight ideas that carry almost all the weight in machine learning.

Lesson 16 of 769 min

Rank, and why a huge matrix can be two small ones

Counting what is actually there

A matrix has a number of rows and a number of columns. It also has a rank: the number of linearly independent rows, which always equals the number of linearly independent columns. Rank counts how many genuinely different directions the matrix contains, as opposed to how many it is written with.

A = [ 1  2  3 ]      row 2 = 2 x row 1
    [ 2  4  6 ]      row 3 = 3 x row 1
    [ 3  6  9 ]      rank = 1

Three rows, one independent direction. This 3×3 matrix, nine numbers, carries the information of one 3-vector.

Because rank 1 means every row is a multiple of one row, such a matrix can be written as an outer product:

A = [1, 2, 3]^T  x  [1, 2, 3]      3 + 3 = 6 numbers instead of 9

That saving is trivial at 3×3. It is not trivial at 4096×4096.

The arithmetic that makes it matter

A dense 4096 × 4096 weight matrix holds 16,777,216 parameters. Suppose it has rank 8 — or is well approximated by a rank-8 matrix. Then it can be written as A ≈ U V where U is 4096 × 8 and V is 8 × 4096:

One 4096 by 4096 layer, dense and factoredDense 4096 by 409616.8Two thin matrices, rank 640.52Two thin matrices, rank 160.13Two thin matrices, rank 80.07millions of parametersA rank-8 factorisation holds 65,536 numbers against 16,777,216: 256 times fewer, and the reason afine-tune of a large model fits on one consumer card. It buys that by assuming the change the taskneeds is low rank, which is a claim about the task and not a theorem.
One 4096 by 4096 layer, dense and factoredDense 4096 by 409616.8Two thin matrices, rank 640.52Two thin matrices, rank 160.13Two thin matrices, rank 80.07millions of parametersA rank-8 factorisation holds 65,536 numbers against16,777,216: 256 times fewer, and the reason afine-tune of a large model fits on one consumercard. It buys that by assuming the change the taskneeds is low rank, which is a claim about the taskand not a theorem.
dense:    4096 * 4096 = 16,777,216 parameters
rank 8:   4096 * 8 + 8 * 4096 = 65,536 parameters
ratio:    256x fewer

That is the entire idea behind LoRA, the fine-tuning method used almost everywhere people adapt a large model on modest hardware. You freeze the original weights and learn only a low-rank update ΔW = BA with a small inner dimension, typically 8 to 64. The forward pass becomes W x + B(A x), and you train 65,536 numbers instead of 16.7 million.

The empirical claim behind it is that the change a fine-tune needs to make is much lower rank than the weights themselves. The original weights need all their capacity; adapting them to one new task apparently does not. That claim is supported by a lot of practice and it is not a theorem — it fails when the new task is far from anything the base model does, and the standard response is to raise the rank until it stops failing.

What rank tells you about a layer

The rank of a weight matrix bounds what the layer can do. A 768 → 768 layer whose weight matrix has rank 100 can only produce outputs lying in a 100-dimensional subspace, whatever the input. It has 590,000 parameters and 100 directions of expressive power.

This is why the low-rank bottleneck appears deliberately in architectures. An autoencoder squeezes through a narrow middle layer precisely to force a low-rank representation and make the network discard everything but the essentials. Attention projects to 64 dimensions per head for a related reason: comparisons happen in a small subspace, cheaply.

It is also why exact rank is the wrong thing to measure on real weights. A trained matrix is almost never exactly rank-deficient — floating-point noise sees to that. What you want is the effective rank: how many singular values are large enough to matter. np.linalg.matrix_rank uses a tolerance for exactly this reason, and looking at the singular values directly tells you more than the count does.

python
import numpy as np
s = np.linalg.svd(W, compute_uv=False)
print((s > s[0] * 0.01).sum(), "of", len(s), "singular values above 1% of the largest")

Where low rank shows up besides LoRA

  • Recommendation. A users × items rating matrix is enormous and mostly empty. Matrix factorisation approximates it as (users × k)(k × items) with k around 50 to 200. Those k dimensions are the "latent factors", and the whole approach exists because the true matrix is close to low rank: taste is not arbitrary.
  • Compressing a trained model. Replace a big layer with two thin ones fitted to the original's behaviour. It works reasonably for layers whose singular values decay quickly and badly for layers whose do not, which is something you can check before you try.
  • PCA and embeddings. Reducing 768 dimensions to 128 is a low-rank approximation of your data matrix, and the question of how much you lose is the question of how fast the singular values decay.

The limitation nobody mentions

Low-rank methods assume the important structure is linear. A matrix can be full rank and still be highly compressible in some non-linear sense, and conversely, data lying on a curved surface may need full rank to describe linearly while having very few real degrees of freedom. Rank measures linear redundancy only.

The practical version of this warning: when a low-rank fine-tune underperforms, the honest first hypothesis is that the required change genuinely was not low rank, not that you chose the learning rate badly. Raising the rank from 8 to 64 costs little and answers the question directly.

The rule to keep

Rank is the number of directions, not the number of numbers. When the second is far larger than the first, you are storing and computing redundancy, and a factorisation will get most of the behaviour for a fraction of the cost.

The one thing to keep

Rank counts the genuinely independent directions in a matrix, and when it is far below the matrix's size the matrix can be factored into two thin ones at a fraction of the parameters.

Before you move on

A team applies LoRA with rank 4 to fine-tune a model for a task quite unlike anything in its pre-training, and quality is poor. Which diagnosis follows most directly from what rank means?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly