The third installment. Having built the prerequisites (Part 1) and derived the closed-form forward/noising process (Part 2 — the "route"), we now tackle the reverse/denoising process: how to walk a noisy image backward, one step at a time, into the image we want. In the experienced-driver picture this is the car (车).

Loot from the previous levels

Clearing a level earns rewards you carry into the next. Here's our inventory of known conditions:

① The (human-defined) one-step noising formula: q(xt∣xt−1):=N(xt; 1−βt xt−1, βtI).q(x_t \mid x_{t-1}) := \mathcal{N}\big(x_t;\ \sqrt{1-\beta_t}\, x_{t-1},\ \beta_t \mathbf{I}\big). Don't ask why — the driver just picks a reasonable route.

② The closed-form jump from x0x_0 (Part 2's nesting-dolls result): $$ q(x_t \mid x_0) = \mathcal{N}\big(x_t;\ \sqrt{\bar\alpha_t}, x_0,\ (1-\bar\alpha_t)\mathbf{I}\big) \ \Longleftrightarrow
x_t = \sqrt{\bar\alpha_t}, x_0 + \sqrt{1-\bar\alpha_t},\varepsilon,\quad \varepsilon \sim \mathcal{N}(\mathbf{0}, \mathbf{I}). $$ This is the reparameterized form; we'll run it in reverse to read off the underlying Gaussian.

③ The normal PDF, which we'll write in the "expanded exponent" form (this is the form that makes the template-matching trick work): $$ p(x) = \frac{1}{\sqrt{2\pi},\sigma}\exp!\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) = \frac{1}{\sqrt{2\pi},\sigma}\exp!\left[-\frac12\left(\frac{x^2}{\sigma^2} - \frac{2\mu x}{\sigma^2} + \frac{\mu^2}{\sigma^2}\right)\right]. $$

④ and ⑤ — the author's bookkeeping definitions: $$ \bar\alpha_t = \alpha_t,\alpha_{t-1}\cdots\alpha_1 = \prod_{i=1}^{t}\alpha_i, \qquad \alpha_t + \beta_t = 1. $$


Why we need a distribution, not a match

The goal is the reverse direction (reverse = backward in time): given xtx_t, find xt−1x_{t-1}. Specifically we want the distribution q(xt−1∣xt)q(x_{t-1} \mid x_t), then sample from it.

Why a distribution and not a direct mapping? Because this is a generative model — we want to create, including images outside the training set. If we learn a relationship between two distributions, we can sample one point from the prior and generate a corresponding point in the data distribution pdatap_{\text{data}}. A one-to-one sample matching could never work:

  • There are infinitely many noise samples — you can't enumerate the pairing.
  • Your finite training samples are tiny relative to the space. Sample a fresh noise vector that deviates from anything you've seen, and a match-based scheme produces garbage.

So we build a distribution-to-distribution relationship. That's what lets us generalize. This is a generation task, not a matching task.


Step 1: Bayes' rule to flip time

Look at the known conditions — they all run forward in time (t−1→tt-1 \to t, with t>t−1>0t > t-1 > 0). We know forward; we're asked for reverse. The first instinct: flip time with Bayes' rule.

q(xt−1∣xt)=q(xt∣xt−1) q(xt−1)q(xt).q(x_{t-1} \mid x_t) = \frac{q(x_t \mid x_{t-1})\, q(x_{t-1})}{q(x_t)}.

But this introduces a new problem: q(xt−1)q(x_{t-1}) and q(xt)q(x_t) are data distributions we don't know. (If we knew those, we wouldn't need any of this.) Dead end — as written.


Step 2: Add the condition x0x_0

The fix: condition everything on x0x_0.

q(xt−1∣xt,x0)=q(xt∣xt−1,x0) q(xt−1∣x0)q(xt∣x0).q(x_{t-1} \mid x_t, x_0) = \frac{q(x_t \mid x_{t-1}, x_0)\, q(x_{t-1} \mid x_0)}{q(x_t \mid x_0)}.

