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 every ingredient โ the shrink, the noise, the schedule โ was something we chose. Going the other way is the entire remaining problem, and the only part of this book that requires a network at all.
Here is the shape of what we are about to do. We will not build a machine that looks at a noisy apple and paints a clean one. We will build a machine that looks at a noisy apple and points at the noise โ and then we will do the subtraction ourselves, with arithmetic you can check by hand. That distinction sounds pedantic in this paragraph and it is the most important sentence in the chapter. By the end you will have computed a loss, taken a gradient step with real numbers, and pulled a pixel back from $1.4725$ to close to the $0.8$ it started as.
Why we ask for the noise
Start with the honest difficulty. The forward process โ adding noise on purpose โ 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 exact 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 do not ask for the apple. We ask: of the numbers in front of you, which part was the noise? That question has exactly one right answer for every training example we will ever build, and โ this is the trick that makes the whole field work โ we know that answer, because we are the ones who drew the noise.
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 itself is a promise about what comes out: noise, not an image. The subscript $\theta$ โ theta โ stands for every adjustable number inside the network at once โ for a U-Net of the kind this chapter describes, several hundred million of them, and billions once the other trained pieces of a checkpoint are counted alongside it; if you have met the neuron, $\theta$ is every weight and every bias in the whole stack, gathered into one symbol. And the two things in the brackets are its only two inputs: $\mathbf{x}_t$, the noisy image, and $t$, the timestep โ the noise level, 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, and the right answer is a faint noise field; high up it is almost all noise with a ghost of apple in it, and the right answer is nearly the whole picture. Telling the network which rung it is standing on is what 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, and the reason is 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 recipe for manufacturing homework. 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$. You now hold a training example whose input is $(\mathbf{x}_t, t)$ and whose correct answer is $\boldsymbol{\epsilon}$ โ not because anyone labeled it, but because you drew it thirty milliseconds ago and still have it in your hand.
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. Here it is:
$$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 โ the smaller it is, the closer the guess was.
The double bars $\|\cdot\|$ are the length of a list of numbers; 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 does two jobs: it 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 deliberately: one entry the network guesses too low, one it guesses too high, and one it gets exactly right โ so all three cases show up in a single table. Watch what the squaring does to each of them.
| 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$ โ negative times negative is positive, which is exactly 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 suppose training has improved the network and the same input now 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 only moved by $0.05$ in two places. That steepness is the squaring at work, and it is what gives training something strong to push against.
One step downhill, by hand
A loss on its own changes nothing; it is a thermometer, not a treatment. The treatment is gradient descent, which we are not going to re-derive here 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 exactly 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; the arithmetic of updating any single one of them is exactly 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 chosen so you can follow along without a calculator, and nothing about the method depends on them. The learning rate โ $\eta$, eta, the number that sets how big a step we take โ is $\eta = 0.1$. Why a tenth? A half would fling the weight past the bottom of this valley and out the other side, and a hundredth would be safe but a hundred times slower. A tenth is stable here and large enough that you can see the effect of a single step.
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. What we need to know is this: 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 one piece of machinery this book borrows rather than builds โ it is the chain rule, done slowly in blame flows backward. Take the formula on trust here, and check as we go that it behaves the way a slope should: no error means no slope and no change, and a bigger input means a steeper slope and a bigger correction.
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: 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$ โ 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
Now assemble the pieces into the thing that actually runs, for weeks, on a lot of hardware. Five moves, 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 โ illustratively $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. One multiplication and one addition per pixel โ no simulation, 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 move 1 with a different apple, a different timestep, and a different noise draw. Millions of times. Notice what is not in that list: there is no loop over the noise levels. Each visit to the loop touches exactly one randomly chosen $t$. The network never walks a whole ladder during training; it just gets asked, over and over, about single rungs picked at random, 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 pure algebra, and it is ours to do, not 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 exactly, this would give back the true clean image exactly โ 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.)
Suppose 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, not a perfect one. Now 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, and you can check every digit with a calculator.
Now look at the error, because it is more interesting than the success. The network's noise guess was wrong by $1.5 - 1.4 = 0.1$. The recovered pixel is wrong by $0.8623 - 0.8 = 0.0623$. Those 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.
Here is the part to take seriously. The factor $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 that 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 is blown up into a large error in the apple. And at those levels the guess is necessarily poor, for the reason we opened with: a heavily corrupted patch is compatible with many different apples, so the honest prediction hedges between all of them, and the $\hat{\mathbf{x}}_0$ you get from one leap is a soft, characterless blur.
That is not a flaw in the training objective โ the network is doing precisely what we asked. It is an argument about how to use it, and the resolution, which Chapter 5 builds, is to 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
We have said what $\boldsymbol{\epsilon}_\theta$ must do without once saying what it looks like inside. The usual answer is the U-Net โ named for its shape when you draw it, which really does look like the letter U. We will describe it architecturally and leave its equations alone; they are the ordinary machinery of any image network.
The job has a genuine tension in it. 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 has to be delivered pixel by pixel, at full resolution, with fine detail intact โ and wide-angle understanding and fine-grained output are hard to get from the same layers.
The U resolves it in three moves. Coming down the left arm, the U-Net repeatedly shrinks the image and widens it: fewer and fewer pixels, more and more numbers describing each surviving location. Detail is traded away for scope, until at the bottom a single position's numbers are influenced by essentially the entire original picture. That bottom is the bottleneck. Going up the right arm, the process reverses: expand back toward full resolution, step by step, painting the coarse understanding back onto a finer and finer grid. And 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, un-shrunk detail it threw away on the way down. Without them the output is a blurry approximation of the right answer; 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 of the ladder it is working on.
See it move
Where you'll meet this
The most concrete place you meet this chapter is 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$: the U-Net's hundreds of millions of numbers โ billions, once the
encoder and the text encoder packed in beside it are counted โ that the training loop above
ground into shape, and nothing else. No images, no captions, no index. When people compare two
checkpoints and say one "knows" fruit better, the difference is entirely in those numbers, put
there by a great many repetitions of draw-noise, predict-noise, nudge.
You meet it a second time if you ever watch a model train. The number scrolling past in the log, the one everybody stares at, is $L(\theta)$ from this chapter, averaged over a batch of examples. It is noisy from one line to the next โ of course it is: 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 means anything.
And 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 exactly the loss on this page, and it is telling 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 โ 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 exactly 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 โ the two halves of the reverse process, both of them arithmetic you have now done by hand. But count the cost of what we just specified. 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 altogether and move the entire machinery into a much smaller space built by a separate pair of networks, where each image becomes a latent โ the compression trick, and not one equation from this chapter changes when we get there. The machinery works, and it is far too expensive to run on 786,432 numbers.