Now we learn to walk back
We can destroy an apple at any noise level in one shot. Now we learn to walk back. In destroying an apple we built a one-way machine: hand it our apple and a timestep, and it hands back that apple part-dissolved into static. It never needed to learn anything, because we chose every ingredient: the shrink, the noise and the schedule. Going the other way is the whole remaining problem, and the only part of this book that needs a network.
The machine we build does not look at a noisy apple and paint a clean one. It looks at a noisy apple and points at the noise, and then we do the subtraction ourselves, with arithmetic you can check by hand. That distinction sounds pedantic here, and everything in the chapter rests on it.
Why we ask for the noise
The forward process throws information away, and throwing information away is not reversible. Look at a heavily speckled patch and ask "which apple was this?" There is no single right answer. A red apple with a bright highlight and a slightly larger green apple in dimmer light could both have landed on that patch of static, given different luck with the noise draw. A network trained on a question with many answers learns to output the blurry average of all of them.
So we change the question. We ask: of the numbers in front of you, which part was the noise? That question has one right answer for every training example we will ever build, and we know the answer, because we drew the noise. That is the trick the whole field runs on.
The thing that answers it is the noise predictor, written $\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)$ and read "epsilon-theta". Take that symbol apart. The $\boldsymbol{\epsilon}$, epsilon, is Chapter 2's noise blob, so the letter says what comes out: noise, not an image. The subscript $\theta$, theta, stands for every adjustable number inside the network at once, several hundred million for a U-Net of the kind this chapter describes, and billions once the other trained pieces of a checkpoint are counted. If you have met the neuron, $\theta$ is every weight and every bias in the stack gathered into one symbol. The brackets hold its only inputs: $\mathbf{x}_t$, the noisy image, and $t$, the timestep, which is the noise level and the same $t$ that indexes Chapter 2's schedule. Nothing else goes in. The network does not know what we want, does not know it is looking at an apple, and has never been told the word "apple".
Why does the timestep need to go in at all? Because the same speckle means different things at different noise levels. Low down the ladder the picture is almost all apple with a faint dusting on top, so the right answer is a faint noise field. High up it is almost all noise with a ghost of apple in it, so the right answer is nearly the whole picture. Telling the network which rung it is standing on lets one network handle all of them.
The answer key we make ourselves
Most machine learning is limited by labeled data. Somebody has to say what the right answer is, and people are slow and expensive. Diffusion has no such problem, because of the closed form we derived last chapter:
$$\mathbf{x}_t = \sqrt{\bar{\alpha}_t}\,\mathbf{x}_0 + \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}$$In words: the noisy image at timestep $t$ is the clean image faded by alpha-bar-t, the cumulative fraction of the original signal still surviving, plus one blob of noise scaled by whatever is left over.
Read that equation as a way to manufacture training examples. Take any real apple photograph and call it $\mathbf{x}_0$. Pick a timestep $t$ at random. Draw a noise blob $\boldsymbol{\epsilon}$, one number per pixel, each pulled independently from the bell curve centered at zero with spread one. Combine them with the two coefficients and out comes $\mathbf{x}_t$. The input is $(\mathbf{x}_t, t)$ and the correct answer is $\boldsymbol{\epsilon}$, which nobody had to label, because you drew it thirty milliseconds ago and still have it.
The loss: one number for how wrong
To train anything we need a single number that says how bad the current guess was, and it has to get smaller as the guess gets better:
$$L(\theta) = \left\| \boldsymbol{\epsilon} - \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) \right\|^2$$In words: subtract the network's guessed noise from the true noise, one number at a time, square each of those differences, and add the squares up. That total is the loss, and the smaller it is, the closer the guess was.
The double bars $\|\cdot\|$ are the length of a list of numbers, and squaring that length means "skip the square root and keep the sum of squares". This is the mean-squared-error idea from measuring wrongness, applied to a noise field instead of a prediction about text. Squaring makes every disagreement positive, so overshoots and undershoots cannot cancel out, and it punishes one big miss far harder than several small ones.
Worked example — the loss on three numbers
A real noise field has hundreds of thousands of entries. Ours will have three, so you can check every digit. Suppose the true noise we drew was $\boldsymbol{\epsilon} = [1.0,\, -0.5,\, 0.2]$ and the network guessed $\boldsymbol{\epsilon}_\theta = [0.8,\, -0.1,\, 0.2]$. I picked those three so that one entry is guessed too low, one too high, and one right, and all three cases show up in a single table.
| entry 1 | entry 2 | entry 3 | sum | |
|---|---|---|---|---|
| true noise $\boldsymbol{\epsilon}$ | $1.0$ | $-0.5$ | $0.2$ | |
| guess $\boldsymbol{\epsilon}_\theta$ | $0.8$ | $-0.1$ | $0.2$ | |
| difference | $0.2$ | $-0.4$ | $0.0$ | |
| difference squared | $0.04$ | $0.16$ | $0.00$ | $0.20$ |
Every step in the open: $1.0 - 0.8 = 0.2$, and $0.2 \times 0.2 = 0.04$. Then $-0.5 - (-0.1) = -0.4$, and $(-0.4) \times (-0.4) = 0.16$, because negative times negative is positive, which is why the sign of the mistake cannot matter. Then $0.2 - 0.2 = 0.0$, and $0.0 \times 0.0 = 0.00$. Add them: $0.04 + 0.16 + 0.00 = 0.20$. The loss is $0.20$.
Now say training has improved the network and the same input produces the guess $[0.95,\, -0.45,\, 0.2]$. Redo it: $1.0 - 0.95 = 0.05$ and $0.05 \times 0.05 = 0.0025$; $-0.5 - (-0.45) = -0.05$ and $(-0.05) \times (-0.05) = 0.0025$; the third entry is still exact at $0.00$. Add them: $0.0025 + 0.0025 + 0.00 = 0.005$.
The loss fell from $0.20$ to $0.005$, a factor of forty, for a guess that moved by $0.05$ in two places. That steepness is the squaring at work, and it gives training something strong to push against.
One step downhill, by hand
A loss on its own changes nothing. What changes the network is gradient descent, which this chapter does not re-derive, because rolling downhill already does it properly and blame flows backward explains how the blame reaches a weight buried deep inside a network. The one-sentence version: work out which way each adjustable number would have to move to make the loss smaller, then move it a little way in that direction.
To see that happen with real numbers, shrink the network until it has one adjustable number in it. Our toy noise predictor is a single multiplication. It takes the noisy value and scales it by one weight $w$:
$$\epsilon_\theta = w\,x_t$$In words: this pretend network's entire opinion is "the noise is some fixed fraction of what I am looking at", and the fraction $w$ is the only thing it can learn. A real U-Net has hundreds of millions of numbers where this has one, and the arithmetic of updating any single one of them is what follows.
Worked example — one gradient step
Set up the numbers. The noisy value is $x_t = 2$, the true noise we drew is $\epsilon = 1$, and the weight currently sits at $w = 0.3$. Those are round numbers, so you can follow along without a calculator, and nothing about the method depends on them. The learning rate, $\eta$ or eta, sets how big a step we take, and here $\eta = 0.1$. A half would push the weight past the bottom of this valley and out the other side, and a hundredth would be safe but a hundred times slower.
Predict. $\epsilon_\theta = w\,x_t = 0.3 \times 2 = 0.6$.
Measure the error. $\epsilon - \epsilon_\theta = 1 - 0.6 = 0.4$.
Compute the loss. With one number there is one square to add up: $L = (0.4)^2 = 0.4 \times 0.4 = 0.16$.
Find the slope. If I nudge $w$ a little, how much does the loss change, and in which direction? That quantity, the slope of the loss with respect to the weight, is written $\frac{dL}{dw}$, read "d L by d w", and it is called the derivative. The loss as a function of $w$ is $L(w) = (\epsilon - w x_t)^2$, and for this toy network its derivative works out to:
$$\frac{dL}{dw} = -2\,(\epsilon - w\,x_t)\,x_t$$In words: the slope of the loss with respect to the weight is minus twice the error, multiplied by the input that the weight was applied to. Big error or big input means a steep slope and a decisive correction; zero error means zero slope and no change at all.
Where the $-2$ and the trailing $x_t$ come from is the chain rule, which this book borrows rather than builds and which blame flows backward does slowly. Take the formula on trust here.
Put the numbers in: $-2 \times 0.4 \times 2 = -1.6$. The slope is $\frac{dL}{dw} = -1.6$. It is negative, which says that increasing $w$ decreases the loss.
Take the step. Gradient descent moves against the slope, so we subtract the learning rate times the slope:
$$w \leftarrow w - \eta\,\frac{dL}{dw} = 0.3 - 0.1 \times (-1.6) = 0.3 + 0.16 = 0.46$$In words: the arrow means "replace the old weight with this". Subtracting a tenth of a negative slope adds $0.16$, so the weight climbs from $0.3$ to $0.46$. That is a nudge in the direction the slope pointed, not a leap to the answer.
Check that it worked. New prediction: $0.46 \times 2 = 0.92$. New error: $1 - 0.92 = 0.08$. New loss: $(0.08)^2 = 0.08 \times 0.08 = 0.0064$. The loss fell from $0.16$ to $0.0064$, twenty-five times smaller, from one step on one weight.
The training loop
Assembled, the pieces make the thing that runs for weeks on a lot of hardware. Five steps, repeated:
- Take a real apple. Draw one image $\mathbf{x}_0$ from the training set, one of the many varied apples from the big picture, a point sitting inside the data distribution.
- Pick a noise level. Choose the timestep $t$ uniformly at random from $1$ to $T$, the length of the schedule, with $T = 1000$ in a model of this kind. Uniformly means every rung of the ladder is equally likely, so the network gets equal practice at barely-speckled apples and at near-total static.
- Draw the noise. Sample $\boldsymbol{\epsilon} \sim \mathcal{N}(\mathbf{0}, \mathbf{I})$. The tilde reads "drawn from", and the rest reads "the standard bell curve, mean zero, spread one", one independent draw per pixel. Keep it. This is the answer key.
- Build the noisy image. Compute $\mathbf{x}_t = \sqrt{\bar{\alpha}_t}\,\mathbf{x}_0 + \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}$ with the two coefficients looked up from the schedule. That is one multiplication and one addition per pixel, with no simulation and no chain of a thousand small corruptions, because Chapter 2's closed form jumps straight there.
- Score and nudge. Run $\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)$, compute $L(\theta) = \|\boldsymbol{\epsilon} - \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)\|^2$ against the answer key from move 3, and take one gradient step on every number in $\theta$ at once.
Then go back to step 1 with a different apple, a different timestep, and a different noise draw, millions of times. What is not in that list is a loop over the noise levels. The network never walks a whole ladder during training. It gets asked about single rungs picked at random, over and over, until it is good at all of them.
Subtracting the noise
We now have a network that points at the noise. Turning that into a cleaner apple is algebra, and it is ours to do rather than the network's. This is the first half of the reverse process, also called the denoising process. Start from the closed form and isolate the clean image. Move the noise term across:
$$\sqrt{\bar{\alpha}_t}\,\mathbf{x}_0 = \mathbf{x}_t - \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}$$In words: the faded clean image is whatever is left of the noisy image once the scaled noise has been taken away.
Then divide both sides by the fading factor to undo the fade:
$$\mathbf{x}_0 = \frac{\mathbf{x}_t - \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}}{\sqrt{\bar{\alpha}_t}}$$In words: subtract the scaled noise, then divide by alpha-bar-t's square root to restore the original brightness. If we knew the true noise, this would give back the true clean image. The closed form is an equation, not an approximation.
We do not know the true noise. We have a guess. So swap $\boldsymbol{\epsilon}$ for the network's output and mark the result with a hat, which is this book's notation for "an estimate rather than the real thing":
$$\hat{\mathbf{x}}_0 = \frac{\mathbf{x}_t - \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{\bar{\alpha}_t}}$$In words: x-zero-hat is our best guess at the clean image. Take the noisy image, subtract the noise the network thinks is in there, and undo the fade. Every symbol on the right is something we hold: the noisy image, two numbers from the schedule, and one network output.
Worked example — recovering the pixel we destroyed
Chapter 2 took a single pixel with value $\mathbf{x}_0 = 0.8$, ran it to $t = 2$ on the toy schedule $\beta = (0.1,\, 0.2,\, 0.3,\, 0.5)$ where $\bar{\alpha}_2 = 0.72$, drew the noise value $\epsilon = 1.5$, and got $0.6788 + 0.7937 = 1.4725$. Take that same pixel back. We round to four significant figures as we go, carrying the spare digits through each multiplication.
Say the trained network, shown this pixel and told $t = 2$, answers $\epsilon_\theta = 1.4$. The truth was $1.5$, so it is off by a tenth, a decent guess rather than a perfect one. Work the formula from the inside out.
The noise coefficient. $1 - \bar{\alpha}_2 = 1 - 0.72 = 0.28$, and $\sqrt{0.28} = 0.5292$.
Scale the predicted noise. $0.5292 \times 1.4 = 0.7408$.
Subtract it. $1.4725 - 0.7408 = 0.7317$.
The fading coefficient. $\sqrt{\bar{\alpha}_2} = \sqrt{0.72} = 0.8485$.
Undo the fade. $0.7317 \div 0.8485 = 0.8623$.
So $\hat{x}_0 = 0.8623$, against a true $x_0$ of $0.8$. We destroyed a pixel and got it back.
Now look at the error, which matters more than the success. The noise guess was wrong by $1.5 - 1.4 = 0.1$, and the recovered pixel is wrong by $0.8623 - 0.8 = 0.0623$. The two are related by the ratio of the coefficients: $0.5292 \div 0.8485 = 0.6237$, and $0.1 \times 0.6237 = 0.0623$. A mistake in the noise guess arrives in the picture multiplied by that factor.
That amplification factor is the part to take seriously. The $0.6237$ came from $\bar{\alpha}_2 = 0.72$, a mild noise level where most of the apple was still there. Push to a high timestep where $\bar{\alpha}_t$ is small and the picture is nearly all static, and the ratio grows sharply. The divisor $\sqrt{\bar{\alpha}_t}$ shrinks toward zero while the numerator's coefficient grows toward one, so a small error in the noise guess becomes a large error in the apple. And at those levels the guess is poor for the reason we opened with. A heavily corrupted patch is compatible with many different apples, so the prediction hedges between all of them, and the $\hat{\mathbf{x}}_0$ you get from one leap is a soft, characterless blur.
The training objective is not at fault. The network is doing what we asked. The fix is in how we use it, and Chapter 5 builds it: never take the leap. Move a short way down the ladder, look again at a slightly less noisy picture, and let the estimate sharpen as the ambiguity drains away.
The shape of the network
So far we have said what $\boldsymbol{\epsilon}_\theta$ must do without saying what it looks like inside. The usual answer is the U-Net, named for its shape when you draw it, which does look like the letter U. This section describes its structure and leaves its equations alone, because they are the ordinary layers of any image network.
The job pulls in two directions. To decide whether a smear of static is noise or the edge of an apple, the noise predictor needs to see the whole picture. But its answer is delivered pixel by pixel, at full resolution, and wide-angle understanding and fine-grained output are hard to get from the same layers.
The U resolves that in three parts. Coming down the left arm, the U-Net repeatedly shrinks the image and widens it: fewer pixels, more numbers describing each surviving location. Detail is traded for scope, until at the bottom a single position's numbers are influenced by most of the original picture. That bottom is the bottleneck. Going up the right arm, the process reverses, expanding back toward full resolution and painting the coarse understanding onto a finer and finer grid. Across the middle run the skip connections, direct wires from each level of the left arm to the matching level of the right arm, handing the upward path the sharp detail it threw away on the way down. Without them the output is blurry. With them it is crisp. The timestep $t$ is fed in too, converted into a small set of numbers and mixed into every block, so every layer knows which rung it is working on.
See it move
Where you'll meet this
You meet this chapter first as a file. When a workflow graph loads a checkpoint, a
multi-gigabyte .safetensors file with a name like a small brand, what is inside
is $\theta$ and nothing else: the U-Net's hundreds of millions of numbers, billions once the
encoder and the text encoder packed in beside it are counted, ground into shape by the
training loop above. No images, no captions, no index. When people say one checkpoint
"knows" fruit better than another, the difference is in those numbers, put there by a great
many repetitions of draw-noise, predict-noise, nudge.
You meet it again if you ever watch a model train. The number scrolling past in the log is $L(\theta)$ from this chapter, averaged over a batch. It jumps around from one line to the next, because each line used a different apple at a different randomly chosen timestep, and an easy example at a low timestep scores much better than a hard one at a high timestep. A rising loss for a few lines means nothing. Only the trend over thousands of lines does.
You meet it a third time in the vocabulary. When documentation for a model says it was trained with an "epsilon-prediction objective", that phrase is the loss on this page, and it tells you what the noise predictor's output means: static, to be subtracted, not a picture to be looked at.
What you now know
- The reverse direction is ambiguous, because many apples could have produced the same speckled patch, so we never ask the network for the apple. We ask $\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)$ for the noise, which has one right answer per example.
- That answer is free: because we built $\mathbf{x}_t$ ourselves from $\sqrt{\bar{\alpha}_t}\mathbf{x}_0 + \sqrt{1-\bar{\alpha}_t}\boldsymbol{\epsilon}$, we still hold the $\boldsymbol{\epsilon}$ we drew, so every training example arrives with its own answer key and no human labels anything.
- The loss $L(\theta) = \|\boldsymbol{\epsilon} - \boldsymbol{\epsilon}_\theta(\mathbf{x}_t,t)\|^2$ is a sum of squared differences: our three-number guess scored $0.20$, and an improved guess scored $0.005$.
- One gradient step is ordinary arithmetic. With $x_t = 2$, $\epsilon = 1$ and $w = 0.3$ the slope was $-1.6$, and a step of $\eta = 0.1$ moved $w$ to $0.46$, dropping the loss from $0.16$ to $0.0064$.
- Subtracting the predicted noise and undoing the fade gives $\hat{\mathbf{x}}_0 = (\mathbf{x}_t - \sqrt{1-\bar{\alpha}_t}\,\boldsymbol{\epsilon}_\theta)/\sqrt{\bar{\alpha}_t}$, which pulled our pixel from $1.4725$ back to $0.8623$ against a true $0.8$, with the noise guess's $0.1$ error amplified by $0.6237$ on the way.
- The U-Net delivers that prediction by shrinking for scope, growing back for resolution, and carrying detail across on skip connections, with a bottleneck that lives and dies inside a single forward pass.
Where we're headed. We can now train a network to find the noise in a corrupted apple, and we can subtract that noise to get an estimate of the apple back. Those are the two halves of the reverse process, both of them arithmetic you have now done by hand. But count the cost. Every one of those training passes ran the whole U-Net over a full-resolution image, and a single $512 \times 512$ color image is $786{,}432$ numbers going in and $786{,}432$ numbers coming out, millions of times over. The fix is to stop working on pixels and move the whole construction into a much smaller space built by a separate pair of networks, where each image becomes a latent. That is the compression trick, and not one equation from this chapter changes when we get there.