Forward and Reverse Diffusion
Forward diffusion buries an image in noise by a fixed recipe. Reverse diffusion learns to undo one step of that recipe, and repeating it turns static into a picture.
Why Does This Exist?
Diffusion models pull off a strange trick. They start from pure static and land on a sharp photo that never existed. Training stays calm because it is plain regression, yet sampling takes hundreds of sequential network calls. That trade is the whole deal: stable training bought with slow generation.
Saying "add noise, then remove it" hides the two questions you need answered before the code makes sense. How much noise goes in at each step? And what does the network actually output at one reverse step, the clean image or something smaller? Get those wrong and the training loss looks like a bug and the sampler looks like magic.
This page owns those two answers: the schedule that sets the per-step noise, and the noise target the network predicts. The full DDPM recipe lives in DDPM, the faster walking plans live in diffusion samplers, and the compressed-space version lives in latent diffusion.
The one idea you need first: Gaussian noise, the static this method adds and removes. Each draw is independent randomness with mean zero, added per pixel. The full picture is in normal distribution.
Think of It Like This
Footprints buried under measured scoops of sand
You leave a footprint in wet sand. Then the tide throws one measured scoop of sand over it, then another, following bucket sizes written down in advance. Early scoops are small so the print stays readable. Later scoops are bigger. After the last scoop only a dune remains, and anyone walking by would never guess a footprint sat underneath.
Now a beachcomber arrives with the timetable. You point at the dune and say "tide step 7." They studied thousands of burials, so they do not redraw your foot from memory. They answer a smaller question: "here is the sand the seventh scoop added." You brush off exactly that sand. Repeat for step 6, then 5, all the way back to a clean print.
It maps point for point. The footprint is the clean image. Each scoop is one forward step. The bucket sizes are the noise schedule. The dune is the noisy image. The timetable is the step number the network receives. The comber is the network, and brushing off sand is the reverse subtraction.
Here is where it stops. Brushing sand off a print is exact. Denoising is statistical: the prediction is close but never perfect, so sampling adds a little fresh noise back at each step except the last. And your comber remembers the whole beach, while the network sees only the current image plus its step number.
How It Actually Works
The method has two directions with opposite jobs. The forward process destroys structure on a fixed plan. The reverse process learns to undo one step of that plan. Nothing learns in the forward direction at all.
The forward step adds a known amount of noise
Write for the clean image and for its noisy version at step . At each step you mix in fresh Gaussian noise , which means independent randomness with mean zero and variance one, drawn new every time. How much goes in is set by , the noise amount at step , a small positive number. Define , the signal kept at that step. The one-step rule is:
In plain words: shrink yesterday's image a little, then add a little static. Because every step is Gaussian, you can also jump straight from the clean image to any step. Define , pronounced "alpha bar", as the product of everything kept so far: , the cumulative surviving signal. Then:
The list is the noise schedule, fixed before training starts. Its shape decides where the hard work lands. A schedule that adds noise fast early destroys structure quickly, so the first reverse steps face the coarsest question (is this even a face?) while late steps polish texture. Nobody learns the schedule here. You pick it, and picking badly shows up as blurry shapes or gritty detail.
The reverse step predicts the noise, then subtracts it
The network never guesses the clean image directly. It takes the noisy image plus the step number and outputs , pronounced "epsilon hat", its prediction of the noise inside. Training is convenient because you created the answer yourself: during training you sampled to build , so the loss is plain regression between the true noise and the guess:
That is the mean squared error over the noise vectors. One step of denoising then turns the prediction into , the mean of the previous, slightly cleaner image:
You scale the current image up slightly and subtract a scaled copy of the predicted noise. Sampling sets , where is the reverse step's standard deviation from the schedule and is a fresh Gaussian draw, fresh randomness like . The last step skips that fresh noise and keeps as the finished image.
Why predict noise instead of pixels? Early in the chain almost no signal remains, so guessing the whole photo is hopeless while guessing the static is still well defined. The target is known exactly at training time, which keeps training stable.
Name the trade straight. You get stable supervised training and varied samples, and you pay with sequential sampling: each image needs one network call per visited step, each waiting on the last. If you need one forward pass per image, this chain is the wrong tool. Use a single-pass generator or a distilled few-step model such as consistency models. The standing assumption is Gaussian noise on a fixed Markov chain, meaning each step depends only on the last. Break it with a schedule tuned for tiny thumbnails reused on large photos, and structure dies too fast to rebuild.
Worked example: one step out and one step back
Take one pixel value and a single step with . Then , and since this is the first step too. The scalings are for the signal and for the noise. Draw :
Clean becomes noisy . That is the diagram's middle box.
Now suppose the trained network predicts , close to the true . The loss is . The reverse mean reuses the same schedule numbers. First the correction scale: . Then:
So one reverse step moves back to about , nearly home to . The error left over ( versus ) comes straight from the prediction gap ( versus ). Better noise guesses mean cleaner steps, which is why the loss above is the entire training signal.
Code
The snippet below replays that exact step. It is the mechanism, not the formula retyped: corrupt once, score the prediction, walk one step back.
import math
def forward_step(x0: float, eps: float, beta: float) -> float: alpha: float = 1.0 - beta return math.sqrt(alpha) * x0 + math.sqrt(beta) * eps
def reverse_mean(x_t: float, eps_hat: float, beta: float, alpha_bar: float) -> float: alpha: float = 1.0 - beta correction: float = beta / math.sqrt(1.0 - alpha_bar) * eps_hat return (x_t - correction) / math.sqrt(alpha)
x1: float = forward_step(x0=1.0, eps=0.5, beta=0.36)print(round(x1, 4)) # -> 1.1
mu: float = reverse_mean(x_t=x1, eps_hat=0.45, beta=0.36, alpha_bar=0.64)print(round(mu, 4)) # -> 1.0375
loss: float = (0.5 - 0.45) ** 2print(round(loss, 4)) # -> 0.0025The prints match the hand computation: noisy , one step back to , loss . Change eps_hat to and mu lands exactly on , which shows the loss is the only thing steering sample quality.
Watch Out For
Reading the loss as image error instead of noise error
You open a training loop, see predictions compared against random static, and assume someone mixed up the target. So you "fix" it to predict the clean image, and training turns unstable for no visible gain.
The comparison against noise is the method. The forward pass sampled itself, making it a free supervised label. Keep the target as the added noise and read the loss as denoising skill, not image quality.
Skipping steps at sampling time as if they were optional
A thousand sequential calls feels slow, so you sample every tenth step with the same update and get washed-out shapes plus speckled texture. The symptom looks like an undertrained model, which sends you back to train longer.
Skipped levels need different arithmetic, not fewer calls to the same line. Use a sampler built for strides instead of raw skipping, as worked through in diffusion samplers.
The Quick Version
- Forward diffusion corrupts an image through fixed Gaussian steps, and the noise schedule sets how much each step adds.
- The cumulative signal tells you how much of the original image survives at any step.
- The network predicts the noise inside the current image, not the clean image itself.
- Each reverse step subtracts a scaled copy of that predicted noise to reach a slightly cleaner image.
- Training is regression against the very noise the forward pass added, so its label is always known.
- Sampling is slow because steps run in order, which is why fewer-step samplers exist for the same network.