Part II · Ch. 3 — Learning to Undo It

Part II · Chapter 3 of 8

Learning to Undo It

Training a network to spot the noise — the loss, the gradient step, the U-Net


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.

Two rows separated by a hairline. The top row, headed 'what the network does', runs left to right: an amber apple heavily flecked with gray speckles, labeled 'the noisy apple'; a muted arrow into a rounded box outlined in violet holding the symbol epsilon-theta and the words 'the noise predictor', with a small chip labeled 'timestep t' feeding up into its underside; then a muted arrow out to a rectangle of amber and dark checkered static labeled 'predicted noise, same shape as the input'. To the right, in white, the words 'the network never draws an apple'. The bottom row, headed 'what we do with it', shows the arithmetic we do ourselves: the same flecked amber apple, a minus sign, a smaller amber static block, an equals sign, and a nearly clean amber apple labeled 'the estimate', with the note 'a cleaner apple — computed, not predicted' beside it.
The network outputs static, not fruit. The noise predictor $\boldsymbol{\epsilon}_\theta$ takes the noisy image and the timestep and returns a field of numbers the same shape as its input, its guess at the noise (amber). The cleaner apple on the bottom row is something we compute by subtracting, not something the network ever produced.

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 1entry 2entry 3sum
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.

A table drawn as a diagram, headed 'the loss, one entry at a time', with three columns headed entry 1, entry 2, entry 3 and a fourth column headed 'add them up'. Row one, labeled 'true noise' and colored mint, reads 1.0, minus 0.5, 0.2. Row two, labeled 'the guess' and colored amber, reads 0.8, minus 0.1, 0.2. Row three, labeled 'difference' and colored muted gray, reads 0.2, minus 0.4, 0.0. Row four, labeled 'difference squared' and colored red, reads 0.04, 0.16, 0.00, and its sum cell is a red-outlined box reading L = 0.20. Below a hairline, two more rows: 'a better guess' in amber reading 0.95, minus 0.45, 0.2, and 'difference squared' in mint reading 0.0025, 0.0025, 0.00, with a mint-outlined sum box reading L = 0.005. A mint arrow drops from the first sum box to the second, labeled 'forty times smaller'.
The loss is four rows of arithmetic. True noise (mint) minus the guess (amber) gives the differences. Square each and add. A guess that is wrong by $0.2$ and $0.4$ scores $0.20$. A guess that is wrong by $0.05$ twice scores $0.005$.

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.

A graph. The horizontal axis is labeled 'the weight w, the toy network's only adjustable number' and runs from 0 to 1; the vertical axis is labeled 'the loss L' with ticks at 0, 0.16, 0.5 and 1.0. A red parabola falls from 1.0 at the left, touches zero near w = 0.5, and rises again. A violet dot sits on the curve at w = 0.3 where the loss is 0.16, annotated 'we are here: w = 0.3, L = 0.16'. A muted dashed straight line is tangent to the curve at that dot and slopes down to the right, annotated at its lower end 'the tangent: slope = minus 1.6'. Below the curve a short mint arrow runs from w = 0.3 to w = 0.46, labeled 'one step of size eta = 0.1: w = 0.3 to 0.46', with thin drop lines joining each weight to its point on the curve. A second violet dot sits on the curve at w = 0.46, annotated 'after one step: w = 0.46, L = 0.0064'.
The step, drawn. The loss (red) is a valley in $w$; at $w = 0.3$ the ground slopes down to the right with slope $-1.6$. One step of size $\eta = 0.1$ moves us to $w = 0.46$ and drops the loss from $0.16$ to $0.0064$. Real networks do this in hundreds of millions of dimensions at once, with the same arithmetic, one number at a time.

The training loop

Assembled, the pieces make the thing that runs for weeks on a lot of hardware. Five steps, repeated:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.

Five rounded boxes in a left-to-right row, headed 'one visit to the training loop', with muted arrows between them. Step 1, mint: 'take a real apple — one image, x-zero'. Step 2, mint: 'pick a timestep — t, chosen at random'. Step 3, outlined in thicker amber and washed with amber: 'draw the noise — keep it, the answer key'. Step 4, mint: 'build the noisy image — one line of arithmetic'. Step 5, violet: 'score and nudge — the loss L, one step'. An amber dashed arrow arcs over the top from step 3 to step 5, passing through a small amber-outlined label reading 'the answer we already have'. Beneath the row, a muted line runs from step 5 back round to step 1, interrupted by a box reading 'repeat with a new apple, millions of times'. A final muted line at the bottom reads 'one randomly chosen timestep per visit — never a loop over t'.
The loop that trains everything. The amber box is the trick: the noise we draw in step three is handed straight to the scoring step in step five, so no human labels anything. One pass touches one apple at one randomly chosen timestep.

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.

A U-shaped diagram. Down the left arm, four mint-outlined rectangles get progressively narrower, labeled from top to bottom 512 by 512, 256 by 256, 128 by 128 and 64 by 64, with a downward muted arrow between each and a side label reading 'shrink: less detail, more scope'. Across the bottom, a muted line joins the two arms through a violet-outlined box labeled 'the bottleneck'. Up the right arm, four mint rectangles grow back from 64 by 64 to 512 by 512, with upward muted arrows and a side label reading 'grow: place the detail back'. Three horizontal muted dashed arrows cross the middle from each left rectangle to its same-sized partner on the right, each labeled 'skip connection'. An arrow enters the top left labeled 'the noisy image goes in'; an amber arrow leaves the top right labeled 'the predicted noise comes out'. Along the bottom, an amber-outlined chip reading 'the timestep t, mixed in' sends amber dashed lines out to both sides and up past every level.
Down, across, up. The left arm trades detail for scope, the right arm rebuilds resolution, and the skip connections (dashed) carry the fine detail across so the output stays sharp. One warning: the bottleneck at the bottom of the U is a temporary set of numbers that exists only inside a single pass of this network and is thrown away when the pass ends. It is not the compact representation the next chapter is about, and the two must never be confused.

See it move

Watch (19:24): track what leaves the violet box. It is always a field of static, never a picture of fruit. The apple reappears only when the subtraction happens, one panel later.

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.