Course contents 26 / 33

26 / 33 · Diffusion Models

DDPM: the forward process

How denoising diffusion models destroy data on purpose. A naive add-noise chain explodes in variance, and the rescaled step √(1 − β) x + √β ε gives a closed-form jump q(xₜ | x₀) that approaches N(0, I), with linear, quadratic, sigmoid or cosine β schedules in practice.

On this page 8

The energy-based models note ended on a cost: an energy-based model is trained with short, biased MCMC chains run inside every parameter update, so the model it learns depends on its sampler as much as on its data. Diffusion models take sampling out of training. They fix a simple noising process that turns data into Gaussian noise and learn to undo it one small step at a time. Each step back is close to a Gaussian, so a network learns it by regression on noisy samples that the fixed process produces for free. That network turns out to learn the score of the noised data, the negative gradient of an energy and the direction that Langevin sampling follows (score matching note). The noisy latents keep the data’s dimension, the network is unconstrained, and the price is a bound on the likelihood instead of the likelihood itself. DDPM, Denoising Diffusion Probabilistic Models (Ho, Jain and Abbeel, 2020), is the model that brought diffusion to image quality comparable with GANs. This note covers its first half, the forward process: a fixed procedure that slowly turns an image into Gaussian noise. The second half, a neural network that runs the procedure backwards, is in the next note.

Notation. x0x_0 is a data point (an image) and xtx_t its noised version after tt steps, t=1,…,Tt = 1, \dots, T. qq denotes the fixed forward (noising) process: q(x0)q(x_0) is the distribution of the data and q(xt∣xt−1)q(x_t \mid x_{t-1}) one noising step. pθ(xt−1∣xt)p_\theta(x_{t-1} \mid x_t) is the learned reverse step, with network parameters θ\theta. ε∼N(0,1)\varepsilon \sim \mathcal N(0, 1) is standard Gaussian noise drawn fresh at every step, and the second argument of N(μ,σ2)\mathcal N(\mu, \sigma^2) is the variance. We work in one dimension; for images every pixel is noised independently and 11 becomes the identity matrix II, so the target is N(0,I)\mathcal N(0, I).

A little history#

  • In 2015, when GANs were the state of the art in image generation, Sohl-Dickstein et al. (2015) published Deep Unsupervised Learning using Nonequilibrium Thermodynamics. It introduced the idea of diffusion models: destroy the structure of the data with a slow noising process, then learn to reverse it.
  • Five years later DDPM simplified the parameterization and the loss and reached image quality competitive with GANs. Its training objective is still derived from a variational lower bound on the likelihood, the same tool as in the VAE.
  • Shortly afterwards diffusion models overtook GANs on standard image benchmarks (Dhariwal and Nichol, 2021).

The problem#

We do not know the distribution of real images, but we want to sample new images from it. In diffusion notation this distribution is written q(x0)q(x_0), because it is where the forward process qq starts.

The diffusion idea is to connect q(x0)q(x_0) to a distribution we can sample from. Take a real image x0x_0, the original photo, and add a little noise to get x1x_1, then a little more to get x2x_2, and so on until xTx_T is pure noise. Each forward step is fixed and needs no learning. The model, the learned reverse step pθ(xt−1∣xt)p_\theta(x_{t-1} \mid x_t), goes the other way: from xtx_t it produces xt−1x_{t-1}, one step back towards the image. To generate, we sample pure noise xTx_T and apply the model TT times.

x0image  ⟶  x1  ⟶  ⋯  ⟶  xTnoise,xt−1  ←  pθ(xt−1∣xt)    xt.\begin{gathered} \underset{\text{image}}{x_0} \;\longrightarrow\; x_1 \;\longrightarrow\; \cdots \;\longrightarrow\; \underset{\text{noise}}{x_T}, \\ x_{t-1} \;\xleftarrow{\;p_\theta(x_{t-1} \mid x_t)\;}\; x_t . \end{gathered}
Figure

The forward chain adds noise; the model walks back

