Skip to content
The Daily Triptych137 / 365
A dense update versus its low-rank factors

LoRA never stores a full d×k update during training. It learns B (d×r) and A (r×k); their product supplies ΔW and can later be merged into the frozen W₀.

Try it in the local lab

Count the free parameters in a low-rank update

This tiny NumPy check makes the storage claim concrete. Pick a layer shape and a rank, form A and B, and compare how many numbers a full ΔW would need against the factored form.

$ python - <<'PY'
import numpy as np

d, k, r = 4096, 4096, 8
A = np.random.randn(r, k).astype(np.float32)
B = np.random.randn(d, r).astype(np.float32)
delta = B @ A

full = d * k
factored = d * r + r * k
print(f'full ΔW parameters:     {full:,}')
print(f'LoRA A+B parameters:    {factored:,}')
print(f'ratio full/factored:    {full / factored:.1f}×')
print(f'delta shape:            {delta.shape}, rank ≤ {r}')
PY

This only illustrates parameter counts and the BA product. It does not train a language model. Real LoRA runs inside a training stack (for example PEFT-style wrappers) with frozen base weights and an optimiser on A and B alone.

II · THE IDEA · ARTIFICIAL INTELLIGENCE

Low-Rank Adaptation (LoRA)

training · parameter-efficient fine-tuning · ΔW ≈ BA, rank r ≪ width · Hu et al., 2021

▶ Listen · narrated

Full fine-tuning means storing and optimising a second copy of the model. LoRA asks whether the useful change lives in a much smaller subspace, and trains only that.

At a glance

What it is
Frozen pretrained weights with injected low-rank update matrices
Update form
ΔW = BA, with rank r much smaller than the layer dimensions
At inference
Factors can be merged into the base weights; no extra latency
Typical target
Attention projection matrices inside Transformer layers
Design goal
Adapt large models without full fine-tuning cost or storage

Think of a huge printed map you are not allowed to redraw. Instead of reprinting the whole map for each new journey, you overlay a small transparent sheet with a few strokes that correct the route. LoRA does something analogous to a neural network. The original weights — the map — stay exactly as pretrained. Beside chosen layers, the method learns two small matrices. Multiplied together, those matrices act like the overlay: they add a thin correction to the layer’s behaviour. Because the correction is forced to pass through a narrow middle dimension called the rank, there is far less to store and optimise than if every original number were allowed to move. When you are done training, you can even draw the overlay permanently onto the map and throw the transparent sheet away, so the model runs at normal speed with no extra pieces attached.

Look closer

  1. The base never moves

    During adaptation the original weight matrix W₀ is frozen. Gradients do not flow into it. What is trained instead is a pair of thinner matrices, B and A, whose product supplies the update. The adapted forward pass uses W₀ + BA in place of W₀ alone. Because W₀ is shared and untouched, many task-specific adapters can sit beside one base checkpoint.

  2. Rank is a deliberate bottleneck

    If W₀ is d by k, a full update would have d×k free parameters. LoRA forces the update through an intermediate width r, with B shaped d by r and A shaped r by k, so the trainable count scales with r(d+k). The method rests on the idea that the useful change during adaptation has low intrinsic rank, so a small r can still carry the task signal.

  3. Zero at the start, free at the end

    A is typically initialised from a random Gaussian and B to zero, so BA begins as the zero matrix and training starts from the pretrained behaviour. After training, BA can be added into W₀ once and for all. The deployed model then has the same shape and latency as a fully fine-tuned copy, with no adapter modules left in the forward path.

The story

Fine-tuning a large language model in the obvious way means taking every pretrained weight and continuing gradient descent on the new task. That works, but it is expensive in three separate senses: the optimiser must hold states for all of those parameters, each task produces a full-sized checkpoint, and serving many tasks means either swapping huge files or keeping many full copies in memory.

Low-Rank Adaptation, introduced by Hu and colleagues in 2021, attacks that cost structure without abandoning the idea of weight-space adaptation. The pretrained weights stay frozen. Into selected layers the method injects a parallel path made of two trainable matrices whose product approximates the weight update that full fine-tuning would have found. If the original matrix is W₀, the adapted computation uses W₀ + BA rather than a freshly trained W.