Is adding x0x_0 legitimate? Two reasons it is:

  1. It makes the problem solvable — every term on the right becomes something we know (below).
  2. It matches the training setup. In (unconditional) training, our data is a set of original images x0x_0. We add noise to x0x_0 and ask the model to restore it. The only thing we genuinely have in hand is x0x_0 — so it's exactly the condition we're allowed to add. You can only condition on what you can actually obtain, and we can obtain x0x_0.

And conditions ① and ② quietly hint that conditioning on x0x_0 is the only way to make the distribution tractable.

The three terms are all known Gaussians

  • q(xt∣xt−1,x0)=Markovq(xt∣xt−1)q(x_t \mid x_{t-1}, x_0) \overset{\text{Markov}}{=} q(x_t \mid x_{t-1}) — by the Markov property only adjacent timesteps interact, so x0x_0 vanishes. This is condition ①.
  • q(xt−1∣x0)q(x_{t-1} \mid x_0) — condition ② (at t−1t-1).
  • q(xt∣x0)q(x_t \mid x_0) — condition ② (at tt).

Explicitly:

q(xt∣xt−1)=N(xt; αt xt−1, βtI),q(x_t \mid x_{t-1}) = \mathcal{N}\big(x_t;\ \sqrt{\alpha_t}\, x_{t-1},\ \beta_t \mathbf{I}\big), q(xt−1∣x0)=N(xt−1; αˉt−1 x0, (1−αˉt−1)I),q(x_{t-1} \mid x_0) = \mathcal{N}\big(x_{t-1};\ \sqrt{\bar\alpha_{t-1}}\, x_0,\ (1-\bar\alpha_{t-1})\mathbf{I}\big), q(xt∣x0)=N(xt; αˉt x0, (1−αˉt)I).q(x_t \mid x_0) = \mathcal{N}\big(x_t;\ \sqrt{\bar\alpha_t}\, x_0,\ (1-\bar\alpha_t)\mathbf{I}\big).

⚠️ Watch the bars. Some terms use αˉ\bar\alpha (cumulative product) and some use plain α\alpha. The single most common derivation error is copying αˉt−1\bar\alpha_{t-1} where you meant αt\alpha_t, or dropping a bar. Keep them straight.


Step 3: Plug in the PDFs and collect powers of xt−1x_{t-1}

Substitute the three Gaussian densities (condition ③). The leading 12πσ\tfrac{1}{\sqrt{2\pi}\sigma} coefficients are constants and can be dropped — they don't affect the resulting mean/variance. (I checked this by carrying them through too; the final μ\mu and σ2\sigma^2 come out identical, which is itself a confirmation that a product/quotient of Gaussians is again Gaussian.)

Multiplying/dividing exponentials just adds/subtracts exponents. The combined exponent is:

−12[(xt−αt xt−1)2βt+(xt−1−αˉt−1 x0)21−αˉt−1−(xt−αˉt x0)21−αˉt].-\frac{1}{2}\left[\frac{(x_t - \sqrt{\alpha_t}\,x_{t-1})^2}{\beta_t} + \frac{(x_{t-1} - \sqrt{\bar\alpha_{t-1}}\,x_0)^2}{1-\bar\alpha_{t-1}} - \frac{(x_t - \sqrt{\bar\alpha_t}\,x_0)^2}{1-\bar\alpha_t}\right].

We're after a distribution over xt−1x_{t-1}, so expand and collect by powers of xt−1x_{t-1}:

exp⁡ ⁣(−12[(αtβt+11−αˉt−1)⏟coeff. of xt−12 xt−12  −  (2αtβt xt+2αˉt−11−αˉt−1 x0)⏟coeff. of xt−1 xt−1  +  C(xt,x0)]).\exp\!\left(-\frac12\left[ \underbrace{\left(\frac{\alpha_t}{\beta_t} + \frac{1}{1-\bar\alpha_{t-1}}\right)}_{\text{coeff. of } x_{t-1}^2}\, x_{t-1}^2 \;-\; \underbrace{\left(\frac{2\sqrt{\alpha_t}}{\beta_t}\,x_t + \frac{2\sqrt{\bar\alpha_{t-1}}}{1-\bar\alpha_{t-1}}\,x_0\right)}_{\text{coeff. of } x_{t-1}}\, x_{t-1} \;+\; C(x_t, x_0)\right]\right).