Diffusion chain from an original photo to pure noiseFour pixel tiles in a row: x0 the original photo of a sun and a hill, x1 with some noise, x2 with more noise, then an ellipsis, then xT which is pure noise. Straight arrows labelled add noise go left to right. Curved arrows above go right to left, labelled p theta of x0 given x1, p theta of x1 given x2 and p theta of xT minus 1 given xT: the learned reverse step. A long arrow below says forward process q of xt given xt minus 1, fixed; a long arrow at the top says reverse process, learned model.reverse: learned model pθ (goes back one step)x0originalphotox1addnoisex2morenoisexTpurenoise…add noiseadd noisepθ(x0 | x1)pθ(x1 | x2)pθ(xT−1 | xT)forward process q(xt | xt−1): fixed, just adds noiseDiffusion chain from an original photo to pure noiseFour pixel tiles in a column: x0 the original photo of a sun and a hill, x1 with some noise, x2 with more noise, an ellipsis, then xT, pure noise. Arrows labelled add noise point down. Curved blue arrows on the right point up, labelled p theta of x0 given x1, p theta of x1 given x2 and p theta of xT minus 1 given xT: the learned reverse step going one step back.x0original photox1add noisex2more noisexTpure noise⋮add noiseadd noisepθ(x0 | x1)pθ(x1 | x2)pθ(xT−1 | xT)blue: learned model, one step back
Forward arrows are the fixed noising step q(xₜ | xₜ₋₁); the curved arrows are the learned reverse step pθ(xₜ₋₁ | xₜ), which takes xₜ and goes one step back. The tiles are real samples of xₜ = √α̅ₜ x₀ + √(1 − α̅ₜ) ε for α̅ = 1, 0.8, 0.5 and ≈ 0 (4 × 10⁻⁵, the end of DDPM's schedule) with one fixed noise draw ε.

A first attempt: just add noise#

The simplest step adds noise with variance β\beta:

x1=x0+β ε,ε∼N(0,1)⟹q(x1∣x0)=N(x0,β),\begin{gathered} x_1 = x_0 + \sqrt{\beta}\,\varepsilon, \quad \varepsilon \sim \mathcal N(0, 1) \\ \Longrightarrow\quad q(x_1 \mid x_0) = \mathcal N(x_0, \beta), \end{gathered}

where β\beta is the noise variance. Note the square root: c εc\,\varepsilon has variance c2c^2, so noise with variance β\beta is β ε\sqrt\beta\,\varepsilon. The next step does the same to x1x_1: q(x2∣x1)=N(x1,β)q(x_2 \mid x_1) = \mathcal N(x_1, \beta).

Now we can shorten the chain. Two steps add two independent noises, and the variances of independent Gaussians add up:

x2=x1+β ε2=x0+β ε1+β ε2=x0+2β ε,q(x2∣x0)=N(x0,2β),\begin{aligned} x_2 &= x_1 + \sqrt\beta\,\varepsilon_2 \\ &= x_0 + \sqrt\beta\,\varepsilon_1 + \sqrt\beta\,\varepsilon_2 \\ &= x_0 + \sqrt{2\beta}\,\varepsilon, \\ q(x_2 \mid x_0) &= \mathcal N(x_0, 2\beta), \end{aligned}

where ε=(ε1+ε2)/2\varepsilon = (\varepsilon_1 + \varepsilon_2)/\sqrt2 is again a standard normal. Whenever several noises are merged below, ε\varepsilon denotes the merged standard normal in this sense, so such equalities hold in distribution.

Continuing in the same way, after tt steps

xt=x0+tβ ε,q(xt∣x0)=N(x0,tβ).\begin{gathered} x_t = x_0 + \sqrt{t\beta}\,\varepsilon, \\ q(x_t \mid x_0) = \mathcal N(x_0, t\beta). \end{gathered}

This is a useful shortcut: we can jump from x0x_0 to any xtx_t in one draw. But look at the two parameters:

  • the mean does not change: it stays x0x_0 forever;
  • the variance increases indefinitely: tβ→∞t\beta \to \infty.

So the chain never reaches N(0,1)\mathcal N(0, 1): the variance grows without bound, and there is no fixed limiting distribution from which generation could start. The image’s influence fades only relative to the growing spread. This process is called variance-exploding diffusion (Song et al., 2021, §3.4). Models built on it stop at a large finite noise level σmax⁡\sigma_{\max} and start sampling from N(0,σmax⁡2)\mathcal N(0, \sigma_{\max}^2) (Song et al., 2021, §2.1).

The objective, and the rescaled step#

What we want is

q(xt∣x0)→t→∞N(0,1),q(x_t \mid x_0) \xrightarrow[t\to\infty]{} \mathcal N(0, 1),

whatever the starting image. This needs a new way to go from step t−1t-1 to step tt, and in particular the step has to change the mean each time, pulling it towards 00. In general, Sohl-Dickstein et al. allow any Markov kernel Tπ(xt∣xt−1;βt)T_\pi(x_t \mid x_{t-1}; \beta_t) that leaves a simple target distribution π\pi unchanged, π(y)=∫Tπ(y∣y′;β) π(y′) dy′\pi(y) = \int T_\pi(y \mid y'; \beta)\,\pi(y')\,dy' (2015, §2.1, Eq. 1–2): a binomial kernel for binary data, a Gaussian kernel for real values. For real values we look for a step of the form xt=a xt−1+β εx_t = a\,x_{t-1} + \sqrt\beta\,\varepsilon. The Gaussian kernel of diffusion models, introduced by Sohl-Dickstein et al. (2015, Table App.1) and kept by DDPM (Ho, Jain and Abbeel, 2020, Eq. 2), scales the previous point by a=1−βa = \sqrt{1-\beta}:

xt=1−β  xt−1+β  ε,q(xt∣xt−1)=N ⁣(1−β  xt−1,  β).\begin{gathered} x_t = \sqrt{1-\beta}\;x_{t-1} + \sqrt{\beta}\;\varepsilon, \\ q(x_t \mid x_{t-1}) = \mathcal N\!\big(\sqrt{1-\beta}\;x_{t-1},\; \beta\big). \end{gathered}
Figure

One step at a time, or straight from x₀ to xₜ

Naive and DDPM noising chains with their one-jump shortcutsTwo rows of circled nodes x0, x1, x2, an ellipsis and xt joined by step arrows. Top row, naive: each step adds square root of beta times epsilon; a long arc from x0 to xt is labelled q of xt given x0 equals N of x0 and t beta, with a red warning that the mean stays x0 and the variance t beta goes to infinity, so the chain never reaches N(0, 1). Bottom row, DDPM: each step multiplies by the square root of 1 minus beta and adds square root of beta times epsilon; the long arc is labelled q of xt given x0 equals N of square root of alpha bar t times x0 and 1 minus alpha bar t, with a green note that alpha bar t equals 1 minus beta to the power t, which goes to zero, so the chain approaches N(0, 1).Naive: xₜ = xₜ₋₁ + √β εx0x1x2xt…+ √β ε+ √β εq(xₜ | x₀) = N(x₀, tβ)mean stays x₀, variance tβ → ∞: never N(0, 1)DDPM: xₜ = √(1 − β) xₜ₋₁ + √β εx0x1x2xt…× √(1 − β)+ √β ε× √(1 − β)+ √β εq(xₜ | x₀) = N(√α̅ₜ x₀, 1 − α̅ₜ)α̅ₜ = (1 − β)ᵗ → 0, so → N(0, 1)Naive and DDPM noising chains with their one-jump shortcutsTwo rows of circled nodes x0, x1, x2, an ellipsis and xt joined by step arrows. Top row, naive: each step adds square root of beta times epsilon; a long arc from x0 to xt is labelled q of xt given x0 equals N of x0 and t beta, with a red warning that the mean stays x0 and the variance t beta goes to infinity, so the chain never reaches N(0, 1). Bottom row, DDPM: each step multiplies by the square root of 1 minus beta and adds square root of beta times epsilon; the long arc is labelled q of xt given x0 equals N of square root of alpha bar t times x0 and 1 minus alpha bar t, with a green note that alpha bar t equals 1 minus beta to the power t, which goes to zero, so the chain approaches N(0, 1).Naive: xₜ = xₜ₋₁ + √β εx0x1x2xt…q(xₜ | x₀) = N(x₀, tβ)mean stays x₀, variance tβ → ∞: never N(0, 1)DDPM: xₜ = √(1 − β) xₜ₋₁ + √β εx0x1x2xt…q(xₜ | x₀) = N(√α̅ₜ x₀, 1 − α̅ₜ)α̅ₜ = (1 − β)ᵗ → 0, so → N(0, 1)
Single steps and one-jump shortcuts for the two chains. Both add fresh Gaussian noise ε ~ N(0, 1) at every step, and in both the t steps collapse into one Gaussian jump q(xₜ | x₀), so xₜ can be sampled directly. Without rescaling (top) the jump keeps the mean at x₀ and its variance grows without bound. Scaling by √(1 − β) at each step (bottom) shrinks the mean and keeps the conditional variance 1 − α̅ₜ below 1, so the chain approaches N(0, 1). The second argument of N is the variance.

Why exactly 1−β\sqrt{1-\beta}? The fresh noise is independent of xt−1x_{t-1}, so the variance obeys Var⁡(xt)=a2Var⁡(xt−1)+β\operatorname{Var}(x_t) = a^2 \operatorname{Var}(x_{t-1}) + \beta. This recursion settles at 11, the variance of the target, only if a2+β=1a^2 + \beta = 1. So a=1−βa = \sqrt{1-\beta} is the only positive scale that keeps a unit variance at 11, and it also pulls any other variance towards 11 (callout below). With this aa the jump from x0x_0 to any xtx_t takes an especially simple closed form, whose two squared coefficients sum to 11 (Ho, Jain and Abbeel, 2020, Eq. 4):

xt=αˉt x0+1−αˉt  ε,αˉt=(1−β)t,\begin{gathered} x_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1-\bar\alpha_t}\;\varepsilon, \\ \bar\alpha_t = (1-\beta)^t, \end{gathered} q(xt∣x0)=N ⁣(αˉt x0,  1−αˉt).q(x_t \mid x_0) = \mathcal N\!\big(\sqrt{\bar\alpha_t}\,x_0,\; 1-\bar\alpha_t\big).