The rank r of that product is a hyperparameter chosen much smaller than the layer width. That single choice is the efficiency lever: trainable parameters, optimiser memory, and per-task storage all shrink with r. The paper’s motivating claim is not that every possible update is low-rank, but that the updates that matter for downstream adaptation often live in a low-dimensional subspace — a line of thought connected to earlier work on the intrinsic dimension of fine-tuning.

In the original study the factors were applied mainly to attention projection weights inside Transformers, rather than to every linear map in the block. Which matrices receive adapters, and how large r should be, remain empirical choices; they are part of the method’s interface, not theorems. What is fixed is the decomposition itself and the freeze-the-base discipline.

A practical property follows directly from the algebra. Because the update is an additive matrix of the same shape as W₀, it can be merged after training: replace W₀ with W₀ + BA and discard A and B. Inference then looks identical to ordinary dense computation. That distinguishes LoRA from adapter designs that leave extra depth or sequence-length overhead in the forward pass at serving time.

A later unified analysis of parameter-efficient transfer methods places LoRA alongside adapters and prefix-style approaches as different ways of inserting a small trainable path into a frozen network. The implementations differ — some modify activations, some modify keys and prefixes, LoRA modifies weights through a factored residual — but they share the same economic motive: keep the expensive representation, train only a thin task-specific delta.

What you are left with in practice is a base checkpoint that does not move, a handful of small matrices per adapted layer, and the option to fold those matrices away when you want a single dense model again. The quality trade-off depends on rank, placement, and data, and is not guaranteed to match full fine-tuning on every task. The bet is that for many adaptations it comes close enough that the saved compute and storage are the decisive facts.

Why it mattered then

By 2021, language models had grown large enough that full fine-tuning was becoming a bottleneck even for well-resourced labs. Each new task meant another full parameter set, another optimiser footprint, and awkward multi-tenant serving. Adapter modules and prompt-based methods were already exploring parameter-efficient alternatives, each with its own cost in latency, sequence length, or implementation complexity. LoRA arrived as a weight-space answer that preserved the pretrained forward pass at inference: freeze the base, train a low-rank residual, merge when done. That combination — serious reductions in trainable parameters and memory, with no mandatory serving overhead — made adaptation of very large models feel operationally realistic rather than exceptional.

Why it matters now

Open-weight models are routinely specialised on modest hardware, and multi-adapter serving is a normal deployment pattern. LoRA and its close variants remain a default tool in that workflow because the checkpoint math is simple: one shared base, many small deltas, optional merge. The same freeze-and-factor idea also travels beyond the original attention-only recipe into other layer types and training stacks. Whenever the question is how to specialise a large frozen network without paying full fine-tuning’s storage and memory bill, the low-rank residual is still one of the clearest answers on the table.

The surprising detail

Once training finishes, the adapter can disappear. Multiplying B by A and adding the result into W₀ produces a single dense matrix with the same shape the base always had, so a merged LoRA model need not expose any adapter-specific code path at inference. The efficiency trick is concentrated in the training phase; the deployed artefact can look ordinary. That is a sharper separation between train-time thrift and serve-time simplicity than methods that must keep extra modules alive forever in the forward pass.

What is disputed

The claim that adaptation updates have low intrinsic rank is a working hypothesis supported by empirical results in the original paper, not a proof that a given rank suffices for every task or scale. Optimal rank, which weight matrices to adapt, and how close quality stays to full fine-tuning all remain task-dependent. The unified view paper also frames LoRA as one of several related efficient-transfer designs rather than a uniquely privileged mechanism.

Remember this

LoRA keeps the pretrained weights fixed and learns only a low-rank product BA as the update — cheap to train, mergeable at inference.

Test yourself

You fine-tune the same base model on two different tasks with LoRA, keeping identical rank and target layers. Why can you store both specialised models for little more than one base checkpoint plus two small sets of factors — and what do you give up if you merge both adapters into the base before saving?

Go deeper

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

← Back to day 137