The apple the prompt cannot name
Chapter 6 ended on a hard edge. Prompts steer the model within what it already knows, and teaching it something new is a different job. That is this chapter.
Say there is a particular apple you care about: an heirloom variety with a russet shoulder and a squat, lopsided profile. You type it into the prompt and you get an apple, a good one, and not that one. No arrangement of words reaches it, because the words the noise predictor was trained against never pointed at your apple.
The obvious fix is to keep training. Take the finished model, feed it thirty photographs of your apple, and let Chapter 3's gradient steps keep rolling. That is full fine-tuning, and it works. It also hands you a bill. A model of this kind holds billions of learned numbers, the parameters $\theta$ from Chapter 3, counting the hundreds-of-millions U-Net together with the other trained pieces packed into the same checkpoint. Full fine-tuning nudges every one of them, each needing its own gradient and its own bookkeeping while training runs, and what you get back is a second copy of the model: gigabytes, for one apple.
There is a much smaller way to write down a change, and it is the rest of this chapter: a LoRA, short for Low-Rank Adaptation. It leaves the model's own billions of numbers frozen, in Chapter 5's sense of the word: the training process is forbidden to change those numbers at all. They are read and multiplied by, and never touched. That is what makes everything else cheap. The same idea, with the same numbers, appears in the sister book's LoRA chapter, so the two books agree digit for digit. This chapter builds it from scratch anyway, then does the part that belongs to images.
Learning only the change
Inside the noise predictor, the numbers that do the work are arranged in rectangular grids called weight matrices. Pick one and call it $\mathbf{W}$, "the matrix W", a block of numbers the network multiplies things by. After a fine-tune it has become some new matrix $\mathbf{W}'$, "W-prime", and whatever fine-tuning did to it, the result can be written as the original plus a grid of changes. Write $\Delta\mathbf{W}$ for that grid of changes, using the Greek letter delta, the traditional symbol for "a change":
$$\mathbf{W}' = \mathbf{W} + \Delta\mathbf{W}$$In words: the adapted matrix is the original matrix plus a matrix of changes, added cell by matching cell.
On its own that rewrite saves nothing. $\Delta\mathbf{W}$ has as many cells as $\mathbf{W}$, so a million-cell matrix still needs a million-cell correction. It only pays if the change can be described more cheaply than the thing it changes. So how complicated is the change a narrow fine-tune needs?
The LoRA bet is that it is very simple, and there is a precise way to say "simple" about a matrix. A matrix built by multiplying one tall skinny column by one flat wide row can only push its outputs along a single direction. It has rank one, the simplest non-zero change there is. Take a column $\mathbf{B}$ and a row $\mathbf{A}$:
$$\mathbf{B} = \begin{bmatrix} 2 \\ 1 \end{bmatrix}, \qquad \mathbf{A} = \begin{bmatrix} 3 & 1 \end{bmatrix}, \qquad \Delta\mathbf{W} = \mathbf{B}\mathbf{A}$$In words: the whole grid of changes is one column of numbers standing up, multiplied by one row of numbers lying flat.
Worked example — every entry of the product
Multiplying a column by a row fills a grid: the entry in row $i$, column $j$ is the $i$-th number of $\mathbf{B}$ times the $j$-th number of $\mathbf{A}$. All four, one at a time:
- Row 1, column 1: $2 \times 3 = 6$.
- Row 1, column 2: $2 \times 1 = 2$.
- Row 2, column 1: $1 \times 3 = 3$.
- Row 2, column 2: $1 \times 1 = 1$.
In words: two numbers and two numbers, four numbers stored, reconstruct all four cells of the change grid.
Count that: four numbers stored to rebuild four cells. On a toy this small the technique breaks even. The saving arrives when the grids get big, and the end of the chapter counts it.
Now the property that makes it "low rank". Feed this change grid a few different inputs and look at where the answers land. Feeding a grid an input means taking each row of the grid and dotting it with the input, multiplying matching slots and adding the results, and those answers, top row first, are the output list. That is all multiplying by a matrix is.
- Input $\begin{bmatrix} 1 \\ 0 \end{bmatrix}$: top $= 6 \times 1 + 2 \times 0 = 6$, bottom $= 3 \times 1 + 1 \times 0 = 3$, so the output is $\begin{bmatrix} 6 \\ 3 \end{bmatrix}$.
- Input $\begin{bmatrix} 0 \\ 1 \end{bmatrix}$: top $= 6 \times 0 + 2 \times 1 = 2$, bottom $= 3 \times 0 + 1 \times 1 = 1$, so the output is $\begin{bmatrix} 2 \\ 1 \end{bmatrix}$.
- Input $\begin{bmatrix} 1 \\ 1 \end{bmatrix}$: top $= 6 + 2 = 8$, bottom $= 3 + 1 = 4$, so the output is $\begin{bmatrix} 8 \\ 4 \end{bmatrix}$.
Three different inputs, and every answer is some number of copies of $[2, 1]$: three copies, one copy, four copies. That holds for every possible input. The row $\mathbf{A}$ crushes whatever comes in down to a single number, and then the column $\mathbf{B}$ stretches that one number back out along one fixed direction. Everything squeezes through a one-number bottleneck.
That bottleneck width is the knob. Let $r$ numbers through instead of one, where $r$ is the rank, and $\mathbf{B}$ becomes a matrix with $r$ columns, $\mathbf{A}$ a matrix with $r$ rows, and the change can span up to $r$ independent directions. In practice $r$ is small: 4, 8, 16 or 32, against matrices a thousand numbers wide. Small works because the change a narrow fine-tune needs is simple. You are not teaching the model to see. You are teaching it one apple. Everything else about training is unchanged. The loss is Chapter 3's, in the latent, conditioned form Chapters 4 and 6 left it in, $L(\theta) = \|\boldsymbol{\epsilon} - \boldsymbol{\epsilon}_\theta(\mathbf{z}_t, t, \mathbf{c})\|^2$, with the gradient allowed to move only $\mathbf{B}$ and $\mathbf{A}$.
The strength dial, as arithmetic
A LoRA ships with one more number: a scale that says how loudly the learned change should speak. In the update it is the fraction $\frac{\alpha}{r}$:
$$\mathbf{W}' = \mathbf{W} + \frac{\alpha}{r}\,\mathbf{B}\mathbf{A}$$In words: the working matrix is the frozen matrix plus alpha-over-r times the learned low-rank change.
$r$ is the rank, the bottleneck width we just chose, and $\alpha$ is "alpha, the LoRA scale", a volume knob. Dividing by $r$ is a courtesy to your future self: double the rank and the product $\mathbf{B}\mathbf{A}$ picks up roughly twice as many contributions, so dividing by $r$ keeps the overall loudness comparable when you change rank.
Worked example — the frozen matrix, adapted
Let the frozen matrix be a plain doubling machine, $\mathbf{W} = \begin{bmatrix} 2 & 0 \\ 0 & 2 \end{bmatrix}$, chosen so you can see at a glance what the base model contributes and anything else in the answer must have come from the adapter. Keep $\mathbf{B}\mathbf{A} = \begin{bmatrix} 6 & 2 \\ 3 & 1 \end{bmatrix}$ from the last section, and set $\alpha = 2$ with $r = 1$, so $\frac{\alpha}{r} = \frac{2}{1} = 2$. First scale the change, cell by cell: $2 \times 6 = 12$, $2 \times 2 = 4$, $2 \times 3 = 6$, $2 \times 1 = 2$. Then add it on, cell by matching cell: $2 + 12 = 14$, $0 + 4 = 4$, $0 + 6 = 6$, $2 + 2 = 4$.
$$\mathbf{W}' = \begin{bmatrix} 2 & 0 \\ 0 & 2 \end{bmatrix} + 2\begin{bmatrix} 6 & 2 \\ 3 & 1 \end{bmatrix} = \begin{bmatrix} 14 & 4 \\ 6 & 4 \end{bmatrix}$$In words: the adapted matrix is the frozen doubler with the scaled change folded into it, one cell at a time.
Now push the input $\begin{bmatrix} 1 \\ 1 \end{bmatrix}$ through both. The frozen matrix gives top $= 2 \times 1 + 0 \times 1 = 2$ and bottom $= 0 \times 1 + 2 \times 1 = 2$. The adapted matrix gives top $= 14 \times 1 + 4 \times 1 = 18$ and bottom $= 6 \times 1 + 4 \times 1 = 10$.
$$\mathbf{W}\begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 2 \\ 2 \end{bmatrix}, \qquad \mathbf{W}'\begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 18 \\ 10 \end{bmatrix}$$In words: the same input that the base model turned into $[2, 2]$ now comes out as $[18, 10]$. The adapter has bent this one matrix's behavior hard.
Our toy shouts on purpose, so that every digit stays visible. Real adapters nudge. Notice the folding too: once you have computed $\mathbf{W}'$ you can throw the two strips away and run the adapted matrix directly, which is why a merged LoRA costs nothing extra when you generate.
Now the number you turn. In a workflow it is labeled LoRA strength, and it is the multiplier in front of $\mathbf{B}\mathbf{A}$. Sweep it across the same input $[1, 1]$, remembering that $\mathbf{B}\mathbf{A}\begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 8 \\ 4 \end{bmatrix}$ from the worked example above, and the base path contributes $[2, 2]$ every time:
Worked example — the slider is pure arithmetic
| $\frac{\alpha}{r}$ | change contributed | output | what the picture does |
|---|---|---|---|
| 0 | $0 \times [8, 4] = [0, 0]$ | $[2 + 0,\; 2 + 0] = [2, 2]$ | the concept is absent: this is the base model |
| 0.5 | $0.5 \times [8, 4] = [4, 2]$ | $[2 + 4,\; 2 + 2] = [6, 4]$ | the concept shows up, faintly |
| 1.0 | $1.0 \times [8, 4] = [8, 4]$ | $[2 + 8,\; 2 + 4] = [10, 6]$ | the concept is clearly present |
| 1.5 | $1.5 \times [8, 4] = [12, 6]$ | $[2 + 12,\; 2 + 6] = [14, 8]$ | the change swamps the base model's contribution |
Read the middle column against the constant $[2, 2]$ the base path supplies. At 0 the adapter is silent. At 1.0 it contributes four times what the base matrix does on this input, and by 1.5 the base model's opinion is a rounding error. That is what an over-strength LoRA looks like on screen: the concept everywhere, at the cost of composition, background and lighting.
Where the adapter attaches
Which matrices get the treatment? Almost always the ones inside the cross-attention blocks of the U-Net, from Chapter 6, where each patch of the latent asks the conditioning $\mathbf{c}$ what it should be. Those are the matrices that decide how strongly a word in your prompt pulls on a region of the image, so a small correction there is a large change in how the model reads language.
That explains trigger words. Whoever trains an adapter captions the training images with a rare token, "sks apple" or something else the base model has no strong opinion about, and the adapter learns to attach a large correction to that token's pull, because there was nothing there before to interfere with. Leave the trigger word out of your prompt and such an adapter can look inert. Put it in and the whole thing switches on. You are choosing whether the corrected path ever gets a strong query to answer.
Everything else is as you left it. Picture Chapter 4's latent-diffusion-pipeline map again: encoder, loop in latent space, decoder. A LoRA changes nothing about it, not the VAE, not the sampler, and no extra stage. It edits a handful of matrices inside the noise predictor, and Chapter 5's loop runs as before, calling a slightly different function at every sampler step.
Why varied apples matter
Back in Chapter 1 we laid out nine deliberately different apple thumbnails, red and green and golden, spotted, large, small, photographed from two angles, and the caption promised that the difference would matter when we got to LoRAs. This is where that gets paid.
Training an adapter is Chapter 3's procedure on a very small dataset. Encode one of your photographs to a latent, pick a random timestep $t$, add the matching noise using Chapter 2's closed form, ask the noise predictor for that noise, compare, and push $\mathbf{B}$ and $\mathbf{A}$ downhill. Repeat over your twenty or thirty images. The learned change is whatever consistently reduces that loss across your set.
That last sentence contains the trap. The adapter learns whatever is consistent, and it has no idea which parts of your photographs are the concept and which are the circumstances. Say all thirty photographs of your heirloom apple sit on the same wooden table, in the same warm afternoon light, shot from the same height. "Russet shoulder" is consistent across your set, and so is "wooden table", and "warm light", and "shot from above". The gradient cannot tell them apart, so the adapter learns the whole bundle as one concept. Load it, prompt for your apple in a snowfield, and the wooden table comes to the snowfield with it. That is the method working as specified on data that specified the wrong thing.
The fix is variety, and you apply it with a camera rather than a setting. Photograph the apple on a table, on grass, in a hand, against a white wall; morning light, lamp light, flat overcast; close, far, above, side. Now the only thing consistent across the set is the apple, so the only thing the adapter can learn is the apple. Variety isolates the concept from its accidents, and twenty varied photographs beat two hundred from one sitting.
Two neighboring failures deserve names. Overfitting is training for too many passes over too few images: the adapter stops learning "this apple" and starts memorizing "these thirty pictures", and the giveaway is a generation that reproduces a training photo's composition whatever else you ask for. And data quality beats quantity: five sharp, well-lit, correctly captioned photographs teach a cleaner concept than fifty blurry ones, because every blurry image quietly teaches "blurry" as part of the target.
Counting the savings
Now the arithmetic that made the technique famous. Take a weight matrix that is $1{,}000$ numbers wide and $1{,}000$ numbers tall, a typical size inside a model like this. A full change $\Delta\mathbf{W}$ to it has one entry per cell:
$$1{,}000 \times 1{,}000 = 1{,}000{,}000$$In words: changing that matrix the ordinary way means writing down and training one million numbers.
Now the low-rank version at a typical rank of $r = 8$. The column block $\mathbf{B}$ is $1{,}000$ tall and $8$ wide; the row block $\mathbf{A}$ is $8$ tall and $1{,}000$ wide:
$$\underbrace{(1{,}000 \times 8)}_{\mathbf{B}} + \underbrace{(8 \times 1{,}000)}_{\mathbf{A}} = 8{,}000 + 8{,}000 = 16{,}000$$In words: sixteen thousand trained numbers stand in for a million.
The ratio, worked: $16{,}000 \div 1{,}000{,}000 = 0.016$, which is $1.6\%$. Multiply that across the handful of cross-attention matrices a LoRA touches and the file lands in the low tens of megabytes, beside a base model of several gigabytes. Those figures are typical of models of this kind rather than laws. It is why a shelf of adapters is practical to own: one frozen base model and a stack of small files, each teaching it one thing.
Because the corrections are additions, they compose. Load two adapters and the corrections add up on each shared matrix, each with its own strength:
$$\mathbf{W}' = \mathbf{W} + s_1\mathbf{B}_1\mathbf{A}_1 + s_2\mathbf{B}_2\mathbf{A}_2$$In words: the adapted matrix is the frozen matrix plus the first adapter's change at its own strength, plus the second adapter's change at its own strength. These strengths $s_1$ and $s_2$ are LoRA strengths, not Chapter 6's guidance scale $s$, which lives in a different equation.
Composition works right up until it does not. Each adapter was trained separately, assuming the frozen matrix underneath it was untouched and knowing nothing of the other. If they push the same matrices in conflicting directions, say a style adapter that flattens everything against a subject adapter that insists on photographic texture, the sum is a fight rather than a compromise, and the usual repair is turning both strengths down.
See it move
Where you'll meet this
In a workflow graph, this chapter is one node, usually called Load LoRA, sitting after the checkpoint loader, taking the base model in on one wire and handing a modified model out on another. That wiring is the picture of the chapter: the adapter never stands alone in the graph, because it has nothing to do without a model flowing through it.
The number in that node's box is $\frac{\alpha}{r}$ from the sweep table, the same multiplier with the same arithmetic behind it. Some interfaces give you two of them, one for the correction applied inside the U-Net and one for the correction applied to the text encoder, because a LoRA can carry strips for both. And when a model page tells you to include a strange token like "sks apple" in your prompt, you know what you are doing: handing the corrected cross-attention path the one query it was trained to answer loudly.
Three habits fall out of the math. If a generation looks untouched, check the trigger word first. If it looks scorched, drop the strength before you rewrite the prompt, because you are turning down the multiplier in front of $\mathbf{B}\mathbf{A}$ and nothing more. And if a LoRA does nothing at all, check which base model it was trained against. LoRA is the famous member of a larger family of adaptation methods, and the others are a topic for another day.
What you now know
- A fine-tune never has to rewrite a weight matrix. It can be written as the original plus a change, $\mathbf{W}' = \mathbf{W} + \Delta\mathbf{W}$, and the whole game is describing that change cheaply.
- A LoRA describes the change as a column times a row: $\mathbf{B} = [2, 1]$ times $\mathbf{A} = [3, 1]$ fills the grid $\begin{bmatrix} 6 & 2 \\ 3 & 1 \end{bmatrix}$, and every output it can produce lies along the single direction $[2, 1]$, which is rank 1.
- The strength you turn in a workflow is the multiplier $\frac{\alpha}{r}$ in $\mathbf{W}' = \mathbf{W} + \frac{\alpha}{r}\mathbf{B}\mathbf{A}$, and it is pure arithmetic: on our toy it moves the output from $[2, 2]$ at strength 0 to $[18, 10]$ at $\frac{\alpha}{r} = 2$. This $\alpha$ is not the noise schedule's $\alpha_t$.
- Adapters usually attach to the cross-attention matrices from Chapter 6, which is why trigger words switch them on so sharply, and a rank-8 adapter on a $1{,}000 \times 1{,}000$ matrix trains $16{,}000$ numbers instead of $1{,}000{,}000$, which is $1.6\%$: megabytes riding on gigabytes.
- The adapter learns whatever is consistent across your training images, so varied backgrounds, light and angles are what separate your apple from the wooden table it sat on. That is the promise Chapter 1's varied apples made.
- A LoRA is not a model: it holds a correction to specific matrices, it is inert on its own, and it runs only on top of the base model it was trained against.
Where we're headed. You can now teach a frozen model one new thing with a file small enough to email, and read every number on the node that loads it. What you cannot do is make it last longer than an instant. The adapter bends the noise predictor, the sampler walks its loop, the decoder hands back a picture, and that is the end of it. Chapter 8 adds the missing axis, treating a whole sequence of frames as one object and using temporal attention to keep the apple the same apple from frame to frame.