With αˉ0=1\bar\alpha_0 = 1 the formula also covers t=0t = 0. So we can produce xtx_t for any timestep directly from x0x_0, in one draw, without running the tt steps before it.

Why this reaches N(0, 1)#

If β∈(0,1)\beta \in (0, 1), then αˉt=(1−β)t→0\bar\alpha_t = (1-\beta)^t \to 0 as t→∞t \to \infty. Then the image term αˉt x0→0\sqrt{\bar\alpha_t}\,x_0 \to 0, while the noise coefficient 1−αˉt→1\sqrt{1-\bar\alpha_t} \to 1, so the noise term tends to plain ε\varepsilon with variance 11:

q(xt∣x0)→t→∞N(0,1).q(x_t \mid x_0) \xrightarrow[t\to\infty]{} \mathcal N(0, 1).

For example, with a constant β=0.02\beta = 0.02:

ttαˉt=0.98t\bar\alpha_t = 0.98^tmean coefficient αˉt\sqrt{\bar\alpha_t}noise std 1−αˉt\sqrt{1-\bar\alpha_t}naive noise std tβ\sqrt{t\beta}
10.9800.9900.1410.141
100.8170.9040.4280.447
500.3640.6030.7971.000
1000.1330.3640.9311.414
2000.01760.1330.9912.000

