Type at least 2 letters. Enter opens the first result, Esc closes.

    Generative Models · Lesson 7 · Diffusion and flow matching

    Denoising diffusion (DDPM): forward process, forward posterior, ELBO and the noise-prediction loss

    Advanced 95 min 4 interactive figures 4 videos Colab notebook

    Before this lesson: lesson 01 (the ELBO), lesson 02 (the KL divergence between two Gaussians) and lesson 06 (denoising score matching). From other tracks: the multivariate Gaussian (sums of independent Gaussians, conditioning). Time: about 95 minutes, plus the notebook.


    Why this matters #

    DDPM is the starting point of modern diffusion models: Stable Diffusion, Imagen and DALL·E 2 for images, diffusion models for video and audio, GenCast for ensemble weather forecasts, and latent diffusion emulators of seismic ground motion. The loss of this lesson ("predict the noise") is still the most common training objective. The next lessons change one piece of what is built here: the prediction target and the loss weights (lesson 08), the sampler (lesson 09), the conditioning (lesson 11) and the number of steps (lesson 12). "Derive the DDPM loss" is also a standard interview question.

    DDPM is a latent variable model with a fixed encoder, so it connects back to lesson 01: the training loss is the ELBO. It is also a score model: predicting the noise is denoising score matching at many noise levels, as in lesson 06.

    1. Predict first #

    2. The picture #

    One coordinate, one data point. Take x0=2x_0 = 2. One forward step multiplies by 1−β\sqrt{1 - \beta} (a number slightly below 1) and adds Gaussian noise of variance β\beta:

    xt=1−βt xt−1+βt zt,zt∼N(0,1).x_t = \sqrt{1 - \beta_t}\,x_{t-1} + \sqrt{\beta_t}\,z_t, \qquad z_t \sim \mathcal N(0, 1).

    The mean shrinks geometrically toward 0, and the noise accumulates. If xt−1x_{t-1} has variance 1, then xtx_t has variance (1−βt)⋅1+βt=1(1 - \beta_t) \cdot 1 + \beta_t = 1: the process is variance preserving (for data of unit variance). After many steps, xTx_T is close to N(0,1)\mathcal N(0, 1) and has forgotten x0x_0.

    In 2D. The figure applies the forward process to the track's 8 Gaussians. The heat map is the exact density of xtx_t; the dots are data points pushed to step tt.

    Interactive figure: loading…

    Move the step tt (or press Play). The 8 modes shrink toward the center and blur into one Gaussian. The shaded heat map is the exact density of xtx_t. Switch "How xtx_t is made" between one jump xt=αˉt x0+1−αˉt εx_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1 - \bar\alpha_t}\,\varepsilon and running the chain for tt steps: the path of the yellow point changes, but the cloud of points and the variance readouts agree. This is Theorem 1 below.

    The generative model runs the chain backward. Start from xT∼N(0,I)x_T \sim \mathcal N(0, I) and apply learned Gaussian steps pθ(xt−1∣xt)p_\theta(x_{t-1} \mid x_t) down to x0x_0. A Gaussian reverse step is a good model only because each forward step is small. For a small step, the true reverse conditional q(xt−1∣xt)q(x_{t-1} \mid x_t) is close to Gaussian. For a large step it can have several modes, and no Gaussian can fit it.

    Interactive figure: loading…

    One reverse step in 1D, for data with two points x0∈{−1,+1}x_0 \in \{-1, +1\}. The blue curves are the forward posteriors q(xt−1∣xt,x0)q(x_{t-1} \mid x_t, x_0) for each data point: always Gaussian. The black curve is the true reverse step q(xt−1∣xt)q(x_{t-1} \mid x_t), a mixture of the two blue curves. The orange dashed curve is the best single Gaussian. With "large step" the black curve has two bumps and the KL readout is large; choose "small step" and it is almost Gaussian. Move the observed xtx_t to see the weights change.

    It is a latent variable model. The latents are x1,…,xTx_1, \dots, x_T, each with the same dimension as the data. The "encoder" q(x1:T∣x0)q(x_{1:T} \mid x_0) is the fixed forward process and has no parameters. Only the "decoder" chain pθp_\theta is learned. So DDPM is a hierarchical VAE with a fixed encoder, and the ELBO of lesson 01 applies without change.

    The key trick. The reverse conditional q(xt−1∣xt)q(x_{t-1} \mid x_t) depends on the unknown data distribution. But once we also condition on x0x_0, the forward posterior q(xt−1∣xt,x0)q(x_{t-1} \mid x_t, x_0) is a Gaussian with a closed form (the blue curves above). The ELBO compares each learned step with this known Gaussian: one KL divergence per step.

    Quick check

    In the figure with two data points and a large step, why is the true reverse step q(xt−1∣xt)q(x_{t-1} \mid x_t) bimodal even though each forward posterior is Gaussian?

    3. Definitions and main results #

    Notation and schedules #

    x0∈Rdx_0 \in \R^d is a data point. The noise schedule is β1,…,βT∈(0,1)\beta_1, \dots, \beta_T \in (0, 1). Write

    αt=1−βt,αˉt=∏s=1tαs,αˉ0=1.\alpha_t = 1 - \beta_t, \qquad \bar\alpha_t = \prod_{s=1}^{t} \alpha_s, \qquad \bar\alpha_0 = 1.

    Always ε∼N(0,I)\varepsilon \sim \mathcal N(0, I).

    • Forward process: q(xt∣xt−1)=N(αt xt−1,βtI)q(x_t \mid x_{t-1}) = \mathcal N(\sqrt{\alpha_t}\,x_{t-1}, \beta_t I) and q(x1:T∣x0)=∏t=1Tq(xt∣xt−1)q(x_{1:T} \mid x_0) = \prod_{t=1}^T q(x_t \mid x_{t-1}), a Markov chain.
    • Reverse model: p(xT)=N(0,I)p(x_T) = \mathcal N(0, I) and pθ(xt−1∣xt)=N(μθ(xt,t),σt2I)p_\theta(x_{t-1} \mid x_t) = \mathcal N(\mu_\theta(x_t, t), \sigma_t^2 I), with a network μθ\mu_\theta and fixed variances σt2\sigma_t^2. The joint is pθ(x0:T)=p(xT)∏t=1Tpθ(xt−1∣xt)p_\theta(x_{0:T}) = p(x_T) \prod_{t=1}^T p_\theta(x_{t-1} \mid x_t).
    • Linear schedule (Ho et al.): βt\beta_t evenly spaced from β1=10−4\beta_1 = 10^{-4} to βT=0.02\beta_T = 0.02, with T=1000T = 1000. This gives αˉT≈4.04×10−5\bar\alpha_T \approx 4.04 \times 10^{-5}.
    • Cosine schedule (Nichol and Dhariwal 2021): αˉt=f(t)/f(0)\bar\alpha_t = f(t)/f(0) with f(t)=cos⁡2 ⁣(t/T+s1+s⋅π2)f(t) = \cos^2\!\big(\tfrac{t/T + s}{1 + s}\cdot\tfrac{\pi}{2}\big), s=0.008s = 0.008, and each βt\beta_t capped at 0.9990.999.
    • Signal-to-noise ratio: SNR(t)=αˉt/(1−αˉt)\mathrm{SNR}(t) = \bar\alpha_t / (1 - \bar\alpha_t). It decreases with tt.
    Interactive figure: loading…

    Compare the two schedules. Show αˉt\bar\alpha_t, log⁡SNR\log\mathrm{SNR} or βt\beta_t against t/Tt/T. The linear schedule loses half of the signal variance (αˉt=0.5\bar\alpha_t = 0.5) after about a quarter of the steps (t=260t = 260); the cosine schedule keeps it until the middle (t=497t = 497). Change TT: the dashed curve shows what happens if you keep the T=1000T = 1000 values of βt\beta_t with fewer steps.

    Theorem 1: the closed-form marginal #

    q(xt∣x0)=N(αˉt x0, (1−αˉt)I),that is,xt=αˉt x0+1−αˉt ε.q(x_t \mid x_0) = \mathcal N\big(\sqrt{\bar\alpha_t}\,x_0,\ (1 - \bar\alpha_t) I\big), \qquad\text{that is,}\qquad x_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1 - \bar\alpha_t}\,\varepsilon .

    Why this is true. Each step scales the old noise and adds new independent noise. A sum of independent Gaussians is Gaussian, and the variances add up.

    Proof (induction on tt).

    1. For t=1t = 1: αˉ1=α1\bar\alpha_1 = \alpha_1 and 1−αˉ1=β11 - \bar\alpha_1 = \beta_1, so the claim is the definition of the first step.
    2. Assume xt−1=αˉt−1 x0+1−αˉt−1 ε′x_{t-1} = \sqrt{\bar\alpha_{t-1}}\,x_0 + \sqrt{1 - \bar\alpha_{t-1}}\,\varepsilon' with ε′∼N(0,I)\varepsilon' \sim \mathcal N(0, I).
    3. Take one more step with fresh noise ε′′∼N(0,I)\varepsilon'' \sim \mathcal N(0, I), independent of ε′\varepsilon', and use αtαˉt−1=αˉt\sqrt{\alpha_t}\sqrt{\bar\alpha_{t-1}} = \sqrt{\bar\alpha_t}:
    xt=αt xt−1+βt ε′′=αˉt x0+[αt(1−αˉt−1) ε′+βt ε′′].x_t = \sqrt{\alpha_t}\,x_{t-1} + \sqrt{\beta_t}\,\varepsilon'' = \sqrt{\bar\alpha_t}\,x_0 + \Big[\sqrt{\alpha_t(1 - \bar\alpha_{t-1})}\,\varepsilon' + \sqrt{\beta_t}\,\varepsilon''\Big].
    1. The bracket is a sum of independent zero-mean Gaussians. Its covariance is c Ic\,I with c=αt(1−αˉt−1)+βtc = \alpha_t(1 - \bar\alpha_{t-1}) + \beta_t. Expand: c=αt−αˉt+1−αt=1−αˉtc = \alpha_t - \bar\alpha_t + 1 - \alpha_t = 1 - \bar\alpha_t. ■\blacksquare

    So training never runs the chain: draw tt and ε\varepsilon, and compute xtx_t in one line.

    Quick check

    The data have variance 2 in every coordinate. Is the forward process variance preserving for these data?

    Theorem 2: the forward posterior #

    For t≥2t \ge 2, q(xt−1∣xt,x0)=N(μ~t(xt,x0),β~tI)q(x_{t-1} \mid x_t, x_0) = \mathcal N\big(\tilde\mu_t(x_t, x_0), \tilde\beta_t I\big) with

    μ~t=αˉt−1 βt1−αˉt x0+αt (1−αˉt−1)1−αˉt xt,β~t=1−αˉt−11−αˉt βt.\tilde\mu_t = \frac{\sqrt{\bar\alpha_{t-1}}\,\beta_t}{1 - \bar\alpha_t}\,x_0 + \frac{\sqrt{\alpha_t}\,(1 - \bar\alpha_{t-1})}{1 - \bar\alpha_t}\,x_t, \qquad \tilde\beta_t = \frac{1 - \bar\alpha_{t-1}}{1 - \bar\alpha_t}\,\beta_t .

    Why this is true. Given x0x_0, the pair (xt−1,xt)(x_{t-1}, x_t) is jointly Gaussian: xt−1x_{t-1} comes from Theorem 1, and xtx_t is a linear function of xt−1x_{t-1} plus Gaussian noise. Conditioning a Gaussian on a linear observation gives a Gaussian. The mean is a weighted average of "where x0x_0 says xt−1x_{t-1} should be" and "where xtx_t says it should be".

    Proof (completing the square). It is enough to work with one coordinate: all coordinates have the same coefficients and are independent.

    1. Bayes' rule and the Markov property, q(xt∣xt−1,x0)=q(xt∣xt−1)q(x_t \mid x_{t-1}, x_0) = q(x_t \mid x_{t-1}), give, as a function of xt−1x_{t-1},
    q(xt−1∣xt,x0)∝q(xt∣xt−1)  q(xt−1∣x0).q(x_{t-1} \mid x_t, x_0) \propto q(x_t \mid x_{t-1})\; q(x_{t-1} \mid x_0).
    1. Write y=xt−1y = x_{t-1}. Up to a constant that does not depend on yy, the log of the right side is the quadratic function of yy below. So the posterior is Gaussian:
    −12[(xt−αt y)2βt+(y−αˉt−1 x0)21−αˉt−1].-\frac12\left[\frac{(x_t - \sqrt{\alpha_t}\,y)^2}{\beta_t} + \frac{(y - \sqrt{\bar\alpha_{t-1}}\,x_0)^2}{1 - \bar\alpha_{t-1}}\right].
    1. Expand and collect the y2y^2 terms. The coefficient of −12y2-\tfrac12 y^2 is the precision (inverse variance). With the identity of Theorem 1, step 4, it is
    αtβt+11−αˉt−1=αt(1−αˉt−1)+βtβt(1−αˉt−1)=1−αˉtβt(1−αˉt−1).\frac{\alpha_t}{\beta_t} + \frac{1}{1 - \bar\alpha_{t-1}} = \frac{\alpha_t(1 - \bar\alpha_{t-1}) + \beta_t}{\beta_t(1 - \bar\alpha_{t-1})} = \frac{1 - \bar\alpha_t}{\beta_t(1 - \bar\alpha_{t-1})}.
    1. The variance is the inverse of the precision, which is β~t\tilde\beta_t. Now collect the terms linear in yy: the coefficient of yy is
    h=αtβt xt+αˉt−11−αˉt−1 x0.h = \frac{\sqrt{\alpha_t}}{\beta_t}\,x_t + \frac{\sqrt{\bar\alpha_{t-1}}}{1 - \bar\alpha_{t-1}}\,x_0 .
    1. For a Gaussian, log⁡q=−12λy2+hy+const\log q = -\tfrac12 \lambda y^2 + h y + \text{const} with precision λ\lambda has mean h/λh/\lambda. So the mean is β~t h\tilde\beta_t\,h:
    β~th=(1−αˉt−1)βt1−αˉt⋅αtβt xt+(1−αˉt−1)βt1−αˉt⋅αˉt−11−αˉt−1 x0=μ~t.■\tilde\beta_t h = \frac{(1 - \bar\alpha_{t-1})\beta_t}{1 - \bar\alpha_t}\cdot\frac{\sqrt{\alpha_t}}{\beta_t}\,x_t + \frac{(1 - \bar\alpha_{t-1})\beta_t}{1 - \bar\alpha_t}\cdot\frac{\sqrt{\bar\alpha_{t-1}}}{1 - \bar\alpha_{t-1}}\,x_0 = \tilde\mu_t. \quad\blacksquare

    At t=1t = 1, αˉ0=1\bar\alpha_0 = 1 gives β~1=0\tilde\beta_1 = 0: given x0x_0, the last step is a point mass at x0x_0.

    The ε-form of the mean. Theorem 1 gives x0=(xt−1−αˉt ε)/αˉtx_0 = (x_t - \sqrt{1 - \bar\alpha_t}\,\varepsilon)/\sqrt{\bar\alpha_t}. Substitute this into μ~t\tilde\mu_t:

    1. The x0x_0 coefficient becomes αˉt−1 βt(1−αˉt)αˉt=βt(1−αˉt)αt\frac{\sqrt{\bar\alpha_{t-1}}\,\beta_t}{(1 - \bar\alpha_t)\sqrt{\bar\alpha_t}} = \frac{\beta_t}{(1 - \bar\alpha_t)\sqrt{\alpha_t}}.
    2. The total coefficient of xtx_t is βt+αt(1−αˉt−1)(1−αˉt)αt=1−αˉt(1−αˉt)αt=1αt\frac{\beta_t + \alpha_t(1 - \bar\alpha_{t-1})}{(1 - \bar\alpha_t)\sqrt{\alpha_t}} = \frac{1 - \bar\alpha_t}{(1 - \bar\alpha_t)\sqrt{\alpha_t}} = \frac{1}{\sqrt{\alpha_t}}.
    3. The coefficient of ε\varepsilon is −βt(1−αˉt)αt1−αˉt=−βtαt1−αˉt-\frac{\beta_t}{(1 - \bar\alpha_t)\sqrt{\alpha_t}}\sqrt{1 - \bar\alpha_t} = -\frac{\beta_t}{\sqrt{\alpha_t}\sqrt{1 - \bar\alpha_t}}. So
    μ~t=1αt(xt−βt1−αˉt ε).\tilde\mu_t = \frac{1}{\sqrt{\alpha_t}}\Big(x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}}\,\varepsilon\Big).

    Theorem 3: the ELBO as a sum of KL terms #

    −log⁡pθ(x0)≤L=LT+∑t=2TLt−1+L0,where-\log p_\theta(x_0) \le L = L_T + \sum_{t=2}^{T} L_{t-1} + L_0, \quad\text{where}
    LT=KL(q(xT∣x0) ∥ p(xT)),Lt−1=Eq(xt∣x0) KL(q(xt−1∣xt,x0) ∥ pθ(xt−1∣xt)),L0=− Eq(x1∣x0)log⁡pθ(x0∣x1).\begin{aligned} L_T &= \mathrm{KL}\big(q(x_T \mid x_0) \,\|\, p(x_T)\big), \\ L_{t-1} &= \mathbb E_{q(x_t \mid x_0)}\,\mathrm{KL}\big(q(x_{t-1} \mid x_t, x_0) \,\|\, p_\theta(x_{t-1} \mid x_t)\big), \\ L_0 &= -\,\mathbb E_{q(x_1 \mid x_0)} \log p_\theta(x_0 \mid x_1). \end{aligned}

    Proof.

    1. The ELBO with latents x1:Tx_{1:T} (lesson 01): log⁡pθ(x0)≥Eqlog⁡pθ(x0:T)q(x1:T∣x0)\log p_\theta(x_0) \ge \mathbb E_q \log \frac{p_\theta(x_{0:T})}{q(x_{1:T} \mid x_0)}, with q=q(x1:T∣x0)q = q(x_{1:T} \mid x_0).
    2. For t≥2t \ge 2, rewrite each forward factor with Bayes' rule, conditioned on x0x_0:
    q(xt∣xt−1)=q(xt∣xt−1,x0)=q(xt−1∣xt,x0) q(xt∣x0)q(xt−1∣x0).q(x_t \mid x_{t-1}) = q(x_t \mid x_{t-1}, x_0) = q(x_{t-1} \mid x_t, x_0)\,\frac{q(x_t \mid x_0)}{q(x_{t-1} \mid x_0)}.
    1. The ratios telescope: ∏t=2Tq(xt∣x0)q(xt−1∣x0)=q(xT∣x0)q(x1∣x0)\prod_{t=2}^T \frac{q(x_t \mid x_0)}{q(x_{t-1} \mid x_0)} = \frac{q(x_T \mid x_0)}{q(x_1 \mid x_0)}. The denominator cancels the first factor q(x1∣x0)q(x_1 \mid x_0) of the chain, so
    q(x1:T∣x0)=q(xT∣x0)∏t=2Tq(xt−1∣xt,x0).q(x_{1:T} \mid x_0) = q(x_T \mid x_0) \prod_{t=2}^T q(x_{t-1} \mid x_t, x_0).
    1. Insert this and pθ(x0:T)=p(xT)∏tpθ(xt−1∣xt)p_\theta(x_{0:T}) = p(x_T)\prod_t p_\theta(x_{t-1} \mid x_t) into step 1, and split the log:
    log⁡p(xT)q(xT∣x0)+∑t=2Tlog⁡pθ(xt−1∣xt)q(xt−1∣xt,x0)+log⁡pθ(x0∣x1).\log \frac{p(x_T)}{q(x_T \mid x_0)} + \sum_{t=2}^T \log \frac{p_\theta(x_{t-1} \mid x_t)}{q(x_{t-1} \mid x_t, x_0)} + \log p_\theta(x_0 \mid x_1).
    1. Take −Eq-\mathbb E_q. Each of the first two groups is the expectation of log⁡(q/p)\log(q/p) over one variable, averaged over the others: a KL divergence. The last group is L0L_0. ■\blacksquare

    Why this form. Every KL is between two Gaussians, so it has a closed form. This has much lower variance than a Monte Carlo estimate over the whole chain. LTL_T has no parameters; for the linear schedule and x0=1x_0 = 1 it is 2.0×10−52.0 \times 10^{-5} nats. For images scaled to [−1,1][-1, 1], Ho et al. model L0L_0 with a discrete decoder over the 256 pixel values.

    Theorem 4: each Lt−1L_{t-1} is a weighted noise-prediction error #

    Parameterize the reverse mean like the ε-form of μ~t\tilde\mu_t, with a noise-prediction network εθ(xt,t)\varepsilon_\theta(x_t, t):

    μθ(xt,t)=1αt(xt−βt1−αˉt εθ(xt,t)).\mu_\theta(x_t, t) = \frac{1}{\sqrt{\alpha_t}}\Big(x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}}\,\varepsilon_\theta(x_t, t)\Big).

    Then, for t≥2t \ge 2, with xt=αˉt x0+1−αˉt εx_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1 - \bar\alpha_t}\,\varepsilon and a constant CtC_t that does not depend on θ\theta,

    Lt−1=Eε[βt22σt2 αt (1−αˉt)⏟wt ∥ε−εθ(xt,t)∥2]+Ct.L_{t-1} = \mathbb E_{\varepsilon}\Big[\underbrace{\frac{\beta_t^2}{2\sigma_t^2\,\alpha_t\,(1 - \bar\alpha_t)}}_{w_t}\ \big\|\varepsilon - \varepsilon_\theta(x_t, t)\big\|^2\Big] + C_t .

    Proof.

    1. Use the KL divergence between two Gaussians in Rd\R^d with covariances s12Is_1^2 I and s22Is_2^2 I (lesson 02). Here s12=β~ts_1^2 = \tilde\beta_t and s22=σt2s_2^2 = \sigma_t^2 are fixed, so the first part below is the constant CtC_t:
    KL(N(m1,s12I) ∥ N(m2,s22I))=d2(s12s22−1−log⁡s12s22)+∥m1−m2∥22s22.\mathrm{KL}\big(\mathcal N(m_1, s_1^2 I) \,\|\, \mathcal N(m_2, s_2^2 I)\big) = \frac{d}{2}\Big(\frac{s_1^2}{s_2^2} - 1 - \log\frac{s_1^2}{s_2^2}\Big) + \frac{\|m_1 - m_2\|^2}{2 s_2^2}.
    1. Write both means in ε-form. They differ only in the noise term: μ~t−μθ=βtαt1−αˉt (εθ−ε)\tilde\mu_t - \mu_\theta = \frac{\beta_t}{\sqrt{\alpha_t}\sqrt{1 - \bar\alpha_t}}\,(\varepsilon_\theta - \varepsilon).
    2. Square and divide by 2σt22\sigma_t^2: βt22σt2αt(1−αˉt)∥ε−εθ∥2\frac{\beta_t^2}{2\sigma_t^2\alpha_t(1 - \bar\alpha_t)}\|\varepsilon - \varepsilon_\theta\|^2. ■\blacksquare

    So the network only has to predict the noise. This is denoising score matching at noise level tt (lesson 06): the score of the noised data is ∇log⁡pt(xt)≈−εθ(xt,t)/1−αˉt\nabla \log p_t(x_t) \approx -\varepsilon_\theta(x_t, t)/\sqrt{1 - \bar\alpha_t}. The weight depends on σt2\sigma_t^2:

    • with σt2=βt\sigma_t^2 = \beta_t:
    wt=βt2αt(1−αˉt);w_t = \frac{\beta_t}{2\alpha_t(1 - \bar\alpha_t)};
    • with σt2=β~t\sigma_t^2 = \tilde\beta_t:
    wt=βt2αt(1−αˉt−1)=12(SNR(t−1)SNR(t)−1).w_t = \frac{\beta_t}{2\alpha_t(1 - \bar\alpha_{t-1})} = \frac12\Big(\frac{\mathrm{SNR}(t-1)}{\mathrm{SNR}(t)} - 1\Big).

    For the linear schedule, w2=0.27w_2 = 0.27 (with βt\beta_t) or 0.600.60 (with β~t\tilde\beta_t), while wtw_t lies between about 0.0050.005 and 0.0100.010 for every t≥100t \ge 100. So the ELBO puts about 27 to 120 times more weight on t=2t = 2 than on any t≥100t \ge 100.

    LsimpleL_{\text{simple}}: drop the weights #

    Lsimple(θ)=Et∼U{1,…,T}, x0, ε ∥ε−εθ(αˉt x0+1−αˉt ε, t)∥2.L_{\text{simple}}(\theta) = \mathbb E_{t \sim \mathcal U\{1,\dots,T\},\ x_0,\ \varepsilon}\ \big\|\varepsilon - \varepsilon_\theta\big(\sqrt{\bar\alpha_t}\,x_0 + \sqrt{1 - \bar\alpha_t}\,\varepsilon,\ t\big)\big\|^2 .
    • The t≥2t \ge 2 terms are the Lt−1L_{t-1} with weight 1 instead of wtw_t. The t=1t = 1 term approximates L0L_0. LTL_T is dropped because it has no parameters.
    • Relative to the ELBO, LsimpleL_{\text{simple}} lowers the weight of small tt. Those terms teach the network to remove tiny amounts of noise: easy, and almost invisible in samples. The effort moves to larger tt, where the network must create structure.
    • Result (Ho et al., CIFAR-10, Table 1): training on the true bound LL gives FID 13.51 and ≤3.70\le 3.70 bits/dim; LsimpleL_{\text{simple}} gives FID 3.17 and ≤3.75\le 3.75 bits/dim. Much better samples, slightly worse likelihood. (FID: lower is better; lesson 14.)
    • Equal weights in ε also give targets of unit scale at every tt, which is easy for a network. Lesson 08 writes every such choice as a weight over the log-SNR.
    Quick check

    Compared with the true ELBO, what does training with LsimpleL_{\text{simple}} do?

    Training and ancestral sampling (Algorithms 1 and 2 of Ho et al.) #

    Training. Repeat:

    1. draw x0x_0 from the data;
    2. draw t∼U{1,…,T}t \sim \mathcal U\{1, \dots, T\};
    3. draw ε∼N(0,I)\varepsilon \sim \mathcal N(0, I);
    4. take a gradient step on ∥ε−εθ(αˉt x0+1−αˉt ε,t)∥2\|\varepsilon - \varepsilon_\theta(\sqrt{\bar\alpha_t}\,x_0 + \sqrt{1 - \bar\alpha_t}\,\varepsilon, t)\|^2.

    Sampling. Draw xT∼N(0,I)x_T \sim \mathcal N(0, I). For t=T,…,1t = T, \dots, 1: draw z∼N(0,I)z \sim \mathcal N(0, I) if t>1t > 1, else set z=0z = 0; then

    xt−1=1αt(xt−βt1−αˉt εθ(xt,t))+σtz.x_{t-1} = \frac{1}{\sqrt{\alpha_t}}\Big(x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}}\,\varepsilon_\theta(x_t, t)\Big) + \sigma_t z .

    Return x0x_0. This costs TT network evaluations (1000) per sample; lesson 09 reduces this.

    Another view of the same step. Let x^0=(xt−1−αˉt εθ)/αˉt\hat x_0 = (x_t - \sqrt{1 - \bar\alpha_t}\,\varepsilon_\theta)/\sqrt{\bar\alpha_t} be the clean sample implied by the noise prediction. Then the step mean equals μ~t(xt,x^0)\tilde\mu_t(x_t, \hat x_0): predict the clean sample, then take the forward-posterior step toward it. (Substitute x^0\hat x_0 into Theorem 2; it is the ε-form with εθ\varepsilon_\theta in place of ε\varepsilon.) Libraries such as diffusers compute the step this way, and can clip x^0\hat x_0 to the data range.

    Interactive figure: loading…

    Press "Play the reverse process". 1000 samples start as Gaussian noise and move to the 8 data modes; the path of one sample is drawn. The noise prediction is the exact best ε\varepsilon for this data (computed from the mixture, not learned), so any error comes from the sampler. Choose T=1,2,5,10T = 1, 2, 5, 10: with few large steps the Gaussian reverse step is wrong, and samples land between the modes. With T=100T = 100 or 10001000 both variance choices work.

    σt2=βt\sigma_t^2 = \beta_t or σt2=β~t\sigma_t^2 = \tilde\beta_t? #

    The best fixed σt2\sigma_t^2 is the variance of the true reverse conditional q(xt−1∣xt)q(x_{t-1} \mid x_t), with x0x_0 integrated out. It depends on the data. A 1D Gaussian example shows the range.

    Let x0∼N(0,c2)x_0 \sim \mathcal N(0, c^2) and vt=Var(xt)=αˉtc2+1−αˉtv_t = \mathrm{Var}(x_t) = \bar\alpha_t c^2 + 1 - \bar\alpha_t. Then Cov(xt−1,xt)=αt vt−1\mathrm{Cov}(x_{t-1}, x_t) = \sqrt{\alpha_t}\,v_{t-1} and vt=αtvt−1+βtv_t = \alpha_t v_{t-1} + \beta_t. Gaussian conditioning gives

    Var(xt−1∣xt)=vt−1−αtvt−12vt=vt−1 (vt−αtvt−1)vt=βt vt−1vt.\mathrm{Var}(x_{t-1} \mid x_t) = v_{t-1} - \frac{\alpha_t v_{t-1}^2}{v_t} = \frac{v_{t-1}\,(v_t - \alpha_t v_{t-1})}{v_t} = \beta_t\,\frac{v_{t-1}}{v_t}.
    • c=0c = 0 (all data at one point): vt=1−αˉtv_t = 1 - \bar\alpha_t, so the variance is β~t\tilde\beta_t. This is exact for any single point, because then q(xt−1∣xt)=q(xt−1∣xt,x0)q(x_{t-1} \mid x_t) = q(x_{t-1} \mid x_t, x_0).
    • c=1c = 1 (unit-variance Gaussian data): vt=1v_t = 1, so the variance is βt\beta_t.
    • 0<c<10 < c < 1: in between.

    Ho et al. (§3.2) state it the same way: βt\beta_t is optimal for x0∼N(0,I)x_0 \sim \mathcal N(0, I), β~t\tilde\beta_t for a single point, and these are the two extremes for data with unit variance per coordinate. In practice both give similar samples with T=1000T = 1000, because β~t/βt=(1−αˉt−1)/(1−αˉt)\tilde\beta_t/\beta_t = (1 - \bar\alpha_{t-1})/(1 - \bar\alpha_t) is close to 1 except for the first steps. For the linear schedule it is 0.450.45 at t=2t = 2, 0.850.85 at t=10t = 10 and above 0.990.99 for t≥168t \ge 168. The variance matters more for the likelihood, because the ELBO terms are largest at small tt. Nichol and Dhariwal (2021) learn Σθ=exp⁡(νlog⁡βt+(1−ν)log⁡β~t)\Sigma_\theta = \exp\big(\nu \log\beta_t + (1 - \nu)\log\tilde\beta_t\big) with a network output ν\nu, trained by Lsimple+0.001 LL_{\text{simple}} + 0.001\,L. This improves the log-likelihood and allows fewer sampling steps.

    Quick check

    All data are one point, x0=cx_0 = c. Which reverse variance makes the reverse model exact?

    Why small steps make the reverse step Gaussian

    Bayes' rule gives q(xt−1∣xt)∝q(xt∣xt−1) qt−1(xt−1)q(x_{t-1} \mid x_t) \propto q(x_t \mid x_{t-1})\,q_{t-1}(x_{t-1}), where qt−1q_{t-1} is the density of the noised data at step t−1t - 1. The first factor is a Gaussian in xt−1x_{t-1} with variance βt/αt\beta_t/\alpha_t, so for small βt\beta_t it is very narrow. Over such a narrow window, log⁡qt−1\log q_{t-1} is close to its first-order Taylor expansion, a linear function. A Gaussian times the exponential of a linear function is again a Gaussian, with its mean shifted by (βt/αt)∇log⁡qt−1(\beta_t/\alpha_t) \nabla \log q_{t-1}: the score appears here. So the reverse step is Gaussian up to an error that shrinks with βt\beta_t (Feller 1949; Sohl-Dickstein et al. 2015). For a large βt\beta_t, the window covers several modes of qt−1q_{t-1}, and the product keeps them all.

    Answers to section 1. (1) No. Theorem 1 gives x500x_{500} from x0x_0 and one draw of ε\varepsilon. (2) The likelihood gets slightly worse (3.753.75 vs 3.703.70 bits/dim) and the samples get much better (FID 3.173.17 vs 13.5113.51), because the weights moved from small tt to larger tt. (3) Worse: with large steps the true reverse conditional has several modes, and a Gaussian step cannot follow it. With the exact noise predictor on the 8 Gaussians, 99% of the samples land within 0.45 of a mode with T=1000T = 1000, but only 85% with T=10T = 10 and 55% with T=5T = 5 (notebook, section 4).

    4. Worked example #

    A three-step schedule with αˉ1=0.64\bar\alpha_1 = 0.64, αˉ2=0.36\bar\alpha_2 = 0.36 and αˉ3=0.04\bar\alpha_3 = 0.04.

    1. αt=αˉt/αˉt−1\alpha_t = \bar\alpha_t/\bar\alpha_{t-1}: α1=0.64\alpha_1 = 0.64, α2=0.36/0.64=0.5625\alpha_2 = 0.36/0.64 = 0.5625, α3=0.04/0.36=1/9\alpha_3 = 0.04/0.36 = 1/9.
    2. βt=1−αt\beta_t = 1 - \alpha_t: β1=0.36\beta_1 = 0.36, β2=0.4375\beta_2 = 0.4375, β3=8/9\beta_3 = 8/9.
    3. Signal scales: αˉ1=0.8\sqrt{\bar\alpha_1} = 0.8, αˉ2=0.6\sqrt{\bar\alpha_2} = 0.6, αˉ3=0.2\sqrt{\bar\alpha_3} = 0.2. Noise scales: 1−αˉ1=0.6\sqrt{1 - \bar\alpha_1} = 0.6, 1−αˉ2=0.8\sqrt{1 - \bar\alpha_2} = 0.8, 1−αˉ3=0.9798\sqrt{1 - \bar\alpha_3} = 0.9798.
    4. SNRt=αˉt/(1−αˉt)\mathrm{SNR}_t = \bar\alpha_t/(1 - \bar\alpha_t): SNR1=1.778\mathrm{SNR}_1 = 1.778, SNR2=0.5625\mathrm{SNR}_2 = 0.5625, SNR3=0.0417\mathrm{SNR}_3 = 0.0417.

    Marginal. q(x3∣x0)=N(0.2 x0, 0.96)q(x_3 \mid x_0) = \mathcal N(0.2\,x_0,\ 0.96).

    Forward posterior at t=2t = 2.

    • Variance: β~2=1−0.641−0.36⋅0.4375=0.36⋅0.43750.64\tilde\beta_2 = \dfrac{1 - 0.64}{1 - 0.36} \cdot 0.4375 = \dfrac{0.36 \cdot 0.4375}{0.64}, so β~2=0.24609375\tilde\beta_2 = 0.24609375. It is smaller than β2=0.4375\beta_2 = 0.4375.
    • Check with the precision: α2/β2=1.2857\alpha_2/\beta_2 = 1.2857 and 1/(1−αˉ1)=2.77781/(1 - \bar\alpha_1) = 2.7778. The sum is 4.06354.0635, and 1/4.0635=0.246091/4.0635 = 0.24609. ✓
    • Coefficient of x0x_0: 0.8⋅0.43750.64=0.546875\dfrac{0.8 \cdot 0.4375}{0.64} = 0.546875.
    • Coefficient of x2x_2: 0.5625⋅0.360.64=0.75⋅0.5625=0.421875\dfrac{\sqrt{0.5625} \cdot 0.36}{0.64} = 0.75 \cdot 0.5625 = 0.421875.

    One noisy sample. Take x0=1x_0 = 1 and ε=0.5\varepsilon = 0.5. Then x2=0.6⋅1+0.8⋅0.5=1.0x_2 = 0.6 \cdot 1 + 0.8 \cdot 0.5 = 1.0.

    • Mean from x0=1x_0 = 1 and x2=1x_2 = 1: μ~2=0.546875+0.421875=0.96875\tilde\mu_2 = 0.546875 + 0.421875 = 0.96875.
    • Mean from the ε-form: the noise term is 0.43750.8⋅0.5=0.2734375\frac{0.4375}{0.8} \cdot 0.5 = 0.2734375, and μ~2=(1.0−0.2734375)/0.75=0.96875\tilde\mu_2 = (1.0 - 0.2734375)/0.75 = 0.96875. ✓

    A network predicts εθ=0.3\varepsilon_\theta = 0.3 (error 0.20.2).

    • Model mean: the noise term is 0.43750.8⋅0.3=0.1640625\frac{0.4375}{0.8} \cdot 0.3 = 0.1640625, so μθ=(1.0−0.1640625)/0.75=1.114583\mu_\theta = (1.0 - 0.1640625)/0.75 = 1.114583.
    • Implied clean sample: x^0=(1.0−0.8⋅0.3)/0.6=1.266667\hat x_0 = (1.0 - 0.8 \cdot 0.3)/0.6 = 1.266667. Then μ~2(x2,x^0)=0.546875⋅1.266667+0.421875\tilde\mu_2(x_2, \hat x_0) = 0.546875 \cdot 1.266667 + 0.421875, which is 1.1145831.114583. ✓
    • With σ22=β~2\sigma_2^2 = \tilde\beta_2: the mean part of the KL is (μ~2−μθ)2/(2β~2)(\tilde\mu_2 - \mu_\theta)^2/(2\tilde\beta_2). Here μ~2−μθ=−0.145833\tilde\mu_2 - \mu_\theta = -0.145833 and 2β~2=0.49218752\tilde\beta_2 = 0.4921875, so it is 0.0432100.043210.
    • The same from Theorem 4: w2=12(SNR1/SNR2−1)w_2 = \tfrac12(\mathrm{SNR}_1/\mathrm{SNR}_2 - 1). Here SNR1/SNR2=3.1605\mathrm{SNR}_1/\mathrm{SNR}_2 = 3.1605, so w2=1.080247w_2 = 1.080247, and w2⋅0.22=0.043210w_2 \cdot 0.2^2 = 0.043210. ✓
    • With σ22=β2\sigma_2^2 = \beta_2: w2=0.43752⋅0.5625⋅0.64=0.607639w_2 = \dfrac{0.4375}{2 \cdot 0.5625 \cdot 0.64} = 0.607639. The mean part is 0.607639⋅0.04=0.0243060.607639 \cdot 0.04 = 0.024306 (plus a different constant C2C_2).

    LTL_T is not zero for three steps. For x0=1x_0 = 1, q(x3∣x0)=N(0.2,0.96)q(x_3 \mid x_0) = \mathcal N(0.2, 0.96), and the Gaussian KL formula gives

    KL(N(0.2,0.96) ∥ N(0,1))=12(0.96+0.22−1−ln⁡0.96)=0.0204 nats.\mathrm{KL}\big(\mathcal N(0.2, 0.96) \,\|\, \mathcal N(0, 1)\big) = \tfrac12\big(0.96 + 0.2^2 - 1 - \ln 0.96\big) = 0.0204 \text{ nats}.

    For the linear schedule with T=1000T = 1000 it is 2.0×10−52.0 \times 10^{-5} nats.

    Open the figure of section 2 with "worked example" to see this posterior: αˉt−1=0.64\bar\alpha_{t-1} = 0.64, βt=0.4375\beta_t = 0.4375 and xt=1x_t = 1.

    Quick check

    In the worked example, what is the reverse mean μθ\mu_\theta if the network predicts the noise exactly, εθ=0.5\varepsilon_\theta = 0.5?

    5. In code #

    NumPy checks the worked example by plain Gaussian conditioning (no DDPM formula), checks Theorem 4 on the same numbers, and checks Theorems 1 and 2 on the linear schedule.

    import numpy as np
    
    # (a) Worked example: abar = (0.64, 0.36, 0.04). The forward posterior at t = 2 by plain
    #     Gaussian conditioning of the joint (x_1, x_2) given x_0, without any DDPM formula.
    ab1, ab2 = 0.64, 0.36
    a2 = ab2 / ab1                                   # alpha_2 = 0.5625
    x0, x2 = 1.0, 1.0
    mean = np.array([np.sqrt(ab1) * x0, np.sqrt(ab2) * x0])
    cov = np.array([[1 - ab1, np.sqrt(a2) * (1 - ab1)],
                    [np.sqrt(a2) * (1 - ab1), 1 - ab2]])
    k = cov[0, 1] / cov[1, 1]                        # regression coefficient of x_1 on x_2
    print(f"{mean[0] + k * (x2 - mean[1]):.5f} {cov[0, 0] - k * cov[0, 1]:.8f}")
    # 0.96875 0.24609375                            (mu_tilde_2 and beta_tilde_2)
    
    # (b) The same mean from the eps-form, and the eps-MSE weight with sigma^2 = beta_tilde
    b2, eps, eps_hat = 1 - a2, 0.5, 0.3
    mu = (x2 - b2 / np.sqrt(1 - ab2) * eps) / np.sqrt(a2)
    mu_th = (x2 - b2 / np.sqrt(1 - ab2) * eps_hat) / np.sqrt(a2)
    bt2 = (1 - ab1) / (1 - ab2) * b2
    w2 = b2**2 / (2 * bt2 * a2 * (1 - ab2))
    print(f"{mu:.5f} {(mu - mu_th)**2 / (2 * bt2):.6f} {w2 * (eps - eps_hat)**2:.6f}")
    # 0.96875 0.043210 0.043210
    
    # (c) Theorems 1 and 2 on the linear schedule: chain vs jump, and the posterior variance
    rng = np.random.default_rng(0)
    T = 1000
    betas = np.linspace(1e-4, 0.02, T)
    abar = np.cumprod(1 - betas)
    x = np.full(100000, 2.0)
    for b in betas[:300]:                            # run the chain for 300 steps
        x = np.sqrt(1 - b) * x + np.sqrt(b) * rng.standard_normal(x.shape)
    print(f"{x.mean():.3f} {np.sqrt(abar[299]) * 2:.3f} {x.var():.3f} {1 - abar[299]:.3f}")
    # 1.262 1.259 0.602 0.604                       (chain vs closed form: mean, variance)
    ratio = (1 - np.concatenate([[1.0], abar[:-1]])) / (1 - abar)   # beta_tilde_t / beta_t
    print(f"{abar[-1]:.2e}", ratio[1].round(3), ratio[9].round(3), np.argmax(ratio > 0.99) + 1)
    # 4.04e-05 0.455 0.853 168
    

    The notebook writes the closed forms, the ELBO weights and the ancestral sampler, runs the sampler with the exact noise predictor of the 8 Gaussians, and (optionally, with PyTorch) trains a small noise predictor on two moons.

    6. Where it shows up #

    • Images, video, audio. Noise prediction with LsimpleL_{\text{simple}} is the original recipe of latent diffusion (Stable Diffusion 1.x), applied to autoencoder latents (lesson 13). Imagen, DALL·E 2 and many audio models (DiffWave, WaveGrad) started from the same loss.
    • Weather and climate. GenCast generates each ensemble member as a diffusion sample, conditioned on the recent weather states (it uses the EDM form of lesson 08). CorrDiff downscales to km scale with a diffusion model of the residual of a regression network.
    • Seismology. Latent diffusion emulators of ground motion run exactly this forward process on the latent code of a waveform autoencoder, with conditioning inputs such as magnitude, distance and site terms.
    • Likelihoods. The full bound LL gives bits per dimension (lesson 14). Variational diffusion models train LL directly and reach strong likelihoods.
    • Practice: data scale. The schedule assumes data of unit scale. For data with standard deviation cc, the effective SNR is c2 αˉt/(1−αˉt)c^2\,\bar\alpha_t/(1 - \bar\alpha_t). Data with c=10c = 10 have 100 times the SNR at every step, as if the log-SNR were shifted by ln⁡100≈4.6\ln 100 \approx 4.6. So standardize each channel (for physical fields: each variable and level).

    7. Common mistakes #

    • Indexing off by one. αˉt\bar\alpha_t includes step tt, αˉ0=1\bar\alpha_0 = 1, and the posterior uses αˉt−1\bar\alpha_{t-1}. Storing schedules with length T+1T + 1 and index 0 for clean data avoids most errors.
    • Mixing up βt\beta_t and 1−αˉt1 - \bar\alpha_t. βt\beta_t is the variance added by one step; 1−αˉt1 - \bar\alpha_t is the total noise variance at tt. xt=1−βt x0+βt εx_t = \sqrt{1 - \beta_t}\,x_0 + \sqrt{\beta_t}\,\varepsilon is wrong.
    • A variance where a standard deviation is needed. Multiply ε\varepsilon by 1−αˉt\sqrt{1 - \bar\alpha_t}, and zz by σt\sigma_t, not by σt2\sigma_t^2.
    • Noise at the last step. At t=1t = 1, return the mean (z=0z = 0).
    • Reading LsimpleL_{\text{simple}} as a likelihood. Its value is not a bound on −log⁡p(x0)-\log p(x_0). To report bits/dim, evaluate the weighted bound LL.
    • Expecting the loss to reach zero. Even the best network cannot know ε\varepsilon exactly from xtx_t. The minimum of the loss is the conditional variance of ε\varepsilon given xtx_t, summed over coordinates (lesson 08). It stays positive.
    • Large steps with a Gaussian reverse step. With T=10T = 10 and the same total noise, the true reverse conditional can be far from Gaussian (for multimodal data it can have several modes), and ancestral sampling gives poor samples. Few-step sampling needs other tools (lesson 09 and lesson 12).
    • Data that are not standardized. The schedule then gives a different SNR than intended, and the last step may still contain a lot of signal.

    8. Check yourself #

    1. Why does q(xt−1∣xt,x0)q(x_{t-1} \mid x_t, x_0) have a closed form, but q(xt−1∣xt)q(x_{t-1} \mid x_t) does not?
      AnswerGiven x0x_0, all variables are linear-Gaussian, so conditioning is Gaussian algebra. Without x0x_0, q(xt−1∣xt)=∫q(xt−1∣xt,x0) q(x0∣xt) dx0q(x_{t-1} \mid x_t) = \int q(x_{t-1} \mid x_t, x_0)\, q(x_0 \mid x_t)\, dx_0 needs the posterior over the data, which depends on the unknown data distribution.
    2. A constant schedule βt=0.01\beta_t = 0.01. After how many steps is αˉt<0.01\sqrt{\bar\alpha_t} < 0.01?
      Answerαˉt=0.99t\bar\alpha_t = 0.99^t, and we need 0.99t<10−40.99^t < 10^{-4}: t>ln⁡10−4/ln⁡0.99=916.4t > \ln 10^{-4}/\ln 0.99 = 916.4, so t=917t = 917.
    3. Show that the DDPM step mean equals μ~t(xt,x^0)\tilde\mu_t(x_t, \hat x_0) with x^0=(xt−1−αˉt εθ)/αˉt\hat x_0 = (x_t - \sqrt{1 - \bar\alpha_t}\,\varepsilon_\theta)/\sqrt{\bar\alpha_t}.
      AnswerThe ε-form was obtained by substituting x0=(xt−1−αˉt ε)/αˉtx_0 = (x_t - \sqrt{1 - \bar\alpha_t}\,\varepsilon)/\sqrt{\bar\alpha_t} into μ~t\tilde\mu_t. The same algebra with εθ\varepsilon_\theta in place of ε\varepsilon turns μ~t(xt,x^0)\tilde\mu_t(x_t, \hat x_0) into 1αt(xt−βt1−αˉtεθ)=μθ\frac{1}{\sqrt{\alpha_t}}\big(x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}}\varepsilon_\theta\big) = \mu_\theta.
    4. With σt2=β~t\sigma_t^2 = \tilde\beta_t, write the ELBO weight wtw_t of the ε-MSE in terms of the SNR. Is it larger at small or at large tt for the linear schedule?
      Answerwt=12(SNR(t−1)/SNR(t)−1)w_t = \tfrac12\big(\mathrm{SNR}(t-1)/\mathrm{SNR}(t) - 1\big). It is largest at small tt (0.600.60 at t=2t = 2) and only about 0.0050.005 to 0.0100.010 for t≥100t \ge 100.
    5. All data are one point, x0=cx_0 = c. What must εθ\varepsilon_\theta learn so that the reverse model with σt2=β~t\sigma_t^2 = \tilde\beta_t is exact?
      Answerεθ(xt,t)=(xt−αˉt c)/1−αˉt\varepsilon_\theta(x_t, t) = (x_t - \sqrt{\bar\alpha_t}\,c)/\sqrt{1 - \bar\alpha_t}, the noise implied by the known cc. Then x^0=c\hat x_0 = c and μθ=μ~t(xt,c)\mu_\theta = \tilde\mu_t(x_t, c), so every reverse step equals the true one.
    6. Why does LTL_T not appear in training, and when is that a problem?
      AnswerIt has no parameters when the βt\beta_t are fixed. It is a problem when αˉT\bar\alpha_T is not small: then the prior N(0,I)\mathcal N(0, I) does not match q(xT∣x0)q(x_T \mid x_0) (for x0=1x_0 = 1: 0.0204 nats for the three-step example, 2×10−52 \times 10^{-5} nats for the linear schedule). Lesson 08 shows a real case (zero terminal SNR).
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. What is q(xt∣x0)q(x_t \mid x_0) in DDPM?

    2. How do you draw xtx_t from x0x_0 in one line?

    3. What is the variance β~t\tilde\beta_t of the forward posterior q(xt−1∣xt,x0)q(x_{t-1} \mid x_t, x_0)?

    4. Write the forward posterior mean μ~t\tilde\mu_t in terms of xtx_t and the noise ε\varepsilon.

    5. What is LsimpleL_{\text{simple}}?

    6. Why does LsimpleL_{\text{simple}} give better samples than the ELBO?

    7. Write one step of DDPM ancestral sampling.

    8. For which data is σt2=β~t\sigma_t^2 = \tilde\beta_t exact, and for which is σt2=βt\sigma_t^2 = \beta_t exact?

    9. Why must the forward steps of DDPM be small?

    Open the review →

    9. Interview angle #

    • "Derive the DDPM loss." ELBO; rewrite q(x1:T∣x0)q(x_{1:T} \mid x_0) with forward posteriors (the ratios telescope); KL between Gaussians; ε-form of the mean; drop the weights.
    • "Why predict the noise and not the mean?" With the ε-form, the KL becomes an ε-MSE with a unit-scale target at every tt: denoising score matching. Ho et al. (Table 2) report that predicting μ~t\tilde\mu_t directly works only with the true bound, and that training it with an unweighted MSE was unstable.
    • "Why 1000 steps?" A Gaussian reverse step is accurate only for small steps.
    • "Is DDPM a VAE?" A hierarchical VAE with a fixed encoder, latents of the data dimension, and one decoder network shared across steps (it takes tt as input).
    • "What does σt2\sigma_t^2 change?" Almost nothing for samples with T=1000T = 1000; it matters for the likelihood. β~t\tilde\beta_t is exact for a point mass, βt\beta_t for N(0,I)\mathcal N(0, I) data.
    • "How do you get xtx_t during training?" In one line from x0x_0 and one Gaussian draw (Theorem 1); the chain is never run during training.

    10. Practice #

    The notebook for this lesson has five exercises, each with a check cell and a folded solution, and an optional PyTorch demonstration:

    1. Make xtx_t two ways, by the one-step jump and by running the chain; compare the means and variances.
    2. Write q_posterior; check it against the worked example and against Monte Carlo conditioning.
    3. Compute the ELBO weights wtw_t of the ε-MSE for the linear schedule, for both variance choices; plot them.
    4. Write the ancestral sampler; run it with the exact noise predictor of the 8 Gaussians and count the samples per mode; then use fewer, larger steps.
    5. Compare the schedules: when is half of the signal variance gone?
    6. Optional (PyTorch): train a small noise predictor on two moons with LsimpleL_{\text{simple}} and sample from it.

    11. Watch and read #

    The forward and reverse processes, the closed-form marginal and the noise-prediction loss, with clear animations.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The full derivation of this lesson: the ELBO, its simplification into KL terms, and the step from the ELBO to an L2 loss.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    A slower walk through the DDPM paper and its math, including the forward posterior.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The big picture of diffusion for images and video, with excellent visual intuition.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play