DDPM 基本原理讲解
DDPM 基本原理讲解(通俗版)
参考论文:Ho, Jain, Abbeel. Denoising Diffusion Probabilistic Models, NeurIPS 2020(arXiv:2006.11239)
本文只讲原理与公式,不涉及代码。公式块在 Typora / VS Code / Obsidian 等支持 LaTeX 的阅读器中可直接渲染。
写法约定:每个公式后面都跟一段”说人话”,如果只想搞懂思路,只读”说人话”部分也能通。
本文由AI生成。
0. 一个比喻:墨水滴进清水
想象一杯清水里滴了一滴墨水。
- 墨水扩散开(前向过程):墨滴逐渐散开、变淡,最后整杯水变成均匀的浅灰色——你再也看不出原来那滴墨水在哪。这个过程不需要学习,物理规律自己就会发生。
- 现在倒放这段录像(反向过程):浅灰色的水要重新聚成一滴墨水。这在现实里不可能,但如果有一个”聪明的东西”看过成千上万次扩散过程,它就能猜出墨水刚才在哪、该往哪个方向收拢。
DDPM 干的就是这件事,只不过:
| 比喻 | DDPM 里对应 |
|---|---|
| 一滴墨水 | 一张真实照片 $x_0$ |
| 墨水散开 | 一步步往照片里掺噪声 |
| 均匀的浅灰色水 | 纯随机噪声(一张雪花屏) |
| 倒放录像 | 神经网络一步步把噪声去掉 |
关键区别是:扩散模型不是真的”倒放”某一次扩散,而是学会了”从任意一杯浅灰色的水里,还原出一张说得通的图”。所以它能画出训练集中从没出现过的全新图片。
1. 读前只需知道四件事
如果你能看懂下面四条,全文就没有障碍了。
① 高斯分布 $\mathcal N(\mu, \Sigma)$
就是”钟形曲线”。$\mu$(均值)是钟的中心位置,$\Sigma$(协方差)决定钟的胖瘦——越胖表示越不确定。
写成 $\mathcal N(x;\ \mu,\ \Sigma)$ 时,分号前面 $x$ 是自变量(喂进去一个位置,吐出一个”可能性大小”),分号后面是固定参数。
一维时 $\Sigma$ 就是方差 $\sigma^2$,记 $\mathcal N(\mu, \sigma^2)$。标准差 $\sigma$ 才是噪声的实际抖动幅度。
② 竖线 $\mid$ 表示”在已知……的条件下”
$q(x_t \mid x_{t-1})$ 读作”已知 $x_{t-1}$ 时,$x_t$ 的分布”。
③ 两个会反复用到的性质
- 可加性:两个独立的零均值高斯相加,还是零均值高斯,方差直接相加。
$$\mathcal N(0, \sigma_1^2) + \mathcal N(0, \sigma_2^2) = \mathcal N(0, \sigma_1^2 + \sigma_2^2)$$
这是后面”一步跳到第 $t$ 步”的根据。 - **KL 散度 $D_{\text{KL}}$**:衡量两个分布”差多远”,恒 $\ge 0$,两个分布完全相同时等于 0。
④ 三种概率写法:$P(B)$、$P(B, C)$、$P(B \mid C)$
这三兄弟看着像,唯一区别在分母是谁。用 100 天的例子($C$ = 下雨共 30 天,$B$ = 地湿共 40 天,两者都发生共 27 天):
| 写法 | 名字 | 怎么算 | 例子 | 分母是谁 |
|---|---|---|---|---|
| $P(B)$ | 边缘概率 | 忽略 $C$,在全世界里数 $B$ | $40/100 = 0.40$ | 整个世界(100) |
| $P(B, C)$ | 联合概率 | $B$ 和 $C$ 同时成立 | $27/100 = 0.27$ | 整个世界(100) |
| $P(B \mid C)$ | 条件概率 | 世界缩小到 $C$ 里,再数 $B$ | $27/30 = 0.90$ | 只有 $C$ 那部分(30) |
三者的关系:
$$P(B \mid C) = \frac{P(B, C)}{P(C)}, \qquad P(B, C) = P(B \mid C),P(C)$$
说人话:分子都是同一个”交集” $P(B, C)$,只是除的分母不同,值就从 0.27 变成 0.90。
两个自检(能帮你判断有没有搞反):
- $P(B, C)$ 一定 $\le P(B)$ 且 $\le P(C)$:交集不可能比任何一方还大;
- $P(B \mid C) = 0.90 > P(B) = 0.40$:说明 $B$ 和 $C$ 正相关——知道下雨了,地湿的可能性大幅上升。
另外,把 $C$ 的两种情况加一遍,”加总掉” $C$ 就得到边缘概率,这叫全概率公式:
$$P(B) = P(B, C) + P(B, \text{非}C) = 0.27 + 0.13 = 0.40$$
为什么这条重要:DDPM 的贝叶斯公式里每一项都属于这三种之一,分清它属于哪一种,就知道它算不算得动:
| 写法 | DDPM 里是谁 | 算得出来吗 |
|---|---|---|
| $P(B)$ | $q(x_t)$ 边缘分布 | 算不动,要遍历所有可能的图 |
| $P(B, C)$ | $q(x_t, x_0)$ 联合分布 | 算不动 |
| $P(B \mid C)$ | $q(x_t \mid x_0)$ 条件分布 | 闭式解,一步算出来 |
说人话:在连续情形(图像)下,”数格子”要换成”积分”(或概率密度),但规则一模一样,符号不用重新学。
2. 一句话版本
扩散模型做两件事:
- 前向(加噪):拿一张真实图,用固定的、不用学的规则一步步掺噪声,$T$ 步后变成纯噪声。
- 反向(去噪):训练一个网络学会倒着走——给它一张带噪图,它猜出”噪声在哪”,减掉就干净一点。从纯噪声出发重复 $T$ 次,得到一张新图。
让它真正可行的两个数学事实:
- 前向虽然有 $T$ 步,但能一步算出来(有闭式解),训练时不用循环;
- 训练目标最后退化成一个均方误差:让网络预测”我掺进去的噪声是什么”。
3. 符号表
第一次看会觉得符号很多,其实只有 4 个是主角:$x_t$、$\beta_t$、$\bar\alpha_t$、$\epsilon_\theta$。
| 符号 | 人话解释 |
|---|---|
| $x_0$ | 原始的真实图片(像素值被缩放到 $[-1, 1]$) |
| $x_t$ | 掺了 $t$ 步噪声之后的图,$t = 1, \dots, T$ |
| $T$ | 总共掺多少步,论文取 $T = 1000$ |
| $\beta_t$ | 第 $t$ 步掺多强的噪声。人为设定的常数,不学习 |
| $\alpha_t$ | 偷懒写法,$\alpha_t = 1 - \beta_t$ |
| $\bar\alpha_t$ | 偷懒写法,$\bar\alpha_t = \alpha_1\alpha_2\cdots\alpha_t$。到第 $t$ 步还剩多少原图 |
| $q$ | 前向(加噪)分布,固定的,没有参数 |
| $p_\theta$ | 反向(去噪)分布,$\theta$ 是神经网络的参数,要学的 |
| $\epsilon$ | 随机噪声,$\epsilon \sim \mathcal N(0, I)$,就是一张雪花屏 |
| $\epsilon_\theta$ | 网络本体:输入 $(x_t, t)$,输出”我猜噪声长这样” |
记住 $\bar\alpha_t$ 就够了:它是”剩余图像比例”。$\bar\alpha_0 = 1$(全是图),$\bar\alpha_T \approx 0$(全是噪声)。
4. 前向过程:怎么把一张图毁掉
4.1 每一步具体做了什么
每一步只做一件事:把上一步的图缩小一点点,再掺一点噪声。
$$q(x_t \mid x_{t-1}) = \mathcal N\big(x_t;\ \sqrt{1 - \beta_t}, x_{t-1},\ \beta_t I\big)$$
等价的”采样写法”(把随机性单独拎出来,更好算):
$$x_t = \sqrt{1-\beta_t}, x_{t-1} + \sqrt{\beta_t}, \epsilon_{t-1}, \quad \epsilon_{t-1} \sim \mathcal N(0, I)$$
说人话:新图 = 旧图 × 一个略小于 1 的系数 + 一点点雪花。
比如 $\beta_t = 0.02$ 时,系数是 $\sqrt{0.98} \approx 0.99$,也就是旧图保留 99%,再叠加强度 $\sqrt{0.02} \approx 0.14$ 的噪声。
注意:$\beta_t$ 是方差,不是标准差。噪声实际抖动的幅度是 $\sqrt{\beta_t}$。
4.2 那个根号 $\sqrt{1-\beta_t}$ 是干嘛的?
你可能觉得”直接加噪声不就行了,乘这个系数干嘛”。答案是为了保方差。
假设图的数值方差是 1(归一化后),那么:
$$\text{Var}(x_t) = \underbrace{(1-\beta_t)}{\text{缩放后剩下}} \cdot 1 + \underbrace{\beta_t}{\text{新加进去}} = 1$$
说人话:”往 0 收缩”和”往外扩散”两股力量精确配平,所以图的数值尺度永远稳定,不会因为掺了 1000 次噪声就变得巨大无比。
这个设计叫方差保持(variance preserving)。它带来三个好处:数值稳定、不用反复归一化、而且 $T$ 步之后 $x_T$ 会自动变成标准高斯 $\mathcal N(0, I)$——正好可以当生成时的起点。
另一种常见写法是 $x_t = x_{t-1} + \sigma_t \epsilon$(不做收缩,叫”方差爆炸”,Song & Ermon 的 score-based 模型用这种)。DDPM 选了带根号的这种,纯粹是因为闭式解更干净。
4.3 走后门:不用真的走 $t$ 步
如果要造一个”掺了 500 步”的训练样本,难道要真跑 500 次吗?不用。
关键技巧:每一步都是”乘以一个数 + 加一个高斯”,而高斯的线性组合还是高斯。所以掺 500 次的结果,等价于一次缩放 + 一次加噪。
用数学归纳法推一遍(记 $\alpha_t = 1 - \beta_t$,$\bar\alpha_t = \alpha_1\cdots\alpha_t$):
第 1 步:单步定义
$$x_t = \sqrt{\alpha_t}, x_{t-1} + \sqrt{1-\alpha_t},\epsilon_{t-1}$$
第 2 步:假设上一步已经能一步写出(归纳假设)
$$x_{t-1} = \sqrt{\bar\alpha_{t-1}}, x_0 + \sqrt{1-\bar\alpha_{t-1}},\bar\epsilon_{t-1}$$
第 3 步:代入,展开
$$x_t = \sqrt{\bar\alpha_t}, x_0 + \underbrace{\sqrt{\alpha_t}\sqrt{1-\bar\alpha_{t-1}},\bar\epsilon_{t-1}}{\text{噪声 A}} + \underbrace{\sqrt{1-\alpha_t},\epsilon{t-1}}_{\text{噪声 B}}$$
第 4 步:噪声 A 和 B 是两个独立的零均值高斯,可以合并成一个。方差相加:
$$\alpha_t(1-\bar\alpha_{t-1}) + (1-\alpha_t) = \alpha_t - \bar\alpha_t + 1 - \alpha_t = 1 - \bar\alpha_t$$
(因为 $\alpha_t \bar\alpha_{t-1} = \bar\alpha_t$。)
第 5 步:于是
$$\boxed{x_t = \sqrt{\bar\alpha_t}, x_0 + \sqrt{1 - \bar\alpha_t},\epsilon, \quad \epsilon \sim \mathcal N(0, I)}$$
说人话:不管你要第几步的图,都可以用原图和一张雪花屏直接按比例混合出来,一步搞定。这就是”闭式解”。
自检(确认没推错):
- 若 $\text{Var}(x_0) = 1$,则 $\bar\alpha_t + (1 - \bar\alpha_t) = 1$,方差守恒 ✓
- $t = T$ 时 $\bar\alpha_T \approx 0$,于是 $x_T \approx \epsilon$,整张图就是纯噪声 ✓
⚠️ 两个常见误解:
- 这里的 $\epsilon$ 不是任何一步的 $\epsilon_{t-1}$,它是所有中间步噪声”合并等效”出来的新噪声,只是分布相同。
- 这是分布等价,不是”逐样本相等”。逐步迭代 500 次得到的图,和用闭式一步采出的图,是同分布的两个不同样本。训练时我们只关心分布,够用了。
4.4 $\bar\alpha_t$ 到底意味着什么
再看一眼这条核心公式:
$$x_t = \underbrace{\sqrt{\bar\alpha_t}}{\text{图的权重}}, x_0 + \underbrace{\sqrt{1 - \bar\alpha_t}}{\text{噪声的权重}}, \epsilon$$
| 时刻 | $\bar\alpha_t$ | 图的样子 | 网络要干的事 |
|---|---|---|---|
| $t$ 小 | 接近 1 | 几乎还是原图 | 预测一点点残余噪声(很简单) |
| $t$ 中等 | 0.5 左右 | 图噪声各半 | 预测中等强度的噪声 |
| $t$ 大 | 接近 0 | 几乎全是雪花 | 预测的东西几乎就是整张图(很难) |
所以不同 $t$ 是完全不同难度的任务。 网络必须知道”现在进行到第几步”,否则它不知道该猜多大强度的噪声——这就是时间步 $t$ 要作为输入喂给网络的原因。
4.5 噪声的节奏:$\beta_t$ 的具体公式
先说清楚:$\beta_t$ 是人设计的常数,不是学出来的。而且只要给出 $\beta_t$,其余所有量都能推出来:
$$\alpha_t = 1 - \beta_t, \qquad \bar\alpha_t = \prod_{s=1}^{t} \alpha_s$$
下面给出几种常见调度的具体公式。
① 线性调度(DDPM 论文默认)
$$\beta_t = \beta_1 + (\beta_T - \beta_1),\frac{t-1}{T-1}, \qquad t = 1, 2, \dots, T$$
$$\beta_1 = 1\times10^{-4}, \qquad \beta_T = 2\times10^{-2}, \qquad T = 1000$$
代入数字就是:
$$\boxed{\beta_t = 10^{-4} + 1.99\times10^{-2}\cdot \frac{t-1}{999}}$$
举例:$\beta_1 = 0.0001$,$\beta_{500} \approx 0.0100$,$\beta_{1000} = 0.02$。
⚠️ 下标约定要注意:论文用 $t = 1 \dots T$,代码(如 diffusers)通常用 $t = 0 \dots T-1$,此时
$$\beta_t = \beta_{\text{start}} + (\beta_{\text{end}} - \beta_{\text{start}}),\frac{t}{T-1}$$
等价于直接torch.linspace(1e-4, 2e-2, 1000)。两者只是编号差 1,数值序列完全相同。
② scaled linear(Stable Diffusion 用)
不在线性空间插值,而是在平方根空间插值后再平方:
$$\boxed{\beta_t = \left(\sqrt{\beta_{\text{start}}} + \big(\sqrt{\beta_{\text{end}}} - \sqrt{\beta_{\text{start}}}\big),\frac{t}{T-1}\right)^2}$$
Stable Diffusion 1.x 取 $\beta_{\text{start}} = 0.00085$,$\beta_{\text{end}} = 0.012$,$T = 1000$。末端 $\beta$ 更小,是因为它工作在 VAE 压缩后的潜空间里,噪声强度需要相应调小。
③ cosine(Improved DDPM,Nichol & Dhariwal 2021)
它**不直接定义 $\beta_t$**,而是先定好 $\bar\alpha_t$,再反推每一步的 $\beta_t$:
$$\bar\alpha_t = \frac{f(t/T)}{f(0)}, \qquad f(u) = \cos^2!\left(\frac{u + s}{1 + s}\cdot\frac{\pi}{2}\right), \quad s = 0.008$$
$$\beta_t = 1 - \frac{\bar\alpha_t}{\bar\alpha_{t-1}}, \qquad \text{并裁剪 } \beta_t \le 0.999$$
裁剪是为了防止最后几步 $\beta_t \to 1$ 引发数值爆炸。偏移量 $s = 0.008$ 是为了让 $t$ 很小时 $\beta_t$ 不至于太小、避免”开头几乎没加噪”的浪费。
④ sigmoid(GeoDiff 用)
$$\beta_t = \sigma(u_t),(\beta_{\text{end}} - \beta_{\text{start}}) + \beta_{\text{start}}, \qquad u_t \text{ 在 } [-6,,6] \text{ 上均匀取值}$$
其中 $\sigma$ 是 sigmoid 函数,所以曲线呈 S 形:两头慢、中间快。
几种调度下 $\bar\alpha_t$ 的实际数值(近似)
| $t/T$ | 线性 $\bar\alpha_t$ | cosine $\bar\alpha_t$ |
|---|---|---|
| 0 | 1 | 1 |
| 0.25 | 0.52 | 0.85 |
| 0.5 | 0.078 | 0.49 |
| 0.75 | 0.0034 | 0.14 |
| 1 | 0.00004 | 0 |
说人话:线性调度在中段掉得太快——走到一半时原图只剩 7.8%,后面几百步几乎都在对着纯噪声做无用功,浪费了步数。cosine 让”还剩多少图”下降得更均匀,每一步都更有信息量,所以在步数较少(比如只采 50 步)时优势明显。
无论用哪种,唯一的要求只有一条:**掺到最后 $\bar\alpha_T \approx 0$**,让 $x_T$ 足够接近标准高斯,反向才能直接从 $\mathcal N(0, I)$ 起步。
5. 反向过程:怎么把图救回来
5.1 想要什么,能算什么
我们想要的是:给定一团噪声 $x_t$,还原出上一步 $x_{t-1}$,也就是 $q(x_{t-1} \mid x_t)$。
问题是:这个分布要”知道全世界的图片长什么样”才算得出来,算不动。
所以做法是:用一个神经网络去逼近它。
$$p_\theta(x_{t-1} \mid x_t) = \mathcal N\big(x_{t-1};\ \mu_\theta(x_t, t),\ \Sigma_\theta(x_t, t)\big)$$
整条反向链从纯噪声出发:
$$p_\theta(x_{0:T}) = p(x_T) \prod_{t=1}^{T} p_\theta(x_{t-1} \mid x_t), \qquad p(x_T) = \mathcal N(0, I)$$
说人话:起点 $p(x_T)$ 没有参数,就是标准高斯。所以生成时不需要任何输入,随便采一团雪花屏就能开始。这是扩散模型”从噪声凭空画图”的来源。
5.2 为什么敢用高斯去拟合?
真实的 $q(x_{t-1} \mid x_t)$ 是个复杂得多峰的分布,严格来说不是高斯。
但有个经典结论:当每步的扰动 $\beta_t$ 足够小时,扩散过程的逆过程也(近似)是高斯的。$T = 1000$ 步、每步只动一点点,这个近似非常够用。
说人话:每一步只做极小的修正,那么”从上一步到这一步”这件事的形状就很简单,简单到用一条钟形曲线就能描出来。
这也解释了为什么扩散模型需要很多步:步数越多,每步的修正越小,高斯近似越准。
5.3 训练时的”标准答案”:后验
训练时我们有个作弊器——**$x_0$ 是已知的**(就是训练样本本身)。
一旦把 $x_0$ 也给定,$q(x_{t-1} \mid x_t)$ 就变成可以精确算出来的高斯了:
$$\boxed{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 I\big)}$$
$$\tilde\mu_t(x_t, x_0) = \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$$
$$\tilde\beta_t = \frac{1 - \bar\alpha_{t-1}}{1 - \bar\alpha_t},\beta_t$$
5.3.1 这两条公式是怎么算出来的
方法就一句:贝叶斯公式 + 两个高斯相乘 + 配方。最容易被跳过去、也最容易卡住的是第一步,这里拆成四小步慢慢来。
第 0 步:先想清楚为什么要搬出贝叶斯公式。
我们手上有的是加噪规则 $q(x_t \mid x_{t-1})$——这是我们自己定的,闭着眼都能算。
我们想要的是去噪分布 $q(x_{t-1} \mid x_t)$——箭头是反的,直接算不出来。
贝叶斯公式唯一的作用就是把反着的箭头翻成正着的:
$$P(A \mid B) = \frac{P(B \mid A),P(A)}{P(B)}$$
说人话:反着问 = 正着推 × 先验 ÷ 归一化常数。
一个结构完全相同的日常例子:
| 下雨 / 地湿 | DDPM 对应 | |
|---|---|---|
| 正着推(已知) | $P(\text{地湿} \mid \text{下雨}) = 0.9$ | $q(x_t \mid x_{t-1})$ |
| 反着推(想求) | $P(\text{下雨} \mid \text{地湿}) = ?$ | $q(x_{t-1} \mid x_t)$ |
| 先验(已知) | $P(\text{下雨}) = 0.3$ | $q(x_{t-1} \mid x_0)$,4.3 节闭式解 |
| 归一化(可扔) | $P(\text{地湿}) = 0.4$ | $q(x_t \mid x_0)$,不含 $x_{t-1}$ |
代入:$P(\text{下雨} \mid \text{地湿}) = 0.9 \times 0.3 ,/, 0.4 = 0.675$。
第 1 步:写成”带条件”的贝叶斯公式。
直接套 $P(A \mid B)$ 还不够,因为 DDPM 这里**多了一个条件 $x_0$**(训练时原图摆在眼前)。所以要用条件版:
$$P(A \mid B, C) = \frac{P(B \mid A, C),P(A \mid C)}{P(B \mid C)}$$
说人话:$C$ 是”额外已知的背景信息”,全程不动。左边条件里挂着 $C$,右边每一项就都得跟着挂上 $C$ ——就这么简单,没有别的花样。
它怎么来的?把联合概率沿链条拆开再相除,$P(C)$ 上下约掉:
$$P(A \mid B, C) = \frac{P(A, B, C)}{P(B, C)} = \frac{P(B \mid A, C),P(A \mid C),\cancel{P(C)}}{P(B \mid C),\cancel{P(C)}} = \frac{P(B \mid A, C),P(A \mid C)}{P(B \mid C)}$$
三个槽位代入:
| 槽位 | DDPM 里代入 | 状态 |
|---|---|---|
| $A$ | $x_{t-1}$(上一步的图) | 未知,正是要求它的分布 |
| $B$ | $x_t$(当前带噪图) | 已知,手上就拿着 |
| $C$ | $x_0$(原始清晰图) | 训练时已知,是”作弊信息” |
$$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)}$$
为什么非挂 $x_0$ 不可?这是全篇最关键的一处动机。
不挂的话,公式长这样:
$$q(x_{t-1} \mid x_t) = \frac{q(x_t \mid x_{t-1}),q(x_{t-1})}{q(x_t)}$$
其中的 $q(x_{t-1})$ 和 $q(x_t)$ 是边缘分布——“不管原图是哪张,第 $t$ 步的图长什么样”,要遍历所有可能的图才能算,算不动(见 1 节 ④)。一旦挂上 $x_0$,先验和分母就都变成了条件分布,而条件分布全都有 4.3 节的闭式解。
挂 $x_0$ 的真正作用,是把算不动的量换成算得动的量——不是把问题变复杂,恰恰是让它变得能算。
代价是:我们求出来的分布多了一个条件 $x_0$,只在训练时(原图摆在眼前)才成立。生成时怎么办,见第 6 节。
第 2 步:用马尔可夫性擦掉一个条件。
分子第一项条件里同时有 $x_{t-1}$ 和 $x_0$,但既然 $x_{t-1}$ 已经给定,$x_0$ 就是多余信息——这一步掺多少噪声只取决于现在这张图,跟最初那张图无关。这就是马尔可夫性的定义:
$$q(x_t \mid x_{t-1}, x_0) = q(x_t \mid x_{t-1})$$
说人话:已经知道”下雨了”,再告诉你”昨天也下过雨”,也改变不了”今天地湿不湿”。
第 3 步:把分母扔掉。
分母 $q(x_t \mid x_0)$ 里根本没有 $x_{t-1}$。而我们求的是”关于 $x_{t-1}$ 的分布”,关心的是曲线峰在哪、有多胖;分母对每一个 $x_{t-1}$ 都乘上同一个数,只改变整体高度、不改变形状,而分布最后反正要归一化到积分为 1,高度会自动补回来。所以先写成正比号,力气全花在分子上:
$$q(x_{t-1} \mid x_t, x_0) ;\propto; \underbrace{q(x_t \mid x_{t-1})}{\mathcal N(\sqrt{\alpha_t},x{t-1},\ \beta_t I)} ;\cdot; \underbrace{q(x_{t-1} \mid x_0)}{\mathcal N(\sqrt{\bar\alpha{t-1}},x_0,\ (1-\bar\alpha_{t-1}) I)}$$
右边两项都是前面已经算出来过的高斯:一个是 4.1 节的单步定义,一个是 4.3 节的闭式解。至此”未知”的东西全部消掉了。
常见疑问:为什么左边是 $q$ 而不是 $p_\theta$?
因为这一步描述的是”训练数据是怎么被破坏的”(前向),完全由我们设定的 $\beta_t$ 决定,没有任何可学习参数,所以是 $q$。真正的网络 $p_\theta(x_{t-1} \mid x_t)$ 要到第 6 节才登场,登场方式就是”去拟合这个 $q$”。
第 4 步:用上”两个高斯相乘”这个小工具。
$$\mathcal N(x; a, A)\cdot \mathcal N(x; b, B) \propto \mathcal N!\left(x;\ \frac{a/A + b/B}{1/A + 1/B},\ \frac{1}{1/A + 1/B}\right)$$
说人话:两个高斯相乘还是高斯。新的精度(方差的倒数)等于两个精度相加;新的均值是两个均值的精度加权平均。信息越多 → 精度越高 → 方差越小,完全符合直觉。
第 5 步:对指数部分按 $x_{t-1}$ 配方。
分子的指数部分(去掉 $-1/2$)是:
$$\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}}$$
按 $x_{t-1}$ 展开并收集同类项:
- $x_{t-1}^2$ 的系数:$\dfrac{\alpha_t}{\beta_t} + \dfrac{1}{1-\bar\alpha_{t-1}} = \dfrac{1}{\tilde\beta_t}$(精度相加)
- $x_{t-1}$ 的系数:$-2\left(\dfrac{\sqrt{\alpha_t}x_t}{\beta_t} + \dfrac{\sqrt{\bar\alpha_{t-1}}x_0}{1-\bar\alpha_{t-1}}\right) = -\dfrac{2\tilde\mu_t}{\tilde\beta_t}$
第 6 步:解出来。
$$\frac{1}{\tilde\beta_t} = \frac{\alpha_t}{\beta_t} + \frac{1}{1-\bar\alpha_{t-1}} ;\Longrightarrow; \tilde\beta_t = \frac{\beta_t(1-\bar\alpha_{t-1})}{\alpha_t(1-\bar\alpha_{t-1}) + \beta_t} = \frac{1-\bar\alpha_{t-1}}{1-\bar\alpha_t}\beta_t$$
$$\tilde\mu_t = \tilde\beta_t\left(\frac{\sqrt{\alpha_t},x_t}{\beta_t} + \frac{\sqrt{\bar\alpha_{t-1}},x_0}{1-\bar\alpha_{t-1}}\right) = \frac{\sqrt{\alpha_t}(1-\bar\alpha_{t-1}),x_t + \sqrt{\bar\alpha_{t-1}},\beta_t,x_0}{1-\bar\alpha_t}$$
(化简用到 $\alpha_t(1-\bar\alpha_{t-1}) + \beta_t = \alpha_t - \bar\alpha_t + 1 - \alpha_t = 1 - \bar\alpha_t$。)
代入一组数字看效果($\bar\alpha_{t-1} = 0.8$,$\alpha_t = 0.9$,$\beta_t = 0.1$,$x_t = 0.5$,$x_0 = 0.3$):
$$\tilde\mu_t = 0.678 \times 0.5 ;+; 0.319 \times 0.3 = 0.435, \qquad \tilde\beta_t = \frac{0.1 \times 0.2}{0.28} = 0.071$$
说人话:
- $\tilde\mu_t$ 落在 $x_t$ 和 $x_0$ 之间(0.435 介于 0.5 和 0.3 之间),是两个信息的加权折中;
- 两个权重之和 $\approx 1$,且通常 $x_t$ 那一项占大头——因为单步噪声 $\beta_t$ 很小,$x_t$ 对 $x_{t-1}$ 的信息相当精确;
- $\tilde\beta_t = 0.071 < \beta_t = 0.1$:多知道一个 $x_0$,不确定性就下降,这符合”信息越多越确定”。
两个边界情形可以验证公式没错:
- $t = 1$ 时:$\bar\alpha_0 = 1$,于是 $\tilde\beta_1 = 0$、$\tilde\mu_1 = x_0$——知道 $x_0$ 就等于知道 $x_0$,方差为 0,完全确定;
- $t$ 很大时:$\bar\alpha_{t-1} \to 0$,$\tilde\mu_t \to \sqrt{\alpha_t},x_t$,$x_0$ 的权重趋于 0——此时 $x_0$ 已经帮不上什么忙了。
说人话:训练时 $x_0$ 摆在眼前,所以”上一步应该长什么样”有个精确答案 $\tilde\mu_t$。学习问题因此变得非常朴素:让网络的输出去拟合这个答案。
生成时 $x_0$ 当然不知道——那正是网络要替我们猜的东西。
6. 训练目标:为什么最后只是”猜噪声”
这一节是全篇最难的地方。我们慢慢来。
6.1 我们真正想要的是什么
训练生成模型,最正统的目标是最大似然:让模型给真实图片打高分,也就是最大化 $\log p_\theta(x_0)$。
$$\text{想算:}\quad p_\theta(x_0) = \int p_\theta(x_0, x_{1:T}),dx_{1:T}$$
问题来了:这个积分要对 $x_1, \dots, x_T$ 全都积掉。在 DDPM 里是 $1000$ 步 × 每步几千维——天文数字,根本算不动。
6.2 算不出来怎么办 → ELBO
算不出精确值,就退而求其次:**算一个”保底值”**。这就是 ELBO。
ELBO = Evidence Lower BOund = 证据下界(论文里也叫 VLB,变分下界)。
“证据”指的是边际似然 $p_\theta(x_0)$;”下界”是说 ELBO 永远 $\le \log p_\theta(x_0)$,够不着,只能从下面往上顶。
它们之间只差一个非负的间隙:
$$\log p_\theta(x_0) = \text{ELBO} + \underbrace{D_{\text{KL}}\big(q ,\Vert, p_\theta\big)}_{\text{间隙,恒} \ge 0} \quad\Longrightarrow\quad \text{ELBO} \le \log p_\theta(x_0)$$
说人话:真实值 = 保底值 + 一个永远为正的误差。所以把保底值往上推,真实值必然也被往上推(至少不会更低)。这就是”优化下界”的合法性来源。
顺带一提:这个间隙恰好是”我们假设的 $q$”和”真实后验”之间的差距。当 $q$ 正好等于真实后验时,间隙为 0,下界贴合。
6.3 ELBO 是怎么来的
只用一步 Jensen 不等式:因为 $\log$ 是凹函数,所以 $\log \mathbb E[Y] \ge \mathbb E[\log Y]$。把 $\log$ 从期望外面挪到里面,积分就落在能算的东西上了。
$$\log p_\theta(x_0) ;\ge; \mathbb E_{q}!\left[\log \frac{p_\theta(x_{0:T})}{q(x_{1:T} \mid x_0)}\right] =: \text{ELBO}$$
等价地,写成”上界形式”(注意是最小化 $-\log p$):
$$-\log p_\theta(x_0) \le \mathbb E_{q}!\left[-\log \frac{p_\theta(x_{0:T})}{q(x_{1:T} \mid x_0)}\right] =: L_{\text{vlb}}$$
通用形式(换个符号更好认):
$$\text{ELBO} = \mathbb E_q\big[\log p_\theta(x \mid z)\big] - D_{\text{KL}}\big(q(z \mid x) ,\Vert, p(z)\big)$$
说人话:ELBO 有两项在打架——
- 第一项”把图还原得好不好”(越大越好);
- 第二项”编码器输出是否贴近先验”(越小越好)。
如果你学过 VAE,这就是那句”重构损失 − KL“,一模一样的东西。
6.4 摊开:ELBO 变成一堆 KL
把 ELBO 按马尔可夫链展开,并把算不出来的项换成 5.3 节那个”标准答案”后验:
$$L_{\text{vlb}} = \underbrace{D_{\text{KL}}\big(q(x_T \mid x_0) ,\Vert, p(x_T)\big)}{L_T,\ \text{无参数,可忽略}} ;+; \sum{t=2}^{T} \underbrace{D_{\text{KL}}\big(q(x_{t-1} \mid x_t, x_0) ,\Vert, p_\theta(x_{t-1} \mid x_t)\big)}{L{t-1}} ;-; \underbrace{\log p_\theta(x_0 \mid x_1)}_{L_0}$$
说人话:总目标 = 每一步“标准答案的去噪分布”和”模型预测的去噪分布”之间的差距之和。
也就是说:每一步都要去噪去得和理论上一样好。顺带说:这也解释了为什么 DDPM 可以看成 VAE——它是一个有 $T$ 层、编码器被钉死不动的层次化 VAE:
| VAE 术语 | DDPM 中对应 |
|---|---|
| 输入 $x$ | $x_0$ |
| 编码器 $q(z \mid x)$ | 前向加噪,固定无参数 |
| 隐变量 $z$ | $x_1, \dots, x_T$ |
| 先验 $p(z)$ | $p(x_T) = \mathcal N(0, I)$ |
| 解码器 $p_\theta(x \mid z)$ | 反向去噪,要学的 |
| 优化目标 | ELBO |
6.5 再化简:KL 变成”均值的平方误差”
两个方差已知的高斯之间的 KL 有闭式解。论文把模型的方差直接固定成常数 $\Sigma_\theta = \sigma_t^2 I$(取 $\sigma_t^2 = \beta_t$ 或 $\tilde\beta_t$ 都行),于是 KL 里只剩下均值在打架:
$$L_{t-1} = \mathbb E_{q}!\left[\frac{1}{2\sigma_t^2},\big\Vert \tilde\mu_t(x_t, x_0) - \mu_\theta(x_t, t) \big\Vert^2\right] + C$$
说人话:目标已经很干净了——**让网络预测的均值,去贴近那个算得出来的标准答案 $\tilde\mu_t$**。就是个回归问题。
6.6 最后一步转折:别预测均值了,改预测噪声
直接让网络输出 $\mu_\theta$ 效果一般。论文的巧妙做法是:把 $x_0$ 从标准答案里消掉。
由闭式解反解出 $x_0$:
$$x_0 = \frac{1}{\sqrt{\bar\alpha_t}}\big(x_t - \sqrt{1 - \bar\alpha_t},\epsilon\big)$$
代进 $\tilde\mu_t$ 整理后,会发现标准答案可以写成”只含 $x_t$ 和 $\epsilon$”的形式——所以网络只要预测 $\epsilon$ 就够了:
$$\mu_\theta(x_t, t) = \frac{1}{\sqrt{\alpha_t}}\left(x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}},\epsilon_\theta(x_t, t)\right)$$
代回损失,得到:
$$L_{t-1} - C = \frac{\beta_t^2}{2,\sigma_t^2,\alpha_t,(1 - \bar\alpha_t)}\ \mathbb E_{x_0, \epsilon}!\left[\big\Vert \epsilon - \epsilon_\theta(x_t, t) \big\Vert^2\right]$$
说人话:每一步的损失,本质上就是**”我掺进去的噪声”和”网络猜的噪声”之间的均方误差**,只是前面挂了个只跟 $t$ 有关的权重系数。
6.7 最终用的:把权重丢掉
论文发现,把这个权重系数直接扔了效果反而更好:
$$\boxed{L_{\text{simple}} = \mathbb E_{t,, x_0,, \epsilon}\left[\big\Vert \epsilon - \epsilon_\theta(\underbrace{\sqrt{\bar\alpha_t},x_0 + \sqrt{1 - \bar\alpha_t},\epsilon}_{=\ x_t},\ t) \big\Vert^2\right]}$$
其中 $t \sim \text{Uniform}{1,\dots,T}$,$x_0$ 来自数据集,$\epsilon \sim \mathcal N(0, I)$。
为什么要扔?那个权重会让高噪声的步($t$ 大)被压得很小,模型就不太重视”从纯噪声开始”这个最难也最关键的阶段。扔掉后所有噪声水平一视同仁,生成的图质量(FID)更好。
说人话:DDPM 的训练目标,说到底就一句——
给网络一张掺了噪声的图,让它猜”掺进去的噪声是什么”,猜错了就按平方误差罚它。
一个生成模型,训练竟然只是一个去噪回归问题。这是它最反直觉、也最优雅的地方。
严格说,扔掉权重后已经不再是”纯粹的似然下界”了。论文也提供了折中方案 $L_{\text{hybrid}} = L_{\text{simple}} + \lambda L_{\text{vlb}}$,供需要精确似然的场景使用。
7. 完整流程(就这两张清单)
训练(重复到收敛)
- 从数据集取一张真实图 $x_0$;
- 随机抽一个时间步 $t \sim \text{Uniform}{1,\dots,T}$;
- 随机采一张噪声 $\epsilon \sim \mathcal N(0, I)$;
- 一步造出带噪图:$x_t = \sqrt{\bar\alpha_t},x_0 + \sqrt{1-\bar\alpha_t},\epsilon$;
- 让网络猜噪声 $\epsilon_\theta(x_t, t)$,按 $|\epsilon - \epsilon_\theta|^2$ 更新参数。
注意:同一个 batch 里每个样本的 $t$ 都是各自随机的,网络在所有噪声水平上被反复训练,参数共享。
生成(采样)
- 随便采一团噪声 $x_T \sim \mathcal N(0, I)$;
- 对 $t = T, T-1, \dots, 1$ 反复执行:
$$x_{t-1} = \frac{1}{\sqrt{\alpha_t}}\left(x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}},\epsilon_\theta(x_t, t)\right) + \sigma_t z, \quad z \sim \mathcal N(0, I)$$
最后一步($t = 1$)时取 $z = 0$;
3. 输出 $x_0$。
说人话:每一步就是”猜噪声 → 按比例减掉 → 再补一点点随机“。
补的那点随机是为了保持多样性(两次生成不一样)。如果全部去掉随机项,就变成了确定性的 DDIM。
8. 三种等价说法(换个马甲你也要认得)
$\epsilon$、$x_0$、score 三者之间只差线性变换,可以互换:
| 说法 | 网络输出什么 | 与 $\epsilon_\theta$ 的关系 |
|---|---|---|
| 预测噪声(DDPM 默认) | $\epsilon_\theta(x_t, t)$ | — |
| 预测原图 | $\hat x_0(x_t, t)$ | $\hat x_0 = \dfrac{x_t - \sqrt{1-\bar\alpha_t},\epsilon_\theta}{\sqrt{\bar\alpha_t}}$ |
| 预测 score(梯度) | $s_\theta(x_t, t)$ | $s_\theta = -\dfrac{\epsilon_\theta}{\sqrt{1 - \bar\alpha_t}}$ |
第三条特别重要:它说明 DDPM 本质上在学数据分布的梯度场,从而和 Song & Ermon 的 score-based 模型(NCSN / 退火 Langevin 采样)统一到同一框架下。带随机项的采样公式,本质上就是一步 Langevin 动力学。
再往后,SD3、Flux 这一代用的是 flow matching:预测对象换成”从噪声走向数据的速度场 $v$”,路径从弯的改成直的。但”加噪 → 预测 → 回退”这套骨架没变。
9. 论文里的几个关键设计
| 设计 | 做法 | 为什么 |
|---|---|---|
| 预测 $\epsilon$ 而不是 $\mu$ | 让网络猜噪声 | 数值范围稳定,等价于重加权后的 VLB,效果更好 |
| 方差固定不学 | $\Sigma_\theta = \beta_t I$ 或 $\tilde\beta_t I$ | 学方差收益极小且训练不稳 |
| 丢掉损失权重 | 用 $L_{\text{simple}}$ | 各噪声水平一视同仁,FID 更好 |
| 把 $t$ 喂给网络 | 正弦编码 → MLP → 注入每个残差块 | 同一套权重要处理 1000 种不同难度的任务 |
| 主干用 U-Net | 编码器-解码器 + 跳跃连接 + 自注意力 | 去噪是像素级任务,要保细节又要顾全局 |
| 超参 | $T = 1000$,$\beta$ 从 $10^{-4}$ 线性到 $2\times10^{-2}$,Adam(lr $2\times10^{-4}$)+ EMA(0.9999) | EMA 对生成质量帮助明显 |
成果:无条件 CIFAR-10 上 FID 3.17、Inception Score 9.46,首次让扩散类模型的样本质量超过当时的 GAN,而且训练更稳、覆盖的模式更全。这直接引爆了后来的 Stable Diffusion 等一系列工作。
10. 为什么”学会去噪”就等于”学会生成”?
三层递进的直觉:
去噪逼着你理解数据。要从一堆雪花里精确把噪声减掉,网络必须知道”真实的图长什么样”。1000 个噪声水平全都做对,等于把数据分布从粗到细学了一遍。
把难题拆成简单题。直接学”噪声 → 图像”的映射极难;但”预测这一步掺了什么噪声”在 $\beta_t$ 很小时,几乎是道线性回归题。$T$ 步串起来,就走完了从噪声到图像的漫长旅程。
梯度场视角。$\epsilon_\theta$ 乘个系数就是数据分布的梯度,采样就是顺着梯度从”高熵的噪声区”走向”高概率的真实图区”。这和能量模型、Langevin 采样是一脉相承的。
跟其他生成模型比:
| 范式 | 思路 | 主要短板 |
|---|---|---|
| GAN | 生成器与判别器对抗 | 训练不稳、模式坍塌 |
| VAE | 一步编码 + 似然下界 | 高斯解码导致图偏模糊 |
| 自回归 | 逐像素 / 逐 token 生成 | 必须串行,高分辨率极慢 |
| 扩散 | 拆成 $T$ 步去噪 + 变分下界 | 采样要跑几百上千次网络,慢 |
扩散模型的胜利,本质是用训练的稳定性换来了推理的代价。后来 DDIM、DPM-Solver、LCM、一致性模型、flow matching 这一大批工作,都是在还这笔”推理债”。
11. 常见问题 FAQ
Q1:为什么叫”扩散”模型?
借用了物理里墨水在水里扩散的比喻。数学上它确实对应一个随机微分方程描述的扩散过程,但你可以只把它理解成”逐渐加噪”。
Q2:网络为什么还要把 $t$ 喂进去?
因为第 10 步和第 900 步要猜的噪声强度完全不一样。不给 $t$,网络就不知道该猜多大。
Q3:采样时为什么要加那个随机项 $\sigma_t z$?不加行不行?
不加也可以,那就是 DDIM(确定性采样),反而更快、步数更少。加了的话每一步保留随机性,样本多样性通常更好。DDPM 原版是加的。
Q4:训练用的噪声和闭式解里的噪声是同一个吗?
训练时你亲自采一个 $\epsilon$,再用闭式解算出 $x_t$,然后把 $\epsilon$ 当标签监督网络——两者必须严格配对。闭式解里的 $\epsilon$ 只是”所有中间步噪声合并后的等效噪声”,它不等于任何单独一步的 $\epsilon_{t-1}$。
Q5:为什么不直接用闭式解反着算出 $x_0$ 就完事?
因为反解 $x_0$ 需要知道 $\epsilon$,而 $\epsilon$ 恰恰是未知的(生成时没人告诉你掺了什么噪声)。网络的作用就是**猜这个 $\epsilon$**。
Q6:生成的图是不是把训练集的图背下来了?
不是。网络学到的是”如何从噪声里还原出一张合理图”的能力,起点是全新的随机噪声,所以每次生成都不一样。当然,如果训练集很小或重复很多次,确实会出现记忆现象,但那是过拟合,不是原理。
Q7:为什么 $T$ 要 1000 这么大?
为了让每一步的改动足够小,这样”逆过程也是高斯”的近似才成立、训练也更容易。代价是采样慢——后来的加速采样器就是来解决这个的。
Q8:ELBO 是真实似然的近似值吗?
不是近似,是严格下界:真实值 = ELBO + 一个恒为正的 KL 间隙。ELBO 永远只低不高。
Q9:为什么训练损失里要对 $t$ 随机采样,而不是固定 $t$?
因为要覆盖所有噪声水平。随机采样等价于让网络在每个难度上都被训练到,最后才每个 $t$ 都能去噪。
Q10:前向过程为什么不用学习?
因为它是我们自己定义的——“训练数据是怎么被破坏的”这件事由我们说了算,$\beta_t$ 是人为设定的常数。所有需要学的东西都在反向过程里。
Q11:为什么起始分布可以随便用 $\mathcal N(0, I)$?
因为精心设计了 $\beta_t$ 使得 $\bar\alpha_T \approx 0$,前向走到最后就是标准高斯。所以反向从标准高斯出发,两边对得上。
12. 公式速查表
前向(固定,无需学习)
$$q(x_t \mid x_{t-1}) = \mathcal N\big(\sqrt{1-\beta_t},x_{t-1},\ \beta_t I\big), \qquad \alpha_t = 1-\beta_t,\ \bar\alpha_t = \prod_{s=1}^t \alpha_s$$
$$q(x_t \mid x_0) = \mathcal N\big(\sqrt{\bar\alpha_t},x_0,\ (1-\bar\alpha_t)I\big)$$
$$x_t = \sqrt{\bar\alpha_t},x_0 + \sqrt{1-\bar\alpha_t},\epsilon$$
后验(训练时的标准答案)
$$q(x_{t-1}\mid x_t, x_0) = \mathcal N\left(\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,\ \frac{1-\bar\alpha_{t-1}}{1-\bar\alpha_t}\beta_t, I\right)$$
反向(要学的)
$$p_\theta(x_{t-1}\mid x_t) = \mathcal N\left(\frac{1}{\sqrt{\alpha_t}}\Big(x_t - \frac{\beta_t}{\sqrt{1-\bar\alpha_t}}\epsilon_\theta(x_t,t)\Big),\ \sigma_t^2 I\right)$$
训练目标
$$L_{\text{simple}} = \mathbb E_{t,x_0,\epsilon}\left[\big\Vert \epsilon - \epsilon_\theta\big(\sqrt{\bar\alpha_t}x_0 + \sqrt{1-\bar\alpha_t}\epsilon,\ t\big)\big\Vert^2\right]$$
采样迭代
$$x_{t-1} = \frac{1}{\sqrt{\alpha_t}}\left(x_t - \frac{\beta_t}{\sqrt{1-\bar\alpha_t}}\epsilon_\theta(x_t,t)\right) + \sigma_t z$$
等价关系
$$\hat x_0 = \frac{x_t - \sqrt{1-\bar\alpha_t},\epsilon_\theta}{\sqrt{\bar\alpha_t}}, \qquad \nabla_x \log q_t(x) \approx -\frac{\epsilon_\theta(x_t, t)}{\sqrt{1-\bar\alpha_t}}$$
13. 记不住的时候,只留这三句
- 前向加噪有闭式解 —— $x_t$ 能由 $x_0$ 一步算出,训练不必循环。
- 训练只做噪声回归 —— 变分下界一路化简,最后就是 $|\epsilon - \epsilon_\theta|^2$。
- 推理靠迭代回退 —— 从纯噪声出发,反复”猜噪声 → 减掉一点 → 补点随机”,直到 $x_0$。
参考
- Ho, Jain, Abbeel. Denoising Diffusion Probabilistic Models. NeurIPS 2020. arXiv:2006.11239
- Sohl-Dickstein et al. Deep Unsupervised Learning using Nonequilibrium Thermodynamics. ICML 2015.(扩散建模思想的最早来源)
- Song & Ermon. Generative Modeling by Estimating Gradients of the Data Distribution. NeurIPS 2019.(score-based 视角,与 DDPM 等价)
- Song et al. Denoising Diffusion Implicit Models. ICLR 2021.(DDIM,确定性采样、大幅提速)