For small tt the two chains almost agree. Then the naive one passes the target spread and keeps growing, while DDPM’s approaches 11 from below. At a finite TT the image term αˉT x0\sqrt{\bar\alpha_T}\,x_0 is small only relative to the scale of x0x_0, which is one reason images are scaled to [−1,1][-1, 1] before diffusion (next note).

Figure

Variance exploding versus variance preserving

Mean coefficient and noise standard deviation of q(xt | x0) over tTwo plots over t from 0 to 200 with beta equal to 0.02. A dashed green line at height 1 marks the target standard deviation of N(0, 1). Left or top, the naive variance-exploding chain: the red mean coefficient is flat at 1, so the mean does not change, while the blue noise standard deviation, the square root of t beta, crosses 1 at t equals 50 and keeps growing to 2. Right or bottom, the DDPM variance-preserving chain: the red mean coefficient, square root of alpha bar t, decays from 1 to about 0.13, and the blue noise standard deviation, square root of 1 minus alpha bar t, rises towards 1 and levels off there.Naive: variance exploding00.511.52050100150200tDDPM: variance preserving00.511.52050100150200tnoise std √(tβ)variance increasesindefinitelymean doesn't changetarget std 1mean shrinks: √α̅ₜ → 0noise std √(1 − α̅ₜ) → 1Mean coefficient and noise standard deviation of q(xt | x0) over tTwo plots over t from 0 to 200 with beta equal to 0.02. A dashed green line at height 1 marks the target standard deviation of N(0, 1). Left or top, the naive variance-exploding chain: the red mean coefficient is flat at 1, so the mean does not change, while the blue noise standard deviation, the square root of t beta, crosses 1 at t equals 50 and keeps growing to 2. Right or bottom, the DDPM variance-preserving chain: the red mean coefficient, square root of alpha bar t, decays from 1 to about 0.13, and the blue noise standard deviation, square root of 1 minus alpha bar t, rises towards 1 and levels off there.Naive: variance exploding00.511.52050100150200tDDPM: variance preserving00.511.52050100150200tnoise std √(tβ)variance increasesindefinitelymean doesn't changetarget std 1mean shrinks: √α̅ₜ → 0noise std √(1 − α̅ₜ) → 1
Coefficients of q(xₜ | x₀) for a constant β = 0.02: xₜ = (mean coefficient)·x₀ + (noise std)·ε. The naive chain keeps x₀ untouched while the noise std √(tβ) grows past 1 without limit (2.0 at t = 200). The DDPM chain shrinks x₀ by √α̅ₜ (0.13 at t = 200) while the noise std √(1 − α̅ₜ) rises towards 1 (0.991 at t = 200), the std of the target N(0, 1). The dashed green line marks the target std 1; in the left plot it is drawn over the flat mean line, which also sits at 1.

