接着上一篇的问题#
上一篇搞清楚了一件事:DDPM 的前向扩散虽然定义成一步一步加噪的马尔可夫链,但因为高斯分布在线性组合下的封闭性,任意时刻的 \(x_t\) 都可以一步算出来:
$$ x_t = \sqrt{\bar\alpha_t}\, x_0 + \sqrt{1 - \bar\alpha_t}\, \epsilon, \quad \epsilon \sim \mathcal{N}(0, I) $$当时觉得这个结论很漂亮,但紧接着就冒出一个问题:既然 \(x_{100}\) 和 \(x_{900}\) 都能直接生成,那训练的时候随机选一个 timestep 到底有什么意义?不同 timestep 采出来的不都是"原图加了点噪声"吗?
再往下想一步:前向过程能一步到位,反向生成是不是也能倒着一步搞定?
这篇就是把这两个问题想清楚的过程。
同一份噪声,不同的 timestep#
我最初的直觉是:既然 \(\epsilon\) 都是从 \(\mathcal{N}(0, I)\) 采样的,不同 timestep 之间的区别应该不大。
但这个直觉是错的。虽然噪声源相同,\(\bar\alpha_t\) 不同,信号和噪声的配比就完全不同。
把跳步公式拆开看:\(\sqrt{\bar\alpha_t}\) 是原始图片 \(x_0\) 的权重,\(\sqrt{1 - \bar\alpha_t}\) 是噪声 \(\epsilon\) 的权重。\(\bar\alpha_t\) 是所有 \(\alpha_i\) 的连乘积,随着 \(t\) 增大单调递减。
在 \(t\) 比较小的时候,比如 \(t = 100\),\(\bar\alpha_t\) 还比较大,\(x_t\) 里大部分是原图信号,噪声只是让画面有点模糊。图片的主体轮廓、颜色分布都还在。
到了 \(t = 900\),\(\bar\alpha_t\) 已经衰减到接近 0,\(x_t\) 几乎全是噪声,原图的信息基本丢光了。
所以虽然每次采的噪声来自同一个分布,但不同 timestep 构造出来的 \(x_t\) 差异巨大。对于去噪网络来说,从一张还能看出猫的图片里去掉轻微噪声,和从一团完全看不出是什么的噪声里恢复出一张猫,是完全不同难度的任务。
不同 timestep 对应不同难度的去噪问题。训练时随机选 timestep,是为了让网络在各种噪声程度下都学会去噪。
训练的时候网络在学什么#
搞清楚 timestep 的意义之后,再看一下 DDPM 到底在训练什么。
DDPM 训练一个噪声预测网络 \(\epsilon_\theta(x_t, t)\)。符号逐个看:\(\theta\) 是神经网络的可训练参数;\(x_t\) 是当前的噪声图片;\(t\) 是当前的时间步,告诉网络现在的噪声有多重;输出是网络对"这张图片里被加进去的噪声"的预测。
训练流程很直接:
- 从训练集取一张真实图片 \(x_0\)
- 随机选一个 timestep \(t\)
- 从 \(\mathcal{N}(0, I)\) 采样一份噪声 \(\epsilon\)
- 用跳步公式直接构造 \(x_t = \sqrt{\bar\alpha_t}\, x_0 + \sqrt{1 - \bar\alpha_t}\, \epsilon\)
- 让网络看着 \(x_t\) 和 \(t\),预测 \(\epsilon\)。因为第 3 步自己采的噪声,真实的 \(\epsilon\) 是已知的,可以直接算 loss
这里有一个容易忽略的点:前向加噪过程完全不需要训练。 它是人为定义好的确定性规则(给定 \(x_0\) 和 \(\epsilon\),\(x_t\) 就确定了)。网络要学的不是怎么加噪,而是怎么从噪声图片里把噪声剥离出来——也就是反向过程。
如果知道噪声,其实一步就能恢复#
想到这里我试了一下:既然前向公式是 \(x_t = \sqrt{\bar\alpha_t}\, x_0 + \sqrt{1 - \bar\alpha_t}\, \epsilon\),那移个项不就能把 \(x_0\) 解出来?
$$ x_0 = \frac{x_t - \sqrt{1 - \bar\alpha_t}\, \epsilon}{\sqrt{\bar\alpha_t}} $$这个公式在数学上完全成立。训练的时候,因为 \(x_0\) 和 \(\epsilon\) 都是自己给的,验证一下这个等式确实严格相等。
所以困难不在于"数学上不存在逆"。逆公式写在这里,移项就行。
那反向生成到底难在哪?
不知道噪声是关键,但不是全部原因#
我最早的想法是:反向难是因为生成的时候不知道 \(\epsilon\)。训练时噪声是自己加的,当然知道加了什么;但生成时手里只有一张噪声图片 \(x_T\),没有人告诉你里面的噪声具体是什么。
这个想法对,但只对了一半。
更本质的困难是:即使有一个完美的噪声预测器,给定一张高度噪声化的图片,它可能对应很多张完全不同的合理原始图片。
一张接近纯噪声的 \(x_T\),它有可能是从一张猫的照片加噪得到的,也有可能是从一辆汽车、一栋建筑、一片风景加噪得到的。从这张噪声图出发,不存在唯一"正确"的 \(x_0\)。
所以问题不只是"求逆"——不是解一个方程然后得到唯一解。问题是从噪声出发,生成一张符合真实数据分布的图片。 这是一个生成问题,不是一个求解问题。
条件概率不能直接反转#
换成概率的语言看这件事会更清楚。
前向过程定义了 \(q(x_t | x_0)\):给定原始图片 \(x_0\),加噪后的 \(x_t\) 服从什么分布。这个条件分布是已知的,因为加噪规则是我们自己设计的——高斯噪声,\(\bar\alpha_t\) 是预先算好的,整个分布的形式都写得出来。
反向需要的是 \(q(x_0 | x_t)\):给定一张噪声图片,原始图片的分布是什么。
我一开始觉得:知道了 \(q(x_t | x_0)\),反过来写一下不就行了?
但这两个条件概率之间隔着贝叶斯公式:
$$ q(x_0 | x_t) = \frac{q(x_t | x_0) \, p_{\text{data}}(x_0)}{q(x_t)} $$\(q(x_t | x_0)\) 是已知的。但分子里还有一项 \(p_{\text{data}}(x_0)\)——真实图片的数据分布。这恰恰是我们不知道的东西。如果已经知道真实数据分布长什么样,根本就不需要训练生成模型了。
这和日常概率里的情况一样。知道"下雨时地面湿的概率"(\(P(\text{地湿} | \text{下雨})\))并不意味着知道"地面湿时正在下雨的概率"(\(P(\text{下雨} | \text{地湿})\))。后者还取决于下雨本身有多常见、有没有其他原因让地面变湿。
知道 \(P(A|B)\) 不代表知道 \(P(B|A)\)。前向过程定义了从图片到噪声的条件分布,但反过来从噪声到图片的条件分布,依赖于我们不知道的真实数据分布。
为什么要逐步去噪#
既然一步从纯噪声直接跳到清晰图片太难——从 \(\mathcal{N}(0, I)\) 到自然图片的分布,中间的距离太大,一个网络很难一步学会这个映射——DDPM 的做法是把它拆成很多小步:
$$ x_T \rightarrow x_{T-1} \rightarrow \cdots \rightarrow x_1 \rightarrow x_0 $$每一步,网络只需要完成一个小幅度的修正:从 \(x_t\) 到 \(x_{t-1}\),去掉一小部分噪声。这比一步到位简单得多——相邻两个 timestep 之间的分布差异很小,网络只需要学会做局部调整。
网络实际学习的是 \(p_\theta(x_{t-1} | x_t)\):给定当前状态,预测前一步应该长什么样。
这也解释了为什么生成时需要从 \(x_T\) 开始,一步一步迭代回 \(x_0\),而不能像前向那样跳步——前向能跳步是因为加噪规则已知,存在解析形式的边际分布;反向每一步都是网络的近似预测,没有解析捷径。
写在最后#
从上一篇的前向跳步推导走到这里,我觉得 diffusion model 前向和反向的不对称性可以归结为三件事。
前向扩散是一个已知规则的数据破坏过程。 噪声分布已知,noise schedule 已知,给定 \(x_0\) 就能直接写出任意 \(x_t\) 的分布。
反向生成是一个针对未知数据分布的生成过程。 手里只有噪声,没有原始图片,也没有真实数据分布的解析形式。
Diffusion model 的核心不是学习如何加噪——加噪不需要学。它学的是如何把噪声逐步变成符合真实数据分布的样本。 网络在每个 timestep 学习的,是当前噪声程度下的去噪策略。
这也是为什么"前向可以一步采样"和"反向需要逐步去噪、需要训练神经网络"这两件事并不矛盾。它们面对的根本就不是同一个问题:一个在执行已知的随机过程,另一个在学习未知的数据生成规律。
参考资料#
- Ho, Jared, Abbeel Pieter, Denoising Diffusion Probabilistic Models (NeurIPS 2020) — DDPM 原始论文
- DDPM 前向扩散:为什么加噪可以跳过中间步骤 — 本文的前置文章
- Lilian Weng, What are Diffusion Models? — https://lilianweng.github.io/posts/2021-07-11-diffusion-models/