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 idea of adding noise

Instead of learning to generate in one jump, a diffusion model learns to undo a gradual corruption. Each step is a small denoising problem, and sampling is the path walked backwards.

Part 1 of 10

Advanced14 min readBack to Courses

Destruction is easy

A generative model has to produce samples from a distribution it has only seen examples of. A distribution is the set of all possible outputs, with a weight for how likely each one is. Diffusion takes the hardest part of that job, which is jumping from nothing to a structured sample. It replaces that jump with many small problems that are almost trivial. Take a data point, add a little Gaussian noise (noise drawn from a bell curve), and repeat. After enough steps the structure is gone, and what remains is a standard normal sample (pure noise with mean zero and variance one). The model learns to undo those steps one at a time. Sampling is that path walked backwards.

Each step is small enough that a network only has to estimate a local correction, not invent an image. A thousand of those corrections add up to a sample. For that reason, the literature calls the method learning to denoise rather than learning to generate. Generation is denoising that starts at the maximum noise level. The same machinery also gives you a likelihood, a latent space (a smaller representation the model works in) and a way to condition on text. A likelihood says how probable the data is under the model. That range is why one idea became the basis of most image models.

Noise as a coordinate

Any image can be placed on a scale that runs from clean to pure noise. The forward process assigns every data point a family of noisy versions, indexed by a timestep t. The model’s job is to learn, at every point on that scale, which direction leads back toward data. That direction is the score: the gradient (the slope) of the log density with respect to the input. If you know the score at every noise level, you can walk from noise to data without ever knowing the density itself.

The score is not something we can compute for a photograph, because we do not know the distribution. One identity saves us. For Gaussian noise, the score of the noisy distribution is the conditional expectation of the noise that was added, with a sign and a scale. Predicting the noise and predicting the score are the same task. Every training objective in this course is a variation on that one fact.

Add noise with a scheduler

import torch
from diffusers import DDPMScheduler

scheduler = DDPMScheduler(num_train_timesteps=1000, beta_schedule="linear")
image = torch.randn(4, 3, 64, 64)
noise = torch.randn_like(image)
timesteps = torch.tensor([0, 250, 500, 750])

noisy = scheduler.add_noise(image, noise, timesteps)
print(noisy.shape)
print(scheduler.alphas_cumprod[timesteps])

Measure what noise costs

Add Gaussian noise to a sine wave at five betas and watch the signal-to-noise ratio and the correlation with the clean signal fall. Then push beta to 0.9 and see what is left.

Output
Click "Run" to execute your code

Why not generate in one shot

A GAN asks a network to map noise to data in a single jump. A GAN is a generator trained against a critic that tries to spot fakes. That can work well, but the loss is a moving target. Training is a balance between two networks, and it can fail in confusing ways. Diffusion asks for a much weaker thing at every step: given a slightly noisy sample, estimate the noise that was added. The target is fixed, the loss is mean squared error, and the training curve is boring in the best sense.

The price is speed. A single sample needs one forward pass per step, and a thousand steps is a thousand passes. Much of the engineering in later chapters is about buying those passes back. Better schedules help. So do deterministic samplers, and so does running diffusion in a compressed latent space rather than in pixels.

Set the seed before you compare two runs. Diffusion is stochastic by design, so a difference in the output is only evidence of a change if the starting noise and every intermediate draw are held fixed.

What the network predicts

Three parameterizations show up everywhere. The model can predict the noise eps that was added, the clean sample x_0, or the velocity v. Velocity is a fixed mix of the other two. They carry the same information, so a model trained on one can be converted to another. What changes is how the loss weights the timesteps, and how well the numbers behave at the extremes.

Predicting eps is the original choice and still the default. At t near zero the input is almost clean, so eps is almost pure noise and hard to estimate. At t near the end the input is almost noise, so x_0 is the hard one. Velocity splits the difference, and it is popular with cosine schedules (schedules that keep more signal for longer), where both ends matter. Pick one, write it down, and convert on purpose rather than mixing conventions between training and sampling.

Watch a shape dissolve

Print the same one-dimensional shape at five noise levels. The ramp maps a value of minus one to a space and plus one to an at sign.

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 problem does adding noise solve?