The same happens to the whole data distribution. Its marginal at step tt is q(xt)=∫q(xt∣x0) q(x0) dx0q(x_t) = \int q(x_t \mid x_0)\,q(x_0)\,dx_0. To see that it also tends to N(0,1)\mathcal N(0, 1), write xt=αˉt x0+1−αˉt εx_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1-\bar\alpha_t}\,\varepsilon with x0∼q(x0)x_0 \sim q(x_0) independent of ε\varepsilon. The first term is a fixed random variable times a factor that goes to 00, so it tends to 00 for any data distribution, and the second term tends to ε\varepsilon; hence xt→N(0,1)x_t \to \mathcal N(0, 1) in distribution. In one dimension, a two-humped density spreads out, its humps move towards 00 and merge (between t=200t = 200 and t=300t = 300 for the data in the figure below), and it ends as a single bell curve centred at 00. A finite batch of samples looks jagged along the way, but the density itself stays smooth: it is the data density convolved with a Gaussian. For a mixture of Gaussians the marginal stays a mixture and can be written down exactly:

q(x0)=∑kπk N(μk,σk2),q(xt)=∑kπk N ⁣(αˉt μk,  sk,t2),sk,t2=αˉtσk2+1−αˉt.\begin{aligned} q(x_0) &= \textstyle\sum_k \pi_k\,\mathcal N(\mu_k, \sigma_k^2), \\ q(x_t) &= \textstyle\sum_k \pi_k\,\mathcal N\!\big(\sqrt{\bar\alpha_t}\,\mu_k,\; s_{k,t}^2\big), \\ s_{k,t}^2 &= \bar\alpha_t\sigma_k^2 + 1 - \bar\alpha_t. \end{aligned}

Both components are pulled towards mean 00 and variance 11, so they merge into one standard normal.

Figure

The data distribution dissolves into N(0, 1)

Marginal density of xt at t = 0, 100, 300 and 1000Four small density plots joined by arrows. At t = 0 the red data density has two humps, at about minus 1.3 and plus 1.25. At t = 100, alpha bar 0.90, the humps are lower, wider and closer together. At t = 300, alpha bar 0.40, they have merged into one lopsided bump. At t = 1000, alpha bar about 0, the green density is the standard normal N(0, 1). Each panel also shows a jagged histogram of 600 noised samples.t = 0 (data)α̅ = 1q(x₀)t = 100α̅ = 0.90t = 300α̅ = 0.40t = 1000α̅ ≈ 4.0 × 10⁻⁵N(0, 1)Marginal density of xt at t = 0, 100, 300 and 1000Four small density plots joined by arrows. At t = 0 the red data density has two humps, at about minus 1.3 and plus 1.25. At t = 100, alpha bar 0.90, the humps are lower, wider and closer together. At t = 300, alpha bar 0.40, they have merged into one lopsided bump. At t = 1000, alpha bar about 0, the green density is the standard normal N(0, 1). Each panel also shows a jagged histogram of 600 noised samples.t = 0 (data)α̅ = 1q(x₀)t = 100α̅ = 0.90t = 300α̅ = 0.40t = 1000α̅ ≈ 4.0 × 10⁻⁵N(0, 1)
Every data point is noised by the same rule, so the whole 1-D data density q(x₀), a mixture of two Gaussians, turns into the marginal q(xₜ) = Σₖ πₖ N(√α̅ₜ μₖ, α̅ₜσₖ² + 1 − α̅ₜ). Curves are exact; bars are a histogram of 600 samples pushed through the same steps, which is why a finite batch looks jagged. The schedule is DDPM's linear β from 10⁻⁴ to 0.02 (T = 1000).

In practice: a β schedule#

In practice β\beta is not constant but varies with the step, β1,…,βT\beta_1, \dots, \beta_T; this is the schedule. The derivation above goes through unchanged with (1−β)(1-\beta) replaced by (1−βt)(1-\beta_t) at step tt:

