Part XXIII — Modern Architectures, Generative Models & LLM Engineering · Chapter 7

LoRA & parameter-efficient fine-tuning

Hook

Part X froze a whole network and fine-tuned one number. A real language model's weight matrices have millions of entries — freezing the matrix is easy, but fine-tuning even a small fraction of millions of numbers is still a lot of numbers. What if the update those numbers need turns out to have far fewer real degrees of freedom than it looks like?

Intuition
2.01.00.0-1.04.02.00.0-2.0-2.0-1.0-0.01.06.03.00.0-3.0
LoRA's rank-1 approximation of the target update

A 4x4 target update, approximated by the product of two length-4 vectors — 8 numbers standing in for 16. Step through training and watch that low-rank approximation converge onto the real target.

Formalize

LoRA — short for Low-Rank Adaptation — freezes a pretrained weight matrix WW and represents the fine-tuning update as a low-rank product instead of a full matrix:

W=W+ΔW,ΔW=BA,BRn×r, ARr×n,rnW' = W + \Delta W, \qquad \Delta W = B A, \quad B \in \mathbb{R}^{n \times r},\ A \in \mathbb{R}^{r \times n}, \quad r \ll n
  • WW — the original pretrained weight matrix, kept frozen throughout fine-tuning.
  • WW' — the effective weight matrix used after applying the fine-tuning update.
  • ΔW\Delta W — the fine-tuning update itself, decomposed into a low-rank product rather than stored as a full matrix.
  • BB — one trainable low-rank factor, of shape n×rn \times r.
  • AA — the other trainable low-rank factor, of shape r×nr \times n.
  • nn — the size of the original (square) weight matrix.
  • rr — the rank of the update, chosen much smaller than nn.
  1. Parameter cost drops from quadratic to linear

    A full update to an n×nn\times n matrix costs n2n^2 trainable parameters. A rank-rr update costs only 2nr2nr. For a 4096×40964096\times4096 attention matrix and r=8r=8:

    • Full update: n2=40962=16,777,216n^2 = 4096^2 = 16{,}777{,}216 parameters
    • LoRA update: 2nr=2×4096×8=65,5362nr = 2 \times 4096 \times 8 = 65{,}536 parameters
    • Ratio: 65,536/16,777,2160.0039=0.39%65{,}536 / 16{,}777{,}216 \approx 0.0039 = 0.39\% — under half a percent
  2. The catch: rank is capped at r

    ΔW\Delta W can only ever be rank r\leq r, however training goes. If the update a task actually needs has higher intrinsic rank than rr, LoRA simply cannot represent it exactly.

Play
2.01.00.0-1.04.02.00.0-2.0-2.0-1.00.01.06.03.00.0-3.0
the target weight update
2.01.00.0-1.04.02.00.0-2.0-2.0-1.00.01.06.03.00.0-3.0
full fine-tune, 1 step (16 params)
2.01.00.0-1.04.02.00.0-2.0-2.0-1.0-0.01.06.03.00.0-3.0
LoRA, 100 steps (8 params)

The target update, the full fine-tune's result after one step, and LoRA's result after 100 steps — visually indistinguishable. Full fine-tuning used 16 parameters and one step; LoRA used 8 parameters and a hundred steps to land in the same place.

Worked example

A 4x4 target update that happens to be exactly rank-1 — ΔW=ab\Delta W^* = a^*b^{*\top} for some vectors a,ba^*, b^*:

  1. Full fine-tuning: trivial, but 16 parameters

    Each of the 16 entries is its own independent quadratic loss, same shape as every "ideal learning rate" example from earlier in this course. At η=0.5\eta=0.5, a full update matches the target exactly in one step.

  2. LoRA: 8 parameters, but a harder optimization

    ΔWab\Delta W \approx ab^\top makes the loss a product of two vectors, not a sum of independent terms — no one-step closed form. After 100 gradient steps at η=0.02\eta=0.02, the loss drops to 6×1031\approx6\times10^{-31}: effectively exact, at half the parameter count.

  3. The learned vectors aren't unique — and that's fine

    The trained a,ba, b don't match a,ba^*, b^* directly — scaling aa up and bb down by the same factor leaves abab^\top unchanged, so infinitely many (a,b)(a,b) pairs solve this exactly. What matters is the product, and that converges to the true update regardless of which particular pair training lands on.

Checkpoint

Find the step count, among the three candidates, where LoRA's loss has dropped below 1e-10.

Pick a step count to try it
Summary
ΔW=BA,cost: 2nr instead of n2— exact only if the true update fits inside rank r\Delta W = BA, \qquad \text{cost: } 2nr \text{ instead of } n^2 \quad\text{— exact only if the true update fits inside rank } r

LoRA doesn't make fine-tuning cheaper by approximating carelessly — it bets that the update a specific task actually needs has low intrinsic rank, a bet that holds remarkably often in practice for large pretrained models. When that bet is right, as in this worked example, a rank-1 or rank-8 update recovers essentially the same result as fine-tuning every parameter, at a tiny fraction of the cost. The next chapter looks at a different way large models save compute: routing each input through only a handful of specialized sub-networks instead of the whole model at once.