Here C(xt,x0)C(x_t, x_0) collects everything independent of xt−1x_{t-1}. It doesn't affect μ\mu or σ2\sigma^2 — in fact, plugging the final μ,σ2\mu, \sigma^2 back in reproduces exactly the "completing-the-square" remainder, another sanity check.


Step 4: "Trace the gourd to draw the ladle" (照葫芦画瓢)

Last time the keyword was nesting dolls. This time it's 照葫芦画瓢 — match the template. We line our exponent up against the standard form −12(x2σ2−2μxσ2+μ2σ2)-\frac12\big(\frac{x^2}{\sigma^2} - \frac{2\mu x}{\sigma^2} + \frac{\mu^2}{\sigma^2}\big) and read off σ2\sigma^2 and μ\mu.

Variance — from the xt−12x_{t-1}^2 coefficient

1σ2=αtβt+11−αˉt−1=αt(1−αˉt−1)+βtβt(1−αˉt−1).\frac{1}{\sigma^2} = \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})}.

Simplify the numerator using αtαˉt−1=αˉt\alpha_t \bar\alpha_{t-1} = \bar\alpha_t and αt+βt=1\alpha_t + \beta_t = 1:

αt−αtαˉt−1+βt=(αt+βt)−αˉt=1−αˉt.\alpha_t - \alpha_t\bar\alpha_{t-1} + \beta_t = (\alpha_t + \beta_t) - \bar\alpha_t = 1 - \bar\alpha_t.

Therefore:

1σ2=1−αˉtβt(1−αˉt−1)⟹ σ2=β~t=1−αˉt−11−αˉt βt. \frac{1}{\sigma^2} = \frac{1-\bar\alpha_t}{\beta_t(1-\bar\alpha_{t-1})} \quad\Longrightarrow\quad \boxed{\ \sigma^2 = \tilde\beta_t = \frac{1-\bar\alpha_{t-1}}{1-\bar\alpha_t}\,\beta_t.\ }

This is the paper's β~t\tilde\beta_t.

Mean — from the xt−1x_{t-1} coefficient

Matching 2μσ2\dfrac{2\mu}{\sigma^2} to the linear coefficient:

2μσ2=2αtβt xt+2αˉt−11−αˉt−1 x0⟹μ=12 σ2(2αtβt xt+2αˉt−11−αˉt−1 x0).\frac{2\mu}{\sigma^2} = \frac{2\sqrt{\alpha_t}}{\beta_t}\,x_t + \frac{2\sqrt{\bar\alpha_{t-1}}}{1-\bar\alpha_{t-1}}\,x_0 \quad\Longrightarrow\quad \mu = \frac12\,\sigma^2\left(\frac{2\sqrt{\alpha_t}}{\beta_t}\,x_t + \frac{2\sqrt{\bar\alpha_{t-1}}}{1-\bar\alpha_{t-1}}\,x_0\right).

Substituting σ2=β~t\sigma^2 = \tilde\beta_t and simplifying:

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

So the reverse posterior is:

q(xt−1∣xt,x0)=N(xt−1; μ~t(xt,x0), β~tI).q(x_{t-1} \mid x_t, x_0) = \mathcal{N}\big(x_{t-1};\ \tilde\mu_t(x_t, x_0),\ \tilde\beta_t \mathbf{I}\big).

The algebra to get μ~t\tilde\mu_t is pure elementary manipulation (no trick) — just keep applying αtαˉt−1=αˉt\alpha_t\bar\alpha_{t-1} = \bar\alpha_t and αt+βt=1\alpha_t + \beta_t = 1, and don't miscopy a term. xtx_t is the previous (known) step and x0x_0 is the original training image, so everything in μ~t\tilde\mu_t is available at training time. Without conditioning on x0x_0, you genuinely could not solve this.


Step 5: From x0x_0 to noise — why DDPM predicts ε\varepsilon

