Reverse SDEs, the probability-flow ODE and samplers
Before this lesson: lesson 06 (the score, Langevin dynamics, denoising score matching), lesson 07 (the forward process, ancestral sampling, vs ) and lesson 08 (conversions between , and the score; Tweedie's formula; the EDM form ). For the order of a numerical method, see time stepping in the ML for science track. The lesson gives the minimum about SDEs that you need; the ML for science track treats Itô calculus and the Fokker–Planck equation in depth. Time: about 115 minutes, plus the notebook.
Why this matters #
Training fixes the network. The sampler decides how often you call it, and part of the sample quality. The original DDPM used 1,000 network evaluations per sample. With the same trained network and no retraining, DDIM, Heun or DPM-Solver reach similar quality with 10–50 evaluations. Every image, video and audio diffusion library (k-diffusion, diffusers) offers these samplers by name.
In science the cost multiplies. GenCast, a diffusion model for 15-day global weather ensembles, calls its denoiser 39 times per 12-hour forecast step (a second-order solver on 20 noise levels), for 30 steps and many ensemble members. For a diffusion or flow emulator of physical fields, the sampler is the main control of inference cost. "How do you make sampling 20 times faster without retraining?" is a standard interview question. This lesson is the answer, and it is also the basis of flow matching (lesson 10), guidance (lesson 11) and few-step generation (lesson 12).
1. Predict first #
2. The picture #
Sampling solves a differential equation backward in noise level #
At a noisy point with noise level , the trained network gives the denoiser (lesson 08), and so the score by Tweedie's formula. A sampler uses these values to move a point from high noise to low noise. It makes three choices:
- the solver: how to move from one noise level to the next with the help of (Euler, Heun, ...);
- the noise: deterministic steps (an ODE) or fresh random noise in every step (an SDE);
- the step schedule: at which noise levels to call the network.
The cost of a sampler is its number of network function evaluations (NFE). The network is by far the most expensive part, so we always compare samplers at equal NFE, not at equal numbers of steps.
Same distributions, different paths #
The figure below shows the central fact of this lesson in one dimension. The data are two narrow Gaussians at and . The blue background is the density of the noised data at each time (time runs from data at to noise at ). Both samplers start from the same noise points at and run backward to . The score is computed exactly, so no network is involved.
Move the time slider and compare the two histograms with the dashed exact density . Both the ODE particles (magenta) and the SDE particles (orange) follow at every time, and their standard deviations agree with the exact value in the panel. But single paths differ: each magenta path is fixed by its start point, while the orange paths are random. Two orange paths from nearby start points can end at different modes. Press New noise to draw new start points. The score is exact (computed from the known mixture), not learned.
So the two samplers agree on everything a sampler must get right (the distribution at each time) and disagree on the paths. Section 3 proves this with the Fokker–Planck equation.
Three samplers in one sentence each #
- Ancestral sampling (DDPM): take one small step down with the posterior mean, then add posterior noise. This is a discretization of the reverse SDE.
- DDIM: predict , then put it back at the next, lower noise level, mixing the predicted noise and some fresh noise. With no fresh noise the step is deterministic.
- ODE solvers (Euler, Heun, DPM-Solver): integrate the probability-flow ODE with a standard numerical method. DDIM without fresh noise is one of them: Euler's method.
The next figure runs these samplers on the 2D "8 Gaussians" data with the exact score. All differences you see come from the sampler, because the score has no error.
Choose a sampler, an NFE budget and a step schedule. The blue dots are data, the orange dots are 500 samples, the magenta lines are a few sampling paths (drawn in VP coordinates, which stay bounded). Start with Euler at 10 NFE on the Karras schedule: about 85% of the samples land on a mode. Now switch the schedule to uniform: fewer than 15% of the samples reach a mode even at 50 NFE. Try the reverse SDE at 10 NFE (about 60%), then at 50 NFE. Try Heun: below about 15 NFE its second slope is taken where the denoiser changes fast, and it fails; from 20 NFE it works. The score is exact, not learned.
The reverse SDE and the probability-flow ODE start from the same noise point . Which statement is true?
Both processes have the marginals at every time (Theorems 1 and 2 below), so both end with the data distribution. But the SDE adds random noise in every step, so one SDE path from is random, while the ODE path is a fixed function of . Equal distributions do not mean equal paths.
3. Definitions and main results #
The forward process as an SDE #
Lesson 07 adds noise in discrete steps: . Let the number of steps grow and each step shrink. Write for a smooth function and a small time step . Then , so
A Gaussian increment with variance is an increment of Brownian motion : . In the limit we get a stochastic differential equation (SDE):
The drift is the deterministic part of the motion; the diffusion coefficient scales the random part. This is the variance-preserving (VP) SDE (Song et al. 2021). Its marginals are the ones you know: with and .
The variance-exploding (VE) SDE has no drift, only noise: , which is the SDE
(Variances of independent increments add, so the noise added between and must have variance .) EDM uses the VE SDE with , so : the time is the noise level.
Euler–Maruyama is the simplest way to simulate an SDE. On a grid with step :
It is Euler's method for the drift plus a Gaussian kick with the variance that the noise adds in time . Exercise 1 of the notebook checks that it reproduces the closed-form marginals of the VP SDE.
Theorem 1 (reverse-time SDE, Anderson 1982) #
Intuition first. Run the forward SDE backward. The noise must now remove the spread it added, which no random kick can do on average. The fix is a drift toward high density: the score points from a point toward where the density of is larger. A drift of size exactly undoes the spreading that noise of strength causes, while a fresh noise term keeps the spread right.
Theorem. Let solve the forward SDE on with and marginals (smooth and positive). Then the process that runs from to ,
has marginal at every time. Here (time runs backward) and is a Brownian motion in reversed time.
In practice, one Euler–Maruyama step from down to (with ) is
The score enters with a plus sign: pushes the point toward high density. For the VP SDE the step is .
Proof (with the Fokker–Planck equation)
We prove that the marginals agree, which is all a sampler needs. (Anderson proved more: the whole reversed path has the law of the forward path run backward.)
- The Fokker–Planck equation. The density of the solution of satisfies
The first term moves mass along the drift; the second spreads it like heat. (A derivation is in the ML for science track; here we use it as a known fact.) 2. Reverse the clock. Let and . Then . 3. A candidate. An SDE in the clock has the Fokker–Planck equation . 4. Match the two. We need , that is . 5. The key identity. , because . So the choice gives . ✓ 6. Uniqueness. Both processes start from and their densities solve the same equation, so (under the usual uniqueness of solutions) they are equal at every . 7. Written in the original clock (), the drift becomes multiplying a negative : the formula of the theorem.
For the VE SDE (), one Euler–Maruyama step of the reverse SDE goes from noise level down to . Which drift term does it add to ?
The reverse SDE is with . So the drift adds . The minus sign in the formula and the negative time step cancel. The factor belongs to the probability-flow ODE, and "no drift" forgets that the reverse process needs the score even when the forward one has no drift.
Theorem 2 (the probability-flow ODE, Song et al. 2021) #
Theorem. The ordinary differential equation
has the same marginals as the forward SDE: if and you solve it backward, then for every (and the same holds forward from ).
Proof.
- Write the diffusion term of the Fokker–Planck equation as a flux, with the identity of step 5 above: .
- Then the Fokker–Planck equation reads .
- This is a continuity equation with the velocity , and no diffusion term. A continuity equation is exactly the equation for the density of points that move by the ODE (lesson 04, continuous flows).
- Same equation and same initial density, so the same marginals.
The ODE moves mass like a fluid: it never adds randomness, it only pushes points along a velocity field. The factor is not optional: without it the ODE removes the spread twice as fast as the noise added it. (The notebook shows this for Gaussian data: from , the right ODE ends with standard deviation 1, the ODE without the with standard deviation 0.0125.)
A whole family of samplers. The same flux trick shows that for every the backward process
has the marginals . With you get the reverse SDE; with the probability-flow ODE. (Check: its Fokker–Planck equation in reversed time has the drift term and the diffusion term , which add up to , as in step 2 of the proof of Theorem 1.) The amount of noise is a free design choice. One way to see the extra noise: it is Langevin dynamics (lesson 06) at a fixed noise level, added on top of the ODE. Langevin dynamics keeps unchanged, so it can be added in any amount.
The probability-flow ODE in EDM coordinates. Take the VE SDE with : and . The ODE is . Tweedie's formula for is , so and
The slope points away from the denoiser output. Read backward (decreasing ), the point moves toward . This form is the one used by EDM and by most modern samplers.
Ancestral sampling is a discretization of the reverse SDE #
The DDPM step of lesson 07 is . The score is , so the step is . With :
With this is the Euler–Maruyama step of the reverse VP SDE above. So DDPM sampling is a first-order discretization of Theorem 1. It is accurate only when every is small, which is why DDPM needs many steps.
DDIM: a family of samplers for one trained model #
Song, Meng and Ermon (2021) asked which samplers can use a network trained with the DDPM loss. The loss only sees pairs at single times, through . Any process with these same marginals has the same optimal network . They found a family of such processes with one free noise scale per step. Sampling from it gives the DDIM update (Song et al. 2021, eq. 12). From level to any lower level (written ):
with and, with a parameter (eq. 16 of the paper),
(Song et al. call ""; we keep for the noise scale.)
- : no fresh noise. The step is deterministic, and so is the whole sample once is fixed.
- : equals the DDPM posterior variance of this step, and the mean equals the DDPM posterior mean. So is ancestral DDPM sampling with variance . (Worked example (a) checks this with numbers.)
- Any subsequence of levels. Nothing in the derivation needs consecutive steps, so the same formula jumps between any two levels, for example 50 levels out of 1,000.
Why every value of η keeps the DDPM marginals (the non-Markovian forward process)
Song et al. define a forward process that runs down in and may look at :
started from .
Claim. for every and every choice of .
- Assume it holds at level . Write ; then .
- A draw from the kernel is , with independent of .
- Given , this is a sum of independent Gaussians: mean , variance .
- The claim holds at by definition. Induction downward gives every .
Consequences. The process is non-Markovian ( depends on , not only on ), but the training loss never sees this: it uses only . Song et al. (Theorem 1) also show that the ELBO of every member is a weighted plus a constant. Sampling replaces the unknown by and by , which gives the update above.
is DDPM. Let be the of the step. Then , the posterior variance of lesson 07. The coefficient of in the mean becomes , and its square is , using . So the coefficient is : exactly the DDPM coefficient of in .
Theorem 3 (DDIM with is Euler's method for the probability-flow ODE) #
In the EDM coordinates and , the DDIM step is
one Euler step of the probability-flow ODE , with the network's in place of .
Proof.
- Set in the DDIM update and divide by : .
- Rearrange the definition of : . Divide by : and .
- Put this into step 1: . Add and subtract : .
- In these coordinates is the VE form, whose probability-flow ODE is (the boxed equation). Step 3 is one Euler step of it from to , with the slope evaluated at the start.
Move , and the two noise levels. The yellow point is the current state in the coordinates . The violet dashed line joins it to (the blue point on the axis ). The Euler step moves along this line to the next level (magenta ring); the DDIM step (orange dot) lands inside the ring, and the panel shows a difference of up to rounding. Now raise : the step becomes random, and its mean leaves the line. Switch to exact, Gaussian data to see the true ODE path (thin magenta curve) and the Euler error.
What Theorem 3 tells you.
- DDIM is a first-order method: its global error is in the step size . Second-order methods on the same ODE need fewer NFE for the same error.
- In these coordinates the slope points at the denoiser output: one Euler step to returns . A step is exact when does not change along it. If the data are a single point , then , every path is a straight line, and one DDIM step is exact.
- The coordinates matter. Euler steps in on the VP form of the ODE give a different, worse sampler. In the paths are nearly straight at high noise, which is why DDIM works with few steps. Lesson 10 builds on the same idea: flow matching chooses a path that is as straight as possible.
The Gaussian toy: exact paths #
Take 1D data in EDM coordinates. The denoiser is linear, (lesson 08), so the ODE is
(Separate the variables: , so .) Each start value gives exactly one data value: the ODE is a deterministic, invertible map from noise to data. For , is almost proportional to : a straight line that one large step follows almost exactly. Near the path bends. Easy at high noise, hard at low noise: this is the reason for the step schedules below.
ODE or SDE? #
- ODE (; Euler, Heun, DPM-Solver). Deterministic and invertible: DDIM inversion maps an image to its noise (used for editing and interpolation). It gives exact likelihoods with the instantaneous change of variables of lesson 04. It is usually the best choice at low NFE. But errors (network error plus discretization error) are carried along, never corrected.
- SDE (reverse SDE, ancestral, DDIM with ). The fresh noise and the extra score drift act like Langevin steps at a fixed noise level. They pull samples back toward and so partly correct earlier errors. The price: every step must remove the noise it adds, so it needs more steps.
- Numbers (Song et al. 2021, Table 1, CIFAR-10 FID, lower is better): with 10 steps, gives 13.36 and gives 41.07; with 100 steps, 4.16 and 5.78; with 1,000 steps, 4.04 and 4.73. Ancestral sampling with the larger variance is the best at 1,000 steps (3.17) and useless at 10 steps (367).
- EDM's stochastic sampler (Karras et al. 2022, Algorithm 2) adds a controlled amount of noise ("churn") in a band of noise levels, then takes a deterministic Heun step. Too much churn loses detail.
In the 8-Gaussians figure the score is exact, so there is no network error for the noise to correct. There, at 10 NFE on the Karras schedule, Euler puts about 84% of the samples on a mode and the reverse SDE about 62%; at 50 NFE both are above 95%.
Solvers: accuracy per NFE #
From here on we work in EDM coordinates and write and (no tildes). The ODE is with the slope , solved on a decreasing grid with step .
- Euler (= DDIM): . One NFE per step. Global error : halving all steps halves the error.
- Heun (EDM, Algorithm 1): an Euler predictor , then the trapezoidal corrector
Two NFE per step. Global error : halving the steps divides the error by about 4.
- The last step. The slope is undefined at , so the last step into is a plain Euler step (it returns ). So Heun steps that end at 0 cost NFE: 35 for EDM's 18 levels, which reach FID 1.79 on class-conditional CIFAR-10.
The order of a method is the power in "global error ". On log–log axes, error against NFE is a line with slope .
Compare the two lines on log–log axes. Each point integrates the exact Gaussian-toy ODE from to with Euler (orange) or Heun (violet) and plots the relative error against the NFE used. At large NFE the slopes approach and (dashed reference lines). The yellow rings mark about 30 NFE: there the two errors are still close. At about 250 NFE Heun is more than ten times more accurate: halving its steps divides its error by 4, not by 2. Switch to the uniform grid: both methods need hundreds of NFE before their order shows, because almost all steps are spent at high noise.
A Heun sampler uses the noise levels . How many network evaluations does one sample cost?
There are 10 steps. Each Heun step costs 2 NFE, except the last step into , which must be a plain Euler step because the slope is undefined at . So . "20" forgets the last-step rule; "10" is the count for Euler.
DPM-Solver: solve the linear part exactly
Lu et al. (2022) change the variable to . Then . The term is linear and can be integrated exactly (variation of constants):
Only is approximated, by a polynomial in . A constant gives
which is the DDIM step again (DPM-Solver-1 = DDIM, Lu et al., section 4.1). Check: the Euler step is the same expression. DPM-Solver-2 and -3 use 2 and 3 NFE per step for orders 2 and 3. DPM-Solver++(2M) makes linear in from the current and the previous denoiser outputs: order 2 for 1 NFE per step. Lu et al. write the time as (half the log-SNR) and report good samples with 10–20 NFE.
Step schedules #
Karras et al. (2022, eq. 5) choose levels between and with a parameter :
- : uniform in .
- : uniform in (a geometric grid). Proof: with and , the bracket is , and its -th power tends to .
- EDM default: , , , for data scaled to . EDM found that nearly equalizes the error per step, but between 5 and 10 gives better images: errors near have a large effect on what you see.
Move and . The top panel shows the levels for , for your (orange) and for , on a log axis; the yellow line is . The bottom panel shows the local error that one Euler step makes on the Gaussian toy, at the level where the step starts. With one long last step from to almost 0 makes nearly all of the error. Larger moves levels to low noise, where the path bends, and the errors become more even. Press EDM for the default 18 levels with : 7 of them lie below .
Why the steps crowd at low noise.
- The local error of a step of size is about for Euler (and for Heun): it is large where the path bends.
- In the Gaussian toy, gives . It is largest at and decays like . For the curvature at is times the curvature at . For the same Euler error, a step at may be times longer.
- Real data have structure at many scales. The path bends whenever passes a length scale of the data: the distance between modes, the width of a mode, fine detail. At high noise the denoiser output stays near the data mean, so the path is nearly straight.
An adaptive ODE solver finds this spacing by itself (section 5): with no schedule given, it chooses an almost geometric grid.
Where the schedule starts. The first level must be the highest level the model was trained at (, or ). With and 10 steps, "leading" spacing uses and never visits ; "trailing" spacing uses (Lin et al. 2024). Use trailing spacing; see lesson 08 for the related zero-terminal-SNR problem.
Why does the EDM schedule () put 7 of its 18 noise levels below , about 1% of the range from 0.002 to 80?
The local error of a step grows with the curvature of the path. For the Gaussian toy the curvature at is about 8,000 times that at ; real data bend each time passes a length scale of the data. At high noise the denoiser stays near the data mean and the path is almost straight, so long steps are accurate there.
You sample with DDIM, , on the full grid of 1,000 DDPM levels. How does this compare with ancestral DDPM sampling?
With , , and the mean of the DDIM step equals the DDPM posterior mean (worked example (a) checks both with numbers). DDPM with the larger variance is not a member of the family on the same marginals.
Answers to section 1. (1) No retraining. Every keeps the DDPM marginals , and the loss sees only these, so the same network is optimal. With the output is a deterministic function of : an ODE solve (Theorem 3). (2) Not the same point: the SDE path is random. But the same distribution: both have the marginals at every time (Theorems 1 and 2). (3) Not uniformly. Most levels go to low noise, where the paths bend. With , 7 of the 18 levels lie below ; a uniform grid puts only its last level there.
4. Worked example #
(a) One DDIM step by hand. 1D, , , , network output . So , , .
- .
- : .
- Check as Euler. , , . The slope is . Euler: . Back to VP: ✓.
- . The step has . , so . The DDPM posterior variance is ✓.
- The mean: . The DDPM posterior mean (lesson 07) is ✓.
(b) Euler vs Heun for one step, with the exact answer. Data (). Go from , to , so . The slope is .
- Exact: .
- Euler (1 NFE): , so . Error .
- Heun (2 NFE): , so . Error .
(c) Karras grids for (, ). For : and ; the middle level is . Then :
| 1 (uniform) | 80 | 60.0005 | 40.001 | 20.0015 | 0.002 |
| 3 | 80 | 34.75 | 10.90 | 1.609 | 0.002 |
| 7 (EDM) | 80 | 17.53 | 2.515 | 0.1698 | 0.002 |
| (geometric) | 80 | 5.657 | 0.4 | 0.02828 | 0.002 |
The geometric middle level is , the geometric mean of the end points.
(d) Schedule and solver together. Data with the exact denoiser; 500 paths from to on 18 levels (17 steps, no step to 0). The table gives the largest error against an accurate reference solve:
| grid | Euler (17 NFE) | Heun (34 NFE) |
|---|---|---|
| 0.86 | 8.5 | |
| 0.46 | 0.14 | |
| 0.26 | 0.048 | |
| geometric | 0.25 | 0.039 |
- The schedule comes first. On the uniform grid the last step, from to , is far too long, and Heun is even worse than Euler. At the denoiser output lies between the modes, so the Euler predictor stops short of the nearest mode; the slope at the predicted point then points the other way, and the average of the two slopes ends far from the data.
- On a good grid Heun wins at equal cost. With , Heun on 10 levels (18 NFE) has error 0.18, against 0.26 for Euler on 18 levels (17 NFE); Heun on 18 levels (34 NFE) has 0.048, against 0.11 for Euler on 40 levels (39 NFE).
5. In code #
NumPy checks the worked examples (a)–(c). The notebook has these cells and the exercises.
import numpy as np
np.set_printoptions(suppress=True)
# (a) One DDIM step (VP), and the same step as Euler in the EDM coordinates
ab_t, ab_p, xt, eps_hat = 0.5, 0.8, 1.0, 0.6 # alpha_bar at t and t-1, x_t, network output
a_t, s_t, a_p, s_p = np.sqrt(ab_t), np.sqrt(1 - ab_t), np.sqrt(ab_p), np.sqrt(1 - ab_p)
x0_hat = (xt - s_t * eps_hat) / a_t
x_prev = a_p * x0_hat + s_p * eps_hat # eta = 0
st_t, st_p = s_t / a_t, s_p / a_p # sigma tilde = sigma_t / a_t
euler = xt / a_t + (st_p - st_t) * (xt / a_t - x0_hat) / st_t
print(round(x0_hat, 5), round(x_prev, 5), round(euler * a_p, 5)) # 0.81421 0.99658 0.99658
# eta = 1: the DDIM noise and mean equal the DDPM posterior of this (respaced) step
beta = 1 - ab_t / ab_p
nu = 1.0 * (s_p / s_t) * np.sqrt(1 - ab_t / ab_p)
mean_ddim = a_p * x0_hat + np.sqrt(s_p**2 - nu**2) * eps_hat
mean_ddpm = a_p * beta / (1 - ab_t) * x0_hat + np.sqrt(1 - beta) * (1 - ab_p) / (1 - ab_t) * xt
print(round(nu**2, 5), round((1 - ab_p) / (1 - ab_t) * beta, 5)) # 0.15 0.15
print(round(mean_ddim, 5), round(mean_ddpm, 5)) # 0.86242 0.86242
# (b) Euler and Heun for one step of dx/dsigma = sigma x / (1 + sigma^2) (data N(0, 1))
d = lambda x, s: s * x / (1 + s**2)
x_e = 1 + (1 - 2) * d(1, 2)
x_h = 1 + (1 - 2) * (d(1, 2) + d(x_e, 1)) / 2
print(x_e, x_h, round(np.sqrt(2 / 5), 5)) # 0.6 0.65 0.63246
# (c) Karras grids
def karras(n, rho, smax=80.0, smin=0.002):
u = np.arange(n) / (n - 1)
if np.isinf(rho):
return smax * (smin / smax) ** u
return (smax ** (1 / rho) + u * (smin ** (1 / rho) - smax ** (1 / rho))) ** rho
for rho in (1, 3, 7, np.inf):
print(rho, np.round(karras(5, rho), 4))
# 1 [80. 60.0005 40.001 20.0015 0.002 ]
# 3 [80. 34.7465 10.9031 1.6087 0.002 ]
# 7 [80. 17.5278 2.5152 0.1698 0.002 ]
# inf [80. 5.6569 0.4 0.0283 0.002 ]
print((karras(18, 7) < 1).sum(), (karras(18, 1) < 1).sum()) # 7 1
Second, give SciPy's adaptive Runge–Kutta solver (RK45) the probability-flow ODE of the two-mode mixture of example (d), with no schedule at all, and look at where it puts its steps. The denoiser is exact (Tweedie for a Gaussian mixture, with responsibilities in log space):
import numpy as np
from scipy.integrate import solve_ivp
mu, sd = np.array([-1.0, 1.0]), 0.1 # data: 0.5 N(-1, 0.1^2) + 0.5 N(1, 0.1^2)
def denoiser(x, sigma):
"""D(x; sigma) = E[x0 | x0 + sigma * eps = x] for the mixture."""
v = sd**2 + sigma**2
logw = -(x[:, None] - mu) ** 2 / (2 * v)
w = np.exp(logw - logw.max(1, keepdims=True))
w /= w.sum(1, keepdims=True)
return (w * (mu + sd**2 * (x[:, None] - mu) / v)).sum(1)
def pf_ode(sigma, x): # dx/dsigma = (x - D(x; sigma)) / sigma
return (x - denoiser(x, sigma)) / sigma
x_start = 80.0 * np.random.default_rng(0).standard_normal(500)
sol = solve_ivp(pf_ode, (80.0, 0.002), x_start, method="RK45", rtol=1e-5, atol=1e-5)
levels = sol.t[:-1] # sigma at the start of each accepted step
print("steps:", len(levels), " NFE:", sol.nfev) # steps: 25 NFE: 224
print(np.sum(levels >= 1), np.sum((levels >= 0.1) & (levels < 1)), np.sum(levels < 0.1)) # 18 5 2
print(round(np.median(sol.t[1:] / sol.t[:-1]), 2)) # 0.75
print(np.mean(np.abs(np.abs(sol.y[:, -1]) - 1) < 0.4)) # 1.0: every path ends near a mode
The solver takes 25 steps. Their median ratio is 0.75, so it chooses an almost geometric grid by itself: 7 of its 25 steps lie below , where a uniform grid would put none. The last two steps are long again: below , the width of each mode, the denoiser barely changes and the path is straight. But 224 NFE is a lot (RK45 uses 6 evaluations per step, plus rejected steps). EDM tried RK45 and found that its cost outweighs its benefits; a fixed Heun grid is cheaper.
6. Where it shows up #
- Image and video models. Libraries offer these samplers by name: k-diffusion has
sample_euler,sample_heun,sample_euler_ancestral,sample_dpmpp_2mandget_sigmas_karras; diffusers has DDIM, Euler, Heun and DPM-Solver++ schedulers. 20–50 steps is a common default. - Weather. GenCast samples with a second-order DPM-Solver++ variant on a Karras grid () with 20 noise levels (39 NFE) plus EDM-style churn. The ensemble cost is members × forecast steps × NFE.
- Flow matching and rectified flow (lesson 10). Sampling integrates with Euler or Heun; the NFE accounting is the same. Straighter paths need fewer steps, for the reason of Theorem 3: a step is exact when the path is straight.
- Inversion, editing and likelihood. DDIM inversion runs the ODE from data to noise. Likelihoods (bits per dimension, lesson 14) need an accurate, usually adaptive ODE solve with a Hutchinson trace estimate (lesson 04).
- Guidance (lesson 11) changes the denoiser inside the same samplers; classifier-free guidance doubles the NFE of each step.
- Below 10–20 NFE, retrain: progressive distillation and consistency models (lesson 12).
7. Common mistakes #
- Comparing samplers at equal steps instead of equal NFE. A Heun step costs 2 NFE; classifier-free guidance doubles every count.
- Skipping steps in ancestral sampling but keeping the original . On a subsequence, recompute for each step. DDIM's formula does this automatically.
- Forgetting the in the probability-flow ODE. without noise shrinks the spread twice as fast as it should. The reverse SDE has ; the ODE has .
- Heun's corrector on the last step into . It divides by zero; use Euler there.
- Mixing coordinates. DDIM is Euler in . Euler on the VP ODE in is a different sampler with more curved paths.
- Starting below the top level ("leading" spacing) or with a nonzero terminal SNR (lesson 08).
- An SDE sampler at very low NFE. At 10 steps, gives FID 41 where gives 13 (CIFAR-10).
- A uniform grid. Most steps are then spent where the path is straight (example (d)).
- Clipping on unbounded data. Image samplers often clip to (in diffusers,
clip_sample=Trueis the default of the DDPM and DDIM schedulers). On physical fields this silently cuts the extremes; turn it off.
8. Check yourself #
- One DDIM step with : , , , . Compute
and check it as an Euler step.
Answer
, , , . ; . EDM coordinates: , , , slope ; , and ✓. - Write the reverse-time SDE and the probability-flow ODE for the VP SDE with .
Answer
Reverse SDE: (with ). PF-ODE: . - Why may the DDIM forward process be non-Markovian?
Answer
The training loss uses only the pairs at single times, through . Every member of the DDIM family has the DDPM marginals , so the optimal is the same, whatever the joint law across different times. - For levels between and , what is the middle level for , and ?
Answer
: . : . : , the geometric mean. - The data are a single point . Show that DDIM with reaches exactly in one step from any .
Answer
for every input, so the Euler step to gives . The true path is a straight line, so Euler has no discretization error. - In the reverse SDE, the score term is ; in the probability-flow ODE it is . Explain the factor in one or two sentences.
Answer
The forward Fokker–Planck equation has the spreading term . The ODE has no noise, so its drift must undo exactly this term: . The reverse SDE adds noise of strength again (another ), so its drift must undo twice as much: .
Write the reverse-time SDE for the forward SDE .
, run backward from .
Write the probability-flow ODE for the forward SDE .
; it has the same marginals as the SDE.
Give the VP SDE and say what discrete process it is the limit of.
; the limit of the DDPM forward chain with .
Why do the reverse SDE and the PF-ODE have the same marginals?
Writing turns the Fokker–Planck equation into a continuity equation with velocity ; both processes solve it from the same start density.
Write the DDIM update with .
, then .
In which coordinates is DDIM () exactly Euler's method, and for which ODE?
In , , for the PF-ODE .
What are the order and the NFE count of Heun's method with steps ending at ?
Second order (error ); NFE, because the last step into is a plain Euler step.
Give the Karras step schedule.
for , then ; EDM uses .
ODE or SDE sampler: what does each do better?
The ODE is deterministic, invertible and best at low NFE; the SDE's fresh noise partly corrects earlier errors but needs more steps.
9. Interview angle #
- "Make sampling 20 times faster without retraining." — DDIM, Heun or DPM-Solver++(2M) on a Karras grid: 10–50 NFE instead of 1,000. If retraining is allowed: distillation or consistency models.
- "What is the probability-flow ODE, and why does it give the right distribution?" — . The Fokker–Planck equation of the forward SDE can be written as a continuity equation with this velocity.
- "Is DDIM deterministic? Why is that useful?" — With , yes: inversion, interpolation in noise space, reproducible samples, likelihoods.
- "What is DDIM in ODE terms?" — Euler on the PF-ODE in , so first order; it is also the first-order exponential integrator (DPM-Solver-1).
- "ODE or SDE sampler?" — ODE at low NFE. Noise corrects earlier errors when you can afford more steps; tune the amount empirically.
- "Heun with 18 noise levels: how many network calls?" — 35; the last step is Euler.
- "Why are the noise levels not uniform?" — The paths bend at low noise; Karras puts short steps there.
10. Practice #
The notebook for this lesson has five exercises, each with a check cell and a folded solution:
- Simulate the VP SDE with Euler–Maruyama and compare the mean and variance of with the closed form.
- Sample the 8 Gaussians with the reverse SDE and with the probability-flow ODE (exact score); compare the counts per mode and the spread.
- Write the DDIM step with ; check that equals an Euler step in to rounding error, and that has the DDPM posterior variance.
- Euler vs Heun on the Gaussian toy: error against NFE; fit the slopes of the log–log lines.
- Karras vs a uniform grid: sample quality at 10 NFE with the exact 8-Gaussians denoiser.
11. Watch and read #
- Song, Sohl-Dickstein, Kingma, Kumar, Ermon, Poole, Score-Based Generative Modeling through Stochastic Differential Equations (ICLR 2021): section 3 (VE and VP SDEs, the reverse SDE), section 4.3 (the probability-flow ODE), Appendix D (the family of samplers).
- Song, Meng, Ermon, Denoising Diffusion Implicit Models (ICLR 2021): eq. 7 (the non-Markovian forward process), Theorem 1, eq. 12 (sampling), eq. 16 (), section 4.3 (the ODE view) and Table 1.
- Karras, Aittala, Aila, Laine, Elucidating the Design Space of Diffusion-Based Generative Models (EDM, 2022): section 3 (eq. 5 time steps, Algorithm 1 Heun, Figure 3 curvature), section 4 (Algorithm 2, the stochastic sampler).
- Lu, Zhou, Bao, Chen, Li, Zhu, DPM-Solver (NeurIPS 2022): section 3 (the exact solution of the linear part), section 4.1 (DPM-Solver-1 = DDIM).
- Anderson, Reverse-time diffusion equation models, Stochastic Processes and their Applications 12 (1982): the original time-reversal result.
- Holderrieth and Erives, An Introduction to Flow Matching and Diffusion Models (MIT 6.S184 lecture notes, 2025): chapters on SDEs, the Fokker–Planck equation and sampling.
- k-diffusion
sampling.py: short reference implementations ofget_sigmas_karras,sample_euler,sample_heun,sample_euler_ancestralandsample_dpmpp_2m.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.