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.
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.x0 is a data point (an image) and xt its noised version after t steps, t=1,…,T. q denotes the fixed forward (noising) process: q(x0) is the distribution of the data and q(xt∣xt−1) one noising step. pθ(xt−1∣xt) is the learned reverse step, with network parameters θ. ε∼N(0,1) is standard Gaussian noise drawn fresh at every step, and the second argument of N(μ,σ2) is the variance. We work in one dimension; for images every pixel is noised independently and 1 becomes the identity matrix I, so the target is N(0,I).
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).
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), because it is where the forward process q starts.
The diffusion idea is to connect q(x0) to a distribution we can sample from. Take a real image x0, the original photo, and add a little noise to get x1, then a little more to get x2, and so on until xT is pure noise. Each forward step is fixed and needs no learning. The model, the learned reverse step pθ(xt−1∣xt), goes the other way: from xt it produces xt−1, one step back towards the image. To generate, we sample pure noise xT and apply the model T times.
The forward chain adds noise; the model walks 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 ε.
where β is the noise variance. Note the square root: cε has variance c2, so noise with variance β is βε. The next step does the same to x1: q(x2∣x1)=N(x1,β).
Now we can shorten the chain. Two steps add two independent noises, and the variances of independent Gaussians add up:
where ε=(ε1+ε2)/2 is again a standard normal. Whenever several noises are merged below, ε denotes the merged standard normal in this sense, so such equalities hold in distribution.
Continuing in the same way, after t steps
xt=x0+tβε,q(xt∣x0)=N(x0,tβ).
This is a useful shortcut: we can jump from x0 to any xt in one draw. But look at the two parameters:
the mean does not change: it stays x0 forever;
the variance increases indefinitely: tβ→∞.
So the chain never reaches 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 and start sampling from N(0,σmax2) (Song et al., 2021, §2.1).
whatever the starting image. This needs a new way to go from step t−1 to step t, and in particular the step has to change the mean each time, pulling it towards 0. In general, Sohl-Dickstein et al. allow any Markov kernel Tπ(xt∣xt−1;βt) that leaves a simple target distribution π unchanged, π(y)=∫Tπ(y∣y′;β)π(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=axt−1+βε. 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−β:
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−β? The fresh noise is independent of xt−1, so the variance obeys Var(xt)=a2Var(xt−1)+β. This recursion settles at 1, the variance of the target, only if a2+β=1. So a=1−β is the only positive scale that keeps a unit variance at 1, and it also pulls any other variance towards 1 (callout below). With this a the jump from x0 to any xt takes an especially simple closed form, whose two squared coefficients sum to 1 (Ho, Jain and Abbeel, 2020, Eq. 4):
If β∈(0,1), then αˉt=(1−β)t→0 as t→∞. Then the image term αˉtx0→0, while the noise coefficient 1−αˉt→1, so the noise term tends to plain ε with variance 1:
q(xt∣x0)t→∞N(0,1).
For example, with a constant β=0.02:
t
αˉt=0.98t
mean coefficient αˉt
noise std 1−αˉt
naive noise std tβ
1
0.980
0.990
0.141
0.141
10
0.817
0.904
0.428
0.447
50
0.364
0.603
0.797
1.000
100
0.133
0.364
0.931
1.414
200
0.0176
0.133
0.991
2.000
For small t the two chains almost agree. Then the naive one passes the target spread and keeps growing, while DDPM’s approaches 1 from below. At a finite T the image term αˉTx0 is small only relative to the scale of x0, which is one reason images are scaled to [−1,1] before diffusion (next note).
Figure
Variance exploding versus variance preserving
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 t is q(xt)=∫q(xt∣x0)q(x0)dx0. To see that it also tends to N(0,1), write xt=αˉtx0+1−αˉtε with x0∼q(x0) independent of ε. The first term is a fixed random variable times a factor that goes to 0, so it tends to 0 for any data distribution, and the second term tends to ε; hence xt→N(0,1) in distribution. In one dimension, a two-humped density spreads out, its humps move towards 0 and merge (between t=200 and t=300 for the data in the figure below), and it ends as a single bell curve centred at 0. 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:
Both components are pulled towards mean 0 and variance 1, so they merge into one standard normal.
Figure
The data distribution dissolves into 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 β is not constant but varies with the step, β1,…,βT; this is the schedule. The derivation above goes through unchanged with (1−β) replaced by (1−βt) at step t:
The usual shorthand is αt=1−βt, so αˉt=∏i≤tαi. The DDPM paper uses T=1000 steps and a linear schedule from β1=10−4 to β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 xt close to the image; larger steps later finish the job. With this schedule αˉt is about 0.5 at t≈259 (it drops below 0.5 at t=260), falls below 0.01 at t=674 and ends at αˉ1000≈4.0×10−5, so x1000 is noise for all practical purposes.
Figure
A linear β schedule and the resulting α̅ₜ
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): 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 104 at t=1 to 4×10−5 at t=T. The fast samplers of the latent diffusion note work with its logarithm.
The linear schedule is one choice among several (Weng, 2021, reviews them). Write ut=(t−1)/(T−1)∈[0,1] for the position in the chain. With the same endpoints β1=10−4 and βT=0.02, three common shapes are defined through βt:
The quadratic schedule interpolates the noise amplitude β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) is not exactly 0 or 1, its βt actually run from 1.5×10−4 to 0.01995. The cosine schedule (Nichol and Dhariwal, 2021, §3.2, Eq. 17) prescribes αˉt instead and derives the steps from it:
with the offset s=0.008, chosen so that the noise amplitude of the first step stays just below the width 1/127.5 of one pixel level, and with βt clipped at 0.999. Without the clip, f(T)=0 would give βT=1; with it, αˉ1000≈2.4×10−9.
Figure
Four noise schedules: how α̅ₜ falls
α̅ₜ 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=1000:
schedule
αˉt<0.5 from
αˉt<0.01 from
αˉ1000
linear
t=260
t=674
4.0×10−5
quadratic
t=419
t=851
7.3×10−4
sigmoid
t=440
t=721
4.0×10−5
cosine
t=497
t=936
2.4×10−9
The linear schedule destroys the image fastest: half of the signal variance is gone by t=260, and from t=674 on less than 1% is left, so the last third of the chain works on almost pure noise. Nichol and Dhariwal found this wasteful at 32×32 and 64×64: a model trained with the linear schedule barely loses FID when the first 20% of the reverse process, its noisiest end, is skipped. Their cosine schedule was designed to make αˉt fall almost linearly in the middle and change little near both ends; it crosses 0.5 close to T/2. On ImageNet 64×64 (T=4000, Lsimple, 200K iterations) it improved FID from 31.3 to 27.0 and the likelihood from 3.77 to 3.68 bits per dimension (their Table 1). The quadratic schedule shows the opposite risk: it ends at αˉ1000≈7.3×10−4, so a fraction αˉT≈0.027 of the image survives in xT, and q(xT∣x0) sits further from the N(0,I) where sampling starts than for the other three.
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=100 steps. Its first demo runs the step-by-step chain with a constant β=0.0005, for which αˉ100≈0.951. The rest of the notebook uses a sigmoid-shaped schedule with start 10−5 and end 10−2, for which αˉ100≈0.605; since the sigmoid of ±6 is not exactly 0 or 1, the actual βt run from about 3.5×10−5 to 1.0×10−2. It samples xt directly with the closed form (q_sample, alphas_bar_sqrt, one_minus_alphas_bar_sqrt). Neither toy schedule gets close to αˉ=0: the mean coefficient αˉ100 is still about 0.98 and 0.78, so x100 carries much of the data signal. Real models need many more steps or larger β.
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) of Sohl-Dickstein et al. and then picks the Gaussian one. forward_process implements xt=1−βtxt−1+βtε, with β as a variance and β as the noise amplitude, and runs it for 100 steps with constant β=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=1000, start 10−5, end 10−2; the notebook calls it with T=100). With these endpoints and T=100, αˉ100 is 0.605 for the linear and the sigmoid schedule and 0.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 i in the code corresponds to t=i+1 in the formulas, so the plot label x0 already refers to the first noised marginal. These are direct draws from q(xt∣x0) for each t, not one correlated trajectory.
The reverse samplers (cells 24 and 47) start from N(0,I), but with the sigmoid schedule q(x100∣x0)=N(0.78x0,0.40I), 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.
We now have a diffusion process that turns any image into noise that is indistinguishable from N(0,I) in practice; for DDPM’s schedule, αˉT≈4×10−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.