Here's the catch. μ~t\tilde\mu_t needs x0x_0. At training time we have it. At inference time we don't — we only have a noisy xtx_t. So we let a model predict it.

Recall from condition ② that xt=αˉt x0+1−αˉt εx_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1-\bar\alpha_t}\,\varepsilon. Solve for x0x_0:

x^0=xt−1−αˉt εαˉt.\hat{x}_0 = \frac{x_t - \sqrt{1-\bar\alpha_t}\,\varepsilon}{\sqrt{\bar\alpha_t}}.

This says x0x_0 and the noise ε\varepsilon are interchangeable as the unknown. The model has two equivalent options:

  • Predict x0x_0 directly, or
  • Predict the noise ε\varepsilon — and recover x^0\hat x_0 from the equation above.

DDPM chooses to predict the noise ε\varepsilon. Knowing ε^\hat\varepsilon gives x^0\hat x_0, which gives μ~t\tilde\mu_t, which lets us sample xt−1x_{t-1} and iterate xT→xT−1→⋯→x0x_T \to x_{T-1} \to \cdots \to x_0.

The loss

We want our predicted noise to match the true noise — minimize the gap between two tensors. The natural choices are MSE (L2L_2) or L1; DDPM (and most work) uses MSE. So the training objective collapses to: predict the injected noise accurately,

L=∥ ε−εθ(xt,t) ∥2.\mathcal{L} = \big\|\,\varepsilon - \varepsilon_\theta(x_t, t)\,\big\|^2.

Interestingly, this same "predict ε\varepsilon with MSE" target also drops out of the principled route — maximizing the likelihood max⁡θlog⁡pθ(x)\max_\theta \log p_\theta(x) (the variational bound from Part 1). Think of it as two paths to the same technique: the "forward discipline" (likelihood / loss derivation) and the "reverse discipline" (this posterior derivation). Both land on noise prediction with MSE.


Summary

  • Goal: the reverse posterior q(xt−1∣xt)q(x_{t-1} \mid x_t) — but we only know forward conditionals.
  • Bayes' rule flips time but introduces unknown data marginals q(xt),q(xt−1)q(x_t), q(x_{t-1}).
  • Condition on x0x_0: q(xt−1∣xt,x0)=q(xt∣xt−1) q(xt−1∣x0)q(xt∣x0)q(x_{t-1}\mid x_t, x_0) = \dfrac{q(x_t\mid x_{t-1})\,q(x_{t-1}\mid x_0)}{q(x_t\mid x_0)}. Legitimate because we have x0x_0 at training time, and the Markov property drops x0x_0 from the first term.
  • All three terms are known Gaussians; plug in the PDFs, drop constants, and collect powers of xt−1x_{t-1}.
  • Template-match (照葫芦画瓢) against the standard Gaussian exponent to read off: σ2=β~t=1−αˉt−11−αˉtβt,μ~t=αt(1−αˉt−1)1−αˉtxt+αˉt−1βt1−αˉtx0.\sigma^2 = \tilde\beta_t = \frac{1-\bar\alpha_{t-1}}{1-\bar\alpha_t}\beta_t,\qquad \tilde\mu_t = \frac{\sqrt{\alpha_t}(1-\bar\alpha_{t-1})}{1-\bar\alpha_t}x_t + \frac{\sqrt{\bar\alpha_{t-1}}\beta_t}{1-\bar\alpha_t}x_0.
  • At inference x0x_0 is unknown, so the model predicts it — equivalently predicts the noise ε\varepsilon via x^0=(xt−1−αˉt ε)/αˉt\hat x_0 = (x_t - \sqrt{1-\bar\alpha_t}\,\varepsilon)/\sqrt{\bar\alpha_t} — trained with MSE.

That's the car. Next time: the driver — the principled likelihood/loss derivation ("forward discipline"), worked step by step.


Notes taken from a video tutorial on DDPM (Part 3 of the series).


References

  • Ho, J., Jain, A., & Abbeel, P. (2020). Denoising Diffusion Probabilistic Models. NeurIPS 2020. arXiv:2006.11239