q(xt∣xt−1)=N ⁣(1−βt xt−1,  βt),αˉt=∏i=1t(1−βi),q(xt∣x0)=N ⁣(αˉt x0,  1−αˉt).\begin{gathered} q(x_t \mid x_{t-1}) = \mathcal N\!\big(\sqrt{1-\beta_t}\,x_{t-1},\; \beta_t\big), \\ \bar\alpha_t = \textstyle\prod_{i=1}^{t} (1-\beta_i), \\ q(x_t \mid x_0) = \mathcal N\!\big(\sqrt{\bar\alpha_t}\,x_0,\; 1-\bar\alpha_t\big). \end{gathered}

The usual shorthand is αt=1−βt\alpha_t = 1-\beta_t, so αˉt=∏i≤tαi\bar\alpha_t = \prod_{i \le t}\alpha_i. The DDPM paper uses T=1000T = 1000 steps and a linear schedule from β1=10−4\beta_1 = 10^{-4} to βT=0.02\beta_T = 0.02 (Ho, Jain and Abbeel, 2020, §4). Later work found that a cosine-shaped schedule, which destroys information more evenly over time, works better at low resolution (Nichol and Dhariwal, 2021, §3.2). Small steps at the start keep the early xtx_t close to the image; larger steps later finish the job. With this schedule αˉt\bar\alpha_t is about 0.50.5 at t≈259t \approx 259 (it drops below 0.50.5 at t=260t = 260), falls below 0.010.01 at t=674t = 674 and ends at αˉ1000≈4.0×10−5\bar\alpha_{1000} \approx 4.0\times10^{-5}, so x1000x_{1000} is noise for all practical purposes.

Figure

A linear β schedule and the resulting α̅ₜ

Linear beta schedule and alpha bar over 1000 stepsTwo plots sharing the time axis t from 0 to 1000. The upper plot shows beta t as a straight amber line rising from 0.0001 to 0.02. The lower plot shows alpha bar t, the running product of 1 minus beta, as a falling curve that starts at 1, decreases slowly at first, crosses 0.5 at about t equals 259, falls below 0.01 at t equals 674, and is about 4 times 10 to the minus 5 at t equals 1000.00.010.02βtlinear, 10⁻⁴ → 0.0200.250.50.75102004006008001000tα̅t = ∏ (1 − βi)α̅ₜ ≈ 0.5 at t ≈ 259α̅ₜ < 0.01 from t = 674:x₀ is almost gone, xₜ ≈ εLinear beta schedule and alpha bar over 1000 stepsTwo plots sharing the time axis t from 0 to 1000. The upper plot shows beta t as a straight amber line rising from 0.0001 to 0.02. The lower plot shows alpha bar t, the running product of 1 minus beta, as a falling curve that starts at 1, decreases slowly at first, crosses 0.5 at about t equals 259, falls below 0.01 at t equals 674, and is about 4 times 10 to the minus 5 at t equals 1000.00.010.02βtlinear, 10⁻⁴ → 0.0200.250.50.75102505007501000tα̅t = ∏ (1 − βi)α̅ₜ ≈ 0.5 at t ≈ 259α̅ₜ < 0.01 from t = 674:x₀ is almost gone, xₜ ≈ ε
Top: βₜ grows linearly from 10⁻⁴ to 0.02. Bottom: α̅ₜ = ∏ (1 − βᵢ) falls slowly at first (small steps keep early images recognisable), is ≈ 0.5 at t ≈ 259, drops below 0.01 at t = 674 and ends at α̅₁₀₀₀ ≈ 4.0 × 10⁻⁵, so x₁₀₀₀ is essentially pure N(0, I) noise.

A schedule can also be read as a signal-to-noise ratio, SNRt=αˉt/(1−αˉt)\mathrm{SNR}_t = \bar\alpha_t / (1 - \bar\alpha_t): the squared coefficient of the image term divided by the variance of the noise, which is the ratio of the two variances for data of unit variance. For the linear schedule it falls from about 10410^4 at t=1t = 1 to 4×10−54\times10^{-5} at t=Tt = T. The fast samplers of the latent diffusion note work with its logarithm.

Linear, quadratic, sigmoid and cosine schedules#

The linear schedule is one choice among several (Weng, 2021, reviews them). Write ut=(t−1)/(T−1)∈[0,1]u_t = (t - 1)/(T - 1) \in [0, 1] for the position in the chain. With the same endpoints β1=10−4\beta_1 = 10^{-4} and βT=0.02\beta_T = 0.02, three common shapes are defined through βt\beta_t:

linear:βt=β1+(βT−β1) ut,quadratic:βt=(β1+(βT−β1) ut)2,sigmoid:βt=β1+(βT−β1) sigmoid⁡(12 ut−6).\begin{aligned} \text{linear:}\quad & \beta_t = \beta_1 + (\beta_T - \beta_1)\,u_t, \\ \text{quadratic:}\quad & \beta_t = \big(\sqrt{\beta_1} + (\sqrt{\beta_T} - \sqrt{\beta_1})\,u_t\big)^2, \\ \text{sigmoid:}\quad & \beta_t = \beta_1 + (\beta_T - \beta_1)\,\operatorname{sigmoid}(12\,u_t - 6). \end{aligned}

The quadratic schedule interpolates the noise amplitude βt\sqrt{\beta_t} linearly, so its steps stay small for longer. The sigmoid schedule is flat at both ends and makes its change in the middle; since sigmoid⁡(±6)\operatorname{sigmoid}(\pm 6) is not exactly 00 or 11, its βt\beta_t actually run from 1.5×10−41.5\times10^{-4} to 0.019950.01995. The cosine schedule (Nichol and Dhariwal, 2021, §3.2, Eq. 17) prescribes αˉt\bar\alpha_t instead and derives the steps from it:

αˉt=f(t)f(0),f(t)=cos⁡2 ⁣(t/T+s1+s⋅π2),βt=1−αˉtαˉt−1,\begin{gathered} \bar\alpha_t = \frac{f(t)}{f(0)}, \qquad f(t) = \cos^2\!\Big(\frac{t/T + s}{1 + s}\cdot\frac{\pi}{2}\Big), \\ \beta_t = 1 - \frac{\bar\alpha_t}{\bar\alpha_{t-1}} , \end{gathered}

with the offset s=0.008s = 0.008, chosen so that the noise amplitude of the first step stays just below the width 1/127.51/127.5 of one pixel level, and with βt\beta_t clipped at 0.9990.999. Without the clip, f(T)=0f(T) = 0 would give βT=1\beta_T = 1; with it, αˉ1000≈2.4×10−9\bar\alpha_{1000} \approx 2.4 \times 10^{-9}.

Figure

Four noise schedules: how α̅ₜ falls

Alpha bar for linear, quadratic, sigmoid and cosine schedulesFour falling curves of alpha bar t over steps 0 to 1000, all starting at 1. The linear one falls first and crosses 0.5 at t equals 260; the quadratic crosses 0.5 at 419, the sigmoid at 440, and the cosine at 497, staying clearly above zero the longest.00.250.50.75102004006008001000tα̅tlinearquadraticsigmoidcosineAlpha bar for linear, quadratic, sigmoid and cosine schedulesFour falling curves of alpha bar t over steps 0 to 1000, all starting at 1. The linear one falls first and crosses 0.5 at t equals 260; the quadratic crosses 0.5 at 419, the sigmoid at 440, and the cosine at 497, staying clearly above zero the longest.00.250.50.75102505007501000tα̅tlinearquadraticsigmoidcosine
α̅ₜ for four schedules with T = 1000: linear, quadratic and sigmoid with β from 10⁻⁴ to 0.02, and cosine with s = 0.008. Dots mark where α̅ₜ first drops below 0.5: t = 260, 419, 440 and 497. The linear schedule leaves less than 1% of the signal variance from t = 674 on; the cosine one falls almost linearly through the middle of the chain and slowly near its ends.

With T=1000T = 1000:

scheduleαˉt<0.5\bar\alpha_t < 0.5 fromαˉt<0.01\bar\alpha_t < 0.01 fromαˉ1000\bar\alpha_{1000}
lineart=260t = 260t=674t = 6744.0×10−54.0 \times 10^{-5}
quadratict=419t = 419t=851t = 8517.3×10−47.3 \times 10^{-4}
sigmoidt=440t = 440t=721t = 7214.0×10−54.0 \times 10^{-5}
cosinet=497t = 497t=936t = 9362.4×10−92.4 \times 10^{-9}

