Skip to content
The Daily Triptych240 / 365
A weight update forced through low rank

Illustrative shading of a d×k update that factors as BA with small r. In LoRA only those factors are trained; the original W0 stays frozen and the forward pass sums both paths.

Try it in the local lab

Count the trainable slice

Attach LoRA adapters to a small open model with PEFT and read off how many parameters actually train. Needs Python, a working PyTorch install, and a download of the base weights.

$ pip install transformers peft accelerate torch
$ python - <<'PY'
from transformers import AutoModelForCausalLM
from peft import LoraConfig, get_peft_model
m = AutoModelForCausalLM.from_pretrained("gpt2")
cfg = LoraConfig(r=8, lora_alpha=16, target_modules=["c_attn"], bias="none")
pm = get_peft_model(m, cfg)
pm.print_trainable_parameters()
PY

gpt2 is only a fast stand-in. Absolute counts shift with rank, target modules and model width; the point is the ratio between trainable and total parameters.

II · THE IDEA · ARTIFICIAL INTELLIGENCE

LoRA: Low-Rank Fine-Tuning

efficiency · LoRA (low-rank adaptation) · GPT-3 175B in the LoRA paper · PEFT versus in-context learning

▶ 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.

Look closer

  1. 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.

  2. 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.

  3. 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?

Go deeper

Image: Original diagram, The Daily Triptych. Licence: Original work. Source.

← Back to day 240