Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

closed form
A formula that gives a value directly, without stepping through every earlier stage.
denoising
Removing some random corruption from a sample in one step, as the model was trained to do.
diffusion model
A generator trained to turn random noise into data by undoing a chain of small corruptions.
forward process
The fixed chain that adds a little random corruption to a clean sample at each step.
Gaussian
A bell-shaped spread of values around a mean, described by that mean and a width.
guidance
Pushing each sampling step harder toward the text you asked for, trading variety for a closer match.
latent space
A smaller space of numbers where a compressor places images, so the model works on short codes.
noise
Random values added to a sample to corrupt it, drawn from a Gaussian.
noise schedule
The rule that decides how much corruption each step adds, and how fast the real pattern fades.
reverse process
The learned chain that removes corruption step by step, starting from pure randomness.
sampler
The procedure that runs the reverse process to produce a finished sample.
signal-to-noise ratio
How much real structure remains compared with the corruption at a given step.
timestep
One position in the corruption chain, numbered from clean to fully random.
VAE
A model that squeezes an image into a small code and rebuilds it, trained to keep what matters.

Diffusion models from the ground up

The reverse process

The reverse step is a Gaussian whose mean depends on the predicted noise. Training is a mean squared error on that prediction, and one step of algebra recovers the clean sample.

Part 3 of 10

Advanced17 min readBack to Courses

The inverse is also Gaussian

If the forward step is small, its reverse is close to Gaussian too. The true reverse of the chain, given the clean sample, has a closed form. It is a Gaussian whose mean is a weighted blend of x_t and x_0, and whose variance is fixed by the betas. The network does not know x_0, so it predicts the mean from x_t and t. That is the whole model: one Gaussian per step, with a learned mean and a variance you can choose.

The variance is usually not learned. The true variance of that reverse step is close to beta for small steps. Fixing it costs almost nothing in quality and removes a hard prediction. Some later models learn it to improve the likelihood, but for sampling the fixed choice is fine. What matters is the mean, and the mean is where the noise prediction enters. A learned variance mostly buys a better likelihood number. It changes the sampler’s path far less than a better schedule or a better mean. If you are optimising for sample quality, spend the effort on the mean first.

From noise to mean

Substitute the closed form for x_0 in terms of x_t and eps, and the reverse mean becomes a simple function of the predicted noise. The update subtracts a scaled version of eps from x_t, then divides by the square root of alpha. Every DDPM implementation you will read is that formula with different bookkeeping. DDPM is the original denoising diffusion model. Get the signs and the square roots right once, and the rest is scheduling.

The same algebra gives a useful debugging identity. Feed the true noise into the reverse step, and you recover the true x_0 exactly, up to floating point. Any implementation that fails that test has a bug, not a training problem. The examples use it before any model is involved. It is also the fastest way to check a new scheduler. Run one step with a known x_0, eps and t, and compare.

One reverse step with a UNet

import torch
from diffusers import DDPMScheduler, UNet2DModel

unet = UNet2DModel(sample_size=64, in_channels=3, out_channels=3)
scheduler = DDPMScheduler(num_train_timesteps=1000)
sample = torch.randn(1, 3, 64, 64)

for t in scheduler.timesteps:
    noise_pred = unet(sample, t).sample
    sample = scheduler.step(noise_pred, t, sample).prev_sample

print(sample.shape, float(sample.mean()))

Recover the clean sample

Run one reverse step with the true noise and confirm it returns the original value. Then feed it four wrong noise guesses and watch the error grow.

Output
Click "Run" to execute your code

The training objective

Training maximises a variational lower bound on the data likelihood. A lower bound is a stand-in for the quantity you cannot compute, chosen so that pushing it up also pushes the real one up. After simplification, most of the bound collapses into a mean squared error between the noise that was added and the noise the network predicts. The timestep is sampled uniformly, the noise is sampled from a standard normal, and the pair is combined with the closed form. No adversarial game, no replay buffer, no schedule for the loss weight.

The simplification drops a per-timestep weight that the true bound implies. That is a deliberate choice. The unweighted objective puts more emphasis on the middle of the schedule, where the model can learn the most. It also produced better samples than the exact bound. Later work put weights back for likelihood. The trade between sample quality and likelihood is still open. For sampling, the simple loss is the right default.

Test the reverse update with the true noise before training anything. It should return the clean sample to within floating point; if it does not, the bug is in the algebra, not in the model.

What the reverse process cannot do

At high noise the reverse distribution is genuinely multimodal. Many clean images are consistent with the same noisy input, and the best mean is their average, which may look like none of them. The model does not hallucinate one answer. It predicts the conditional mean, and the sampler’s added noise is what lets it pick a mode. Remove that noise and you get a blurry average, unless the sampler is built to follow the score sharply.

For that reason, the reverse process is a distribution, not a function. Two runs from the same starting noise with different intermediate draws give different images, and both are valid. Guidance works for the same reason: it sharpens the conditional distribution toward one answer, at the cost of variety. The amount of noise the sampler injects is therefore a modelling choice, not a numerical detail. Too little and the path collapses to a blurry average. Too much and the sample wanders away from the data. The next chapters take the mean apart, choose its variance, and decide how many steps to spend.

The exact denoiser for two points

Print the expected noise for a dataset that contains only minus one and plus one. At low noise the curve becomes a sharp step; at high noise it is almost linear.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What does the reverse step predict?