我第一次听说扩散模型时,脑子里只有一个问题:你先给一张图片疯狂加噪,加到最后变成纯噪声,然后再让模型从这个噪声一点一点把图片还原出来——这听上去像是一个魔术。为什么反过来就能生成图片?难道模型记住了所有图片的噪声版本?后来我啃完DDPM的论文,又看了Lilian Weng的博客,才终于想通这件事。今天我想把那个“啊哈”时刻分享给你。

加噪:一场温柔的热寂
扩散模型的前向过程(加噪)其实很简单:你有一张真实的图片,比如一只猫。你分很多步(比如 1000 步),每一步给图片加一丁点高斯噪声。每一步的噪声量很小,小到你看不出变化,但经过 1000 步之后,图片就完全变成了纯噪声——就像一杯清水,每滴一滴墨水,最后变成一杯黑水。这个过程在数学上是一个马尔可夫链:给定当前状态,下一步只依赖于当前状态,与之前无关。每一步加噪声的公式可以写成:
x_t = √(1-β_t) * x_{t-1} + √β_t * ε,其中 ε ~ N(0, I),β_t 是一个很小的系数,随时间变大。
这个设计来自非平衡热力学中扩散过程的启发,原始论文 “Deep Unsupervised Learning using Nonequilibrium Thermodynamics” 把这个想法搬到了机器学习里。有趣的是,加噪过程是不需要学习的,它就是一套固定的计算规则,你甚至可以提前算好任意步 t 的噪声分布,直接一步到位加噪到 x_t,这就是重参数化技巧。
去噪的关键:不是猜图片,而是猜噪声
如果加噪是确定的,那理论上,只要你能知道每一步加的是什么噪声,就可以逆向操作,从噪声一步步恢复出原图。但问题来了:在生成一张新图片时,我们根本不知道原图,也就不知道每一步到底加了什么噪声。所以,我们用一个神经网络(通常是 U-Net)来猜测每一步的噪声。训练时,我们给模型输入一个加了噪声的图片 x_t 和时间步 t,让模型预测出这一步所加的噪声 ε。损失函数就是预测噪声和真实噪声的均方误差:
L_simple = || ε_θ(x_t, t) – ε ||²
这就是 DDPM 论文 “Denoising Diffusion Probabilistic Models” 提出的核心训练目标。模型学会了辨认“什么样的噪声匹配这个图片和这个时间步”,然后去噪过程就可以用预测的噪声减去,得到前一步的图片。
为什么预测噪声比直接预测图片更聪明?
你可能想:为什么不直接让模型输出去噪后的图片?直接回归 x_0 不行吗?我最早也这么想,但后来发现这会导致严重的模式崩塌。因为每一步的噪声量很小,相邻两步的图片几乎一样,如果让模型直接输出干净图片,它的预测会来回跳,训练不稳定。而预测噪声相当于让模型只去关注“加进去的那部分扰动”,这是一个更简单的目标——噪声服从高斯分布,预测高斯噪声比预测复杂的图片分布容易得多,而且每一步的预测结果可以慢慢累积,最终生成连贯的图片。
训练:噪声预测器是怎么练成的
训练循环很简单,步骤如下:
- 从数据集中随机取一张图片 x_0。
- 随机采样一个时间步 t ~ Uniform(1, T)。
- 采样一个标准高斯噪声 ε。
- 用重参数化直接得到 x_t = √(ᾱ_t) x_0 + √(1-ᾱ_t) ε。
- 把 (x_t, t) 喂给模型,得到预测噪声 ε_θ。
- 计算损失 (ε_θ – ε)²,反向传播更新参数。
不断重复,模型就学会了在任何噪声水平下预测噪声。训练完成后,模型就成为了一个“通用去噪器”。
推理:从随机噪声中 “长” 出图片
生成新图片时,我们从纯噪声 x_T ~ N(0, I) 开始,然后一步步逆向去噪:
for t in reversed(range(T)): z = torch.randn_like(x) if t > 1 else 0 noise_pred = model(x, t) x = 1/sqrt(alpha_t) * (x - (1-alpha_t)/(sqrt(1-bar_alpha_t)) * noise_pred) + sigma_t * z
这个循环反复执行,图片逐渐清晰,就像从雾气中慢慢浮现出轮廓。最终得到一张全新的图片,它从未出现在训练集中,但具有类似训练数据的分布。
对比:扩散模型、GAN、VAE 的三角恋
| 特性 | 扩散模型 | GAN | VAE |
|---|---|---|---|
| 生成方式 | 逐步去噪 | 生成器与判别器博弈 | 编码解码 + 采样 |
| 训练稳定性 | 非常稳定 | 容易模式崩塌、训练震荡 | 稳定 |
| 生成质量 | 极高,细节丰富 | 高,但易有伪影 | 较模糊 |
| 多样性 | 高,覆盖分布 | 可能模式崩塌,多样性低 | 高 |
| 推理速度 | 慢,需要多步采样 | 快,单次前向 | 快 |
扩散模型继承了 VAE 的稳定训练和 GAN 的高质量,但牺牲了推理速度。不过近年来的加速采样方法(如 DDIM “Denoising Diffusion Implicit Models”)已经能把步数压到几十步甚至几步。
为什么非要 1000 步?能少一点吗?
1000 步是 DDPM 的默认设定,因为步数越多,每一步的加噪量越小,逆向过程就越接近高斯分布假设,模型预测噪声更容易。但太多步导致推理巨慢。后来研究者发现,可以设计一个非马尔可夫的逆向过程,跳步采样,比如 DDIM 就直接从 1000 步降到 50 步,质量几乎不降。所以现在很多扩散模型都采用这种加速策略。
我踩过的三个坑
第一个坑:我以为扩散模型会记住训练图片,后来发现它只是学到了数据分布的“梯度场”——每个噪声水平下,指向更干净图片的方向。这类似于 score-based 模型,它估计的是数据分布的梯度,然后沿着梯度方向走,就能到达高概率区域。这个视角来自 “Generative Modeling by Estimating Gradients of the Data Distribution”。
第二个坑:我一开始以为去噪过程能恢复出原图,但生成任务中,起点是纯噪声,没有原图,所以模型是利用习得的去噪能力,从噪声中“凭空”构造出一张看起来合理的图片,而不是恢复某张特定的图片。
第三个坑:我忽略了时间步 t 的编码。模型需要知道当前处于哪个噪声水平,才能预测合适的噪声量。通常用正弦位置编码把 t 变成一个向量,加到 U-Net 的每个层里,这个细节往往是实现时的关键。
FAQ
扩散模型是记住图片然后拼凑吗?
不是。扩散模型在训练时只学习去噪,没有存储图片的机制。它学到的是分布,生成时是从噪声中采样,然后通过去噪一步步走向一个可能的样本,这个样本可以是全新的。
为什么加噪的逆向过程是可行的?
因为加噪过程是线性高斯变换,其逆向过程(从 t 到 t-1)在已知 x₀ 的条件下也是高斯分布,所以理论上可以逆转。而给定 x_t 时,逆向分布不是高斯,但我们可以用神经网络来近似,当步数足够多时,每一步的逆向分布近似为高斯,所以用预测噪声来近似有效。
扩散模型和 GAN 比,哪个更好?
在高质量图像生成任务上,扩散模型目前领先,比如 Stable Diffusion 和 DALL·E 2 都基于扩散。但 GAN 在推理速度快、某些领域(如人脸生成)仍有优势。两者各有千秋,而且现在也有结合两者的尝试(如 GAN 做判别器引导扩散)。
收尾:扩散模型的能力边界与未来
扩散模型最大的优势是训练稳定、生成质量高、模式覆盖全,但推理速度慢仍是硬伤。它已经在文生图、音频生成、视频生成等领域大放异彩,但面对超长序列生成(如高清视频)时,计算成本仍很高。未来,更高效的采样算法、与潜在空间结合(如 Stable Diffusion 的 Latent Diffusion)会进一步降低门槛。理解扩散模型,本质上是理解“如何从噪声中重建信号”——而这一思想,远不止生成图片,它正在渗透到序列建模、强化学习等多个领域。
希望这篇文章帮你捅破了那层窗户纸。如果你当时也像我一样困惑,现在应该能说一句:哦,原来如此。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/61.html