Quant Memo
Advanced

Denoising Diffusion Probabilistic Models

Diffusion models generate realistic data by learning to undo noise: train a network to remove a little static from a slightly corrupted image or price path, then chain thousands of tiny cleanup steps starting from pure static to synthesize something new.

Prerequisites: Latent Variable Models and the ELBO, Markov Chains

Building a model that generates realistic new data — a face, a price path — directly in one shot is hard: the network would have to leap straight from nothing to a fully coherent, detailed output, getting every pixel or every price tick right simultaneously with no room to fix mistakes along the way. Diffusion models sidestep this by never asking for a one-shot leap. Instead they train on a much easier task — given a slightly noisy version of real data, predict just the noise that was added — and then chain thousands of these easy, small corrections together, starting from pure static, to gradually sculpt something realistic out of nothing. Each individual step barely has to do anything; the difficulty gets spread across the whole chain instead of concentrated in one shot.

The analogy: restoring a photo through a thousand small touch-ups

Imagine a photo restorer handed a picture with static sprinkled on it — not ruined, just slightly grainy. Removing that light static and recovering something close to the clean photo is a manageable task; a competent restorer can do it confidently. Now imagine the same restorer handed a photo that is pure static, no picture underneath at all, and asked to produce a photorealistic image from it in one pass — an impossible task, there's no signal there to recover. But suppose instead they're allowed a thousand passes: touch up the static very slightly, then touch up the result very slightly again, then again, each time using the same "remove a little static" skill they're actually good at. After a thousand tiny touch-ups, structure emerges from noise gradually, the same way a print slowly appears in a darkroom developing bath. Diffusion models train the "remove a little static" skill on real data, then run that skill in reverse, a thousand small steps starting from pure noise, to synthesize something new.

The mechanism: add noise forward, learn to remove it backward

The forward process takes a real data point x0x_0 and corrupts it over TT steps by mixing in a little Gaussian noise at each step, so that xtx_t (the data after tt steps of corruption) is a weighted blend of the previous step and fresh noise:

xt=1βtxt1+βtϵt,ϵtN(0,1)x_t = \sqrt{1-\beta_t}\, x_{t-1} + \sqrt{\beta_t}\, \epsilon_t, \qquad \epsilon_t \sim \mathcal{N}(0, 1)

Here βt\beta_t (a small number between 0 and 1, called the noise schedule) controls how much noise gets mixed in at step tt, and ϵt\epsilon_t is a fresh draw of standard noise. In words: each step keeps most of the previous signal and adds a small, controlled dose of static, and after enough steps xTx_T is indistinguishable from pure noise — no signal left at all. Crucially, this forward corruption is not learned; it's a fixed, known recipe, so at training time the exact amount of noise added at any step is known precisely.

The reverse process is what actually gets trained: a network ϵθ(xt,t)\epsilon_\theta(x_t, t) that looks at a noisy xtx_t and the step number tt, and predicts exactly which noise was added to produce it. The training loss is simply how far off that prediction is:

L=E[ϵtϵθ(xt,t)2]L = \mathbb{E}\left[\, \| \epsilon_t - \epsilon_\theta(x_t, t) \|^2 \,\right]

In words: take a real data point, corrupt it a known random amount, ask the network to guess the noise, and penalize the squared distance between its guess and the true noise. Once trained, generation runs the process backward: start from pure noise xTx_T, use the network's noise prediction to subtract a small estimated amount of noise, arrive at a slightly cleaner xT1x_{T-1}, and repeat all the way down to x0x_0 — a real-looking sample built entirely by iterative, small denoising steps.

forward: add a little noise, many times → x₀ clean xᵀ noise ← reverse: learned network removes a little noise, many times generation starts on the right (pure noise) and walks left (a new sample)
The forward corruption is a fixed, known recipe; the reverse denoising is the one thing the network actually learns, applied repeatedly.

The noise schedule βt\beta_t typically grows across the TT steps — small early, larger later — which the function-plot explorer below can approximate with a growing curve; watch how a slowly-rising function stays gentle at first and steepens later, the same shape used to keep early denoising steps easy and let later steps do more work per step.

