II · THE IDEA · ARTIFICIAL INTELLIGENCE
LoRA: Low-Rank Fine-Tuning
▶ Listen · narrated
A model holding 175 billion numbers can learn a new job without changing a single one of them. Two thin grids of fresh numbers per layer carry the entire change.
At a glance
- Mechanism
- Freeze W0; train B and A so the update is ΔW = BA
- Rank
- r ≪ min(d, k) for a d×k weight matrix
- GPT-3 175B
- Up to ~10,000× fewer trainable parameters; ~3× less GPU memory
- Inference
- BA can be merged into W0; no added latency
- Initialisation
- A random Gaussian, B zero, so ΔW starts at zero
A large printed map sits under glass, and you may not redraw it. Instead you lay a clear plastic sheet on top and draw a few lines on the sheet. The lines are enough to guide someone to a new place, and you can lift one sheet off and lay another down without ever touching the map beneath.
LoRA treats a neural network this way. A network keeps its knowledge in huge grids of numbers called weight matrices. LoRA leaves the big grid frozen — completely unchanged — and trains two much smaller grids instead, called B and A. Multiplying B by A produces a grid the same size as the frozen one, and that product is the change the new task needs. When data passes through the layer, it goes through the frozen grid and through the small pair separately, and the two answers are added together.
Because B and A are thin, the number of values being trained is a tiny fraction of what rewriting the whole grid would take. Training also needs far less computer memory, because the computer only tracks adjustments for the small grids, never the big one. When you finish, you have two choices. Add the product into the original grid permanently, and you are left with a perfectly ordinary model that runs at its usual speed, as if the adapter had never existed. Or keep the small pair separate, and change what the model does by swapping one pair for another — like swapping plastic sheets over the same map.
Let W0 ∈ ℝ^{d×k} be a frozen pre-trained weight matrix. LoRA parameterises the task-specific update as ΔW = BA, with B ∈ ℝ^{d×r}, A ∈ ℝ^{r×k}, and rank r ≪ min(d, k). The layer computes h = W0x + BAx = (W0 + BA)x, so the trainable parameter count drops from dk to r(d + k). W0 receives no gradients and holds no optimiser state; only A and B do. Initialisation sets A to random Gaussian values and B to zero, so ΔW = 0 at step 0 and training starts from exactly the pre-trained function.
In the original study the factors attach mainly to the attention projections Wq, Wk, Wv and Wo, not to every dense layer. The rank r is a hyperparameter — chosen, not learned.
Two deployment modes follow directly from the algebra. Merged: fold BA into W0 once and ship a single dense matrix, with zero adapter overhead and zero added latency. Unmerged: keep A and B external, so many task modules share one frozen base in memory, at the cost of carrying the second matmul path at inference.
Reported results: on GPT-3 175B, up to ~10,000× fewer trainable parameters and ~3× lower GPU memory than full fine-tuning, with quality on par with or better than full updates across the RoBERTa, DeBERTa, GPT-2 and GPT-3 evaluations shown. Related PEFT work reports such updates to be both more accurate and cheaper than few-shot in-context learning on the settings tested, since demonstrations need not occupy the context window at inference time.
The limits follow from the construction. Expressivity is bounded by r and by the choice of which matrices are adapted; a task genuinely requiring a high-rank shift, or a shift in layers left untouched, will not be recovered. The low-rank premise is an empirical working assumption, not a theorem.
Look closer
The forward pass stays a sum of two paths
For a frozen weight matrix W0 the adapted hidden state is written h = W0x + BAx. The same input multiplies both the original matrix and the low-rank product; the outputs are added coordinate-wise. Only A and B receive gradients. Nothing in that equation requires the adapter path to remain separate at deployment: once training ends, BA may be folded into W0 so a single dense matrix is all that remains.
Why the memory bill falls so sharply
Full fine-tuning stores gradients and optimiser state for every parameter. With the base frozen, those tensors are needed only for the factors A and B. On GPT-3 175B the LoRA paper reports trainable-parameter cuts as large as ten thousand times and GPU memory need cut by about three times relative to ordinary fine-tuning, while quality on the reported RoBERTa, DeBERTa, GPT-2 and GPT-3 experiments stayed on par with or above full updates.
Where the factors are usually attached
The original work concentrates on the attention projections — the query, key, value and output matrices — rather than every dense layer at once. Rank r is treated as a small chosen integer, not something the model discovers. Different tasks keep different A and B pairs against one shared frozen base, which is how several specialised behaviours can sit on a single copy of the pre-trained weights.
The story
A neural network is, underneath everything, a long list of numbers called weights, stored in rectangular grids called matrices. When the network reads a sentence, the words are turned into lists of numbers, and those lists are multiplied through the grids, layer after layer, until an answer comes out. Everything the model knows lives in the values of those weights. Fine-tuning — teaching a pre-trained model a new task — traditionally meant letting the training process adjust every one of them.
That works, but the cost is larger than it first appears, and the cost is the point of this story. Training a weight means computing a gradient for it: a number saying which direction to nudge it. The optimiser — the routine that decides the actual step sizes — keeps one or two more bookkeeping numbers per weight on top of that. So for every weight it trains, the computer holds two or three extra values in memory. A model with 175 billion weights, the size of GPT-3, therefore needs room for hundreds of billions of extra values before it has learned from a single example. And when training ends, you own a complete second copy of the model that is good at exactly one task. Train it for ten tasks and you own ten copies.
LoRA — low-rank adaptation, introduced by Hu and colleagues — begins from an observation about what fine-tuning actually produces. Call the pre-trained grid W0, with d rows and k columns. Full fine-tuning turns it into some new grid; the difference between new and old is the update, ΔW, a grid of exactly the same shape. LoRA's premise is that this update, though it has room for d times k independent numbers, does not use that room. The measure of how much genuine freedom a grid of numbers exercises is called its rank, and the premise is that the update's effective rank is low — its useful content can be squeezed into a far thinner form.
Here is the mechanism, step by step. Instead of learning ΔW directly, LoRA learns two thin grids: B, with d rows and only r columns, and A, with r rows and k columns. The number r is the rank, chosen by hand before training starts, and it is small — perhaps 8, against grid widths in the thousands. Multiplying B by A gives back a grid of the full d by k shape, and that product stands in for the update. Now count what is actually trained: not d times k numbers, but r times (d plus k). For small r that is a tiny fraction of the original.
During training, W0 does not move at all. It receives no gradients, and the optimiser stores no bookkeeping for it — which is exactly where the memory saving comes from. When an input x passes through the layer, it is multiplied by the frozen W0 and, separately, by the thin pair; the two results are added together, position by position. Written out, the layer's output is W0x + BAx. The starting values matter too. A begins as random noise drawn from a Gaussian — a bell-curve distribution — while B begins as all zeros. Anything multiplied by zeros gives zeros, so the product BA starts at exactly zero, and at the first training step the model behaves precisely as the pre-trained model did. The adapter then grows away from zero only as far as the new task demands.
In the original paper the thin pairs are not attached everywhere. They go mainly on the attention projections — the four matrices in each attention layer, called query, key, value and output, which govern how the model weighs earlier words when processing the current one. The rest of the network stays untouched. The rank r is a setting the researcher picks, not something the model discovers.
The reported results are what made the method spread. On GPT-3 with 175 billion parameters, the paper reports up to roughly 10,000 times fewer trainable parameters than full fine-tuning, and about 3 times less GPU memory, while matching or beating full fine-tuning quality on the RoBERTa, DeBERTa, GPT-2 and GPT-3 experiments run.
There is a closing trick, and the algebra gives it away for free. The layer computes W0x + BAx, and that is the same value as (W0 + BA)x — adding the two grids first and multiplying once gives an identical answer. So before serving the model you may add BA into W0 permanently. What ships is then one ordinary dense matrix of the usual shape. The adapter has vanished into it; nothing extra runs when the model answers a question, so there is no added delay. Or you may skip the merge, keep a single frozen base model in memory, and change what the model does by swapping in a different small A and B pair. Several specialised behaviours can then share one copy of the expensive base weights.
LoRA belongs to a family of methods called parameter-efficient fine-tuning, or PEFT. A separate study compared that family with in-context learning — teaching a model a task by pasting a few worked examples into the prompt itself. On the tasks reported, the efficient updates were both more accurate and cheaper to run. The reason is structural. Pasted examples must be re-read, token by token, on every single request; a trained adapter is paid for once and then costs nothing more.
Two honest limits deserve their own sentences. The low-rank premise is an empirical working assumption — well supported on the models and tasks measured, but not a theorem. A task that genuinely needs a high-rank change, or a change in layers left untouched, will not be captured. And the striking ratios — 10,000 times, 3 times — belong to the specific configurations the paper measured, not to every model at every scale. What the method claims is narrower, and stronger for it: on everything tested, the adjustment a new task needed fitted in a thin slice, and training only that slice matched rewriting the whole.
Why it mattered then
By the time models reached GPT-3's size — 175 billion weights — fine-tuning had become a hardware problem as much as a learning one. Every weight being trained needs a gradient, the number saying which way to nudge it, plus the optimiser's bookkeeping beside it; and every finished task leaves behind a full copy of the model to store and load. Doing that once per dataset, at that scale, sat beyond most laboratories' means. LoRA answered the pressure directly. Freeze the expensive base, so it needs no gradients and no bookkeeping at all. Train only thin factor pairs, attached mainly to the attention projections — the query, key, value and output matrices inside each attention layer. Then merge the pairs back in at the end, so the served model looks and runs exactly like the original. The reported figures — up to 10,000 times fewer trainable parameters on GPT-3 175B, and roughly 3 times less GPU memory — moved the adaptation of very large models from a rare, costly exercise to routine work.
Why it matters now
Open-weight models are now specialised on a single workstation graphics card as a matter of course, and low-rank adapters are the standard way to do it. Three properties explain the staying power. The original checkpoint is never overwritten, so one download serves every task. The training memory bill scales with the thin factors rather than the whole network, which is what lets modest hardware cope. And several task-specific pairs can sit beside one shared frozen base, so switching behaviour means loading a few small grids rather than reloading a model. Both deployment routes still earn their keep: merge the factors into the base when speed matters most; keep them separate when many behaviours must share one machine. The old comparison with in-context learning also still holds. Worked examples pasted into a prompt must be re-read on every request, spending context window and compute each time; a trained low-rank update spends that cost once. Given the choice between rewriting a whole model, stuffing examples into every prompt, or training a thin residual, the third usually fits the hardware in front of you.
The surprising detail
On GPT-3, a model of 175 billion parameters, the paper reports that the count of weights actually being trained can fall by a factor of about 10,000 compared with full fine-tuning — and quality on the benchmarks tested did not fall with it. Everything the model needed in order to learn each new task travelled through factors whose rank was a small hand-picked integer. On the tasks measured, almost none of the network had to move at all.
What is disputed
LoRA is motivated by the hypothesis that the weight updates required for adaptation have low intrinsic rank. That hypothesis is supported by the paper's empirical results on the models and tasks tested; it is not established as a general law for every layer, task or scale. Reported parameter and memory ratios are also specific to the configurations measured, especially the GPT-3 175B figures.
Remember this
Freeze the big grid W0. Train only the thin pair B and A; their product is the whole update. Merge it in for cost-free inference, or swap pairs to change the task.
Test yourself
After LoRA training you can either merge BA into W0 or leave the factors separate and load different pairs for different tasks. What do you gain and lose in each choice, and why can both still be correct for the same base model?
Merging produces a single dense matrix of the original shape, so inference cost and latency match the unmodified network, but you give up cheap task switching — each task needs its own full copy once merged. Leaving A and B separate keeps one shared frozen base in memory and makes task changes a matter of swapping small factors, at the cost of carrying the extra path until you merge. Both are valid because the mathematics is the same: h = W0x + BAx is identical to using W0 + BA as a single matrix. The choice is operational, not algorithmic.
Go deeper
- [2106.09685] LoRA: Low-Rank Adaptation of Large Language Models · arxiv.org
- [2205.05638] Few-Shot Parameter-Efficient Fine-Tuning is Better and Cheaper than In-Context Learning · arxiv.org
Image: Original diagram, The Daily Triptych. Licence: Original work. Source.