The linear schedule destroys the image fastest: half of the signal variance is gone by t=260t = 260, and from t=674t = 674 on less than 1%1\% is left, so the last third of the chain works on almost pure noise. Nichol and Dhariwal found this wasteful at 32×3232 \times 32 and 64×6464 \times 64: a model trained with the linear schedule barely loses FID when the first 20%20\% of the reverse process, its noisiest end, is skipped. Their cosine schedule was designed to make αˉt\bar\alpha_t fall almost linearly in the middle and change little near both ends; it crosses 0.50.5 close to T/2T/2. On ImageNet 64×6464 \times 64 (T=4000T = 4000, LsimpleL_{\text{simple}}, 200K iterations) it improved FID from 31.331.3 to 27.027.0 and the likelihood from 3.773.77 to 3.683.68 bits per dimension (their Table 1). The quadratic schedule shows the opposite risk: it ends at αˉ1000≈7.3×10−4\bar\alpha_{1000} \approx 7.3 \times 10^{-4}, so a fraction αˉT≈0.027\sqrt{\bar\alpha_T} \approx 0.027 of the image survives in xTx_T, and q(xT∣x0)q(x_T \mid x_0) sits further from the N(0,I)\mathcal N(0, I) where sampling starts than for the other three.

Notebook#

The diffusion notebook of the HSE-LAMBDA Deep Generative Models repository (pinned commit; cell numbers count every cell from 1) is based on the ACIDS-IRCAM diffusion tutorial. It has no saved outputs, so it documents procedures rather than results.

The notebook uses toy settings: a 2-D Swiss roll and T=100T = 100 steps. Its first demo runs the step-by-step chain with a constant β=0.0005\beta = 0.0005, for which αˉ100≈0.951\bar\alpha_{100} \approx 0.951. The rest of the notebook uses a sigmoid-shaped schedule with start 10−510^{-5} and end 10−210^{-2}, for which αˉ100≈0.605\bar\alpha_{100} \approx 0.605; since the sigmoid of ±6\pm 6 is not exactly 00 or 11, the actual βt\beta_t run from about 3.5×10−53.5\times10^{-5} to 1.0×10−21.0\times10^{-2}. It samples xtx_t directly with the closed form (q_sample, alphas_bar_sqrt, one_minus_alphas_bar_sqrt). Neither toy schedule gets close to αˉ=0\bar\alpha = 0: the mean coefficient αˉ100\sqrt{\bar\alpha_{100}} is still about 0.980.98 and 0.780.78, so x100x_{100} carries much of the data signal. Real models need many more steps or larger β\beta.

  • Cells 4–6 sample the 2-D Swiss roll used throughout.
  • Cells 8–10: the markdown of cell 8 introduces the general Markov kernel Tπ(xt∣xt−1;βt)T_\pi(x_t \mid x_{t-1}; \beta_t) of Sohl-Dickstein et al. and then picks the Gaussian one. forward_process implements xt=1−βt xt−1+βt εx_t = \sqrt{1-\beta_t}\,x_{t-1} + \sqrt{\beta_t}\,\varepsilon, with β\beta as a variance and β\sqrt\beta as the noise amplitude, and runs it for 100 steps with constant β=0.0005\beta = 0.0005. The returned list starts with the clean data at index 0.
  • Cell 12: make_beta_schedule with the linear, quadratic and sigmoid schedules written above (defaults T=1000T = 1000, start 10−510^{-5}, end 10−210^{-2}; the notebook calls it with T=100T = 100). With these endpoints and T=100T = 100, αˉ100\bar\alpha_{100} is 0.6050.605 for the linear and the sigmoid schedule and 0.7070.707 for the quadratic one. The cosine schedule is not implemented.
  • Cells 13–16: the closed-form sampler q_sample with the sigmoid schedule, using alphas_bar_sqrt and one_minus_alphas_bar_sqrt. The helper extract(a, t, x) picks the coefficient a[t] for each example’s timestep and reshapes it so that it broadcasts over the data dimensions. Coefficient index ii in the code corresponds to t=i+1t = i + 1 in the formulas, so the plot label x0x_0 already refers to the first noised marginal. These are direct draws from q(xt∣x0)q(x_t \mid x_0) for each tt, not one correlated trajectory.

The reverse samplers (cells 24 and 47) start from N(0,I)\mathcal N(0, I), but with the sigmoid schedule q(x100∣x0)=N(0.78 x0,  0.40 I)q(x_{100} \mid x_0) = \mathcal N(0.78\,x_0,\; 0.40\,I), so the starting distribution does not match the end of the forward chain. The reverse process, the training objective and the sampler are in cells 17–48; they are described in the next note.

Next#

We now have a diffusion process that turns any image into noise that is indistinguishable from N(0,I)\mathcal N(0, I) in practice; for DDPM’s schedule, αˉT≈4×10−5\bar\alpha_T \approx 4\times10^{-5}. To generate, we have to invert it, and that is done with a deep neural network. How to set up and train that network is the topic of DDPM: reverse process and training objective.

References#