Function explorer
-2222.0
x = 1.00f(x) = 2.000

Worked example 1: one forward noising step by hand

Take a single clean value x0=10.0x_0 = 10.0 (think of it as one price on a synthetic path) and a noise level β1=0.19\beta_1 = 0.19, so 1β1=0.81=0.9\sqrt{1-\beta_1} = \sqrt{0.81} = 0.9 and β1=0.190.436\sqrt{\beta_1} = \sqrt{0.19} \approx 0.436. Draw ϵ1=0.5\epsilon_1 = 0.5. Then

x1=0.9(10.0)+0.436(0.5)=9.0+0.218=9.218x_1 = 0.9(10.0) + 0.436(0.5) = 9.0 + 0.218 = 9.218

The value moved from 10.010.0 to 9.2189.218 — mostly still the original signal, with a small, known amount of noise mixed in. A network trained on this exact pair (x1,ϵ1=0.5)(x_1, \epsilon_1=0.5) would be graded on how close its prediction ϵθ(x1,1)\epsilon_\theta(x_1, 1) comes to 0.50.5.

Worked example 2: one reverse denoising step

Suppose after training, the network is given x1=9.218x_1 = 9.218 at step 1 and predicts ϵθ=0.47\epsilon_\theta = 0.47 (close to, but not exactly, the true 0.50.5 used above). Reconstructing an estimate of x0x_0 by inverting the forward formula:

x^0=x10.436(0.47)0.9=9.2180.2050.9=9.0130.9=10.014\hat{x}_0 = \frac{x_1 - 0.436(0.47)}{0.9} = \frac{9.218 - 0.205}{0.9} = \frac{9.013}{0.9} = 10.014

The network's estimate, 10.01410.014, lands very close to the true original value of 10.010.0 — the small error in its noise prediction (0.470.47 vs the true 0.50.5) only produced a small error in the reconstructed value. In a real model this single step is followed by hundreds or thousands more like it, each one nudging a noisy sample a little closer to something realistic, and each one only responsible for a small, forgivable amount of error.

Diffusion models never learn to generate directly — they learn only to predict noise in a corrupted sample, a task simple enough to train reliably. Realistic generation emerges purely from chaining that one learned skill across hundreds or thousands of small reverse steps, starting from pure static.

What this means in practice

Diffusion models are the dominant approach behind modern image and audio generators, and the same machinery is being explored for synthetic financial time series — generating plausible price paths or order-flow sequences by learning to denoise corrupted historical data, then sampling new paths from pure noise. Because generation requires running the network many times in sequence (once per denoising step), diffusion models are markedly slower to sample from than a single-pass generator like a VAE, a real cost that motivates active research into fewer, larger denoising steps.

It's tempting to think the forward noising process is the "generative" part being learned, since it's the one described first. It's the opposite: the forward process is fixed and known by design, never learned — it's just a scheduled recipe for destroying signal. The only thing the network ever learns is the reverse step, predicting noise from a corrupted sample. Mixing these up leads to the common misconception that diffusion models need to be trained to add realistic noise, when in fact adding noise is trivial and fixed; removing it is the entire learning problem.

Practice

  1. If βt\beta_t were set to exactly 1.01.0 at some step, what would xtx_t become in terms of xt1x_{t-1}, and why would that step destroy all remaining signal in one move?
  2. Using the reverse formula above, find x^0\hat{x}_0 if x1=9.218x_1 = 9.218 but the network's noise prediction is badly wrong at ϵθ=0.5\epsilon_\theta = -0.5. How far off does the reconstruction land, and what does that suggest about early training?
  3. Why does generation from a trained diffusion model require running the network hundreds of times, while a variational autoencoder produces a sample from a single forward pass through its decoder?

Related concepts

Practice in interviews

Further reading

  • Ho, Jain & Abbeel, Denoising Diffusion Probabilistic Models (2020)
  • Sohl-Dickstein et al., Deep Unsupervised Learning using Nonequilibrium Thermodynamics (2015)
ShareTwitterLinkedIn