阶段 4 · 学会创造

扩散模型:把"生成"
变成一个反复的"去噪"

GAN 要一次就把噪声变成图,所以极难训。扩散模型换了个思路: 先学会"怎么把一点噪声去掉",然后反复用这一招,从纯噪声里一步步雕出图来。 每一步都很简单——这正是它稳定的原因,也是它慢的原因。

1

核心思想:破坏容易,修复难,但可以拆成很多小修复

上一章的 GAN 一不小心就崩:判别器太强,生成器学不到东西;太弱,生成器又原地转圈。有没有一种稳稳当当、只做回归的生成方法?

回归就是预测一个数(这里是预测加了多少噪声),像《损失函数》里的房价预测那样有标准答案,训练就稳。

比什么前向过程(加噪)反向过程(去噪)
做什么往图里一点点加高斯噪声(每个像素都从钟形分布里随机抽一个数加上去),直到变成纯噪声 从纯噪声开始,一步步把噪声减掉
需要训练吗完全不需要——它是固定公式 需要。这是唯一要学的部分
难度破坏信息太容易了 从零生成很难,但每次只去一点噪声很简单
步数由噪声调度(每一步加多少噪声的那条曲线)决定(通常 1000 步)同样的步数倒着走

前向这条规则不用真的加一千次。记 ᾱt(读作 alpha-bar,横线表示「累计」)为 到第 t 步为止信号还剩的比例——单步的保留系数 αt 一直乘下去就是它。 训练时随机抽一个 t 和一组噪声 ε,把原图和噪声按这两份比例兑一次,就得到第 t 步的图。

🎯 类比

像在石头上雕刻。你不可能凭空雕出一匹马(GAN 试图做的事)。 但如果有人先给你一块已经砸得面目全非的石头, 只要求你"敲掉这一个多余的小突起"——这就简单多了。
扩散模型就是把"雕刻"这件事拆成了一千次"敲掉一个小突起"。

2

前向过程:看信息怎么被淹没

互动 · 拖动时间 t,看它落在九格的哪一格

把鼠标移到上面公式的任意一块上——它对应这张图里正在变的那一项。

看 ᾱt 这个数:它从 1 衰减到接近 0。√ᾱ 是信号还剩多少,√(1−ᾱ) 是噪声占了多少。 (线性调度下)t = 1000 时 ᾱ ≈ 0.00004——原图的信息被压到了十万分之四, 这时候 xT 几乎就是纯噪声,和 x₀ 完全无关了。

3

反向过程:从噪声到数据

反向过程要学的东西叫去噪器:给它一张加了噪的图和时间 t,它猜图里的噪声是什么 (第 4 节讲怎么训;真实模型叫 U-Net)。带帽子的 x̂0、ε̂ 都表示「网络猜的值」。

下面每一帧都在执行 DDIM 的确定性一步——DDIM 是一种每步不再掺随机数的采样方法(第 6 节细讲)。

互动 · 从纯噪声里生成一个螺旋

💡 这一章全在这张图里

从一团纯噪声出发,每一步只做一件事:猜出当前这点噪声,再减掉一点。 一千步小修正累积起来,就是一张图。

互动 · 三维:卷起来的纸,被噪声吹成一团,再被拉回来

为什么不用训练也能跑:本页用了一个现成算得出的去噪器——把 xt 附近的训练点 (页面上那条螺旋)按距离加权平均,越近权重越大(这一版比精确值多做了一点平滑)。 真实模型的去噪器是在几百万张图上训练过的网络。

本页的「图」是平面上的一个个点;换成 512×512 的照片,同一套公式照用—— 只是每个点变成一整张图的所有像素。

原版和 DDIM 的区别:原版 DDPM 每一步还要再掺一点新的随机噪声,所以同一张噪声图能出很多张不同结果; DDIM 把这一步去掉了,给定起点结果固定(第 6 节那张加速表就从此开始)。

M

数学 · 把「信号」和「噪声」按两个比例兑起来

前向过程整章只有一条公式。它做的事像兑一杯饮料: 倒进多少信号、多少噪声,由两个比例决定,而这两个比例只看时间。 下面三个画面,就是公式右边两项各自的实物。

动画 · 信号一份,噪声一份,加起来就是那一格的图

图示 · 两个比例为什么是 √ᾱ 和 √(1−ᾱ)

💡 一句话记住这条公式

它做的事是把两样东西按比例兑起来:ᾱt 是信号还剩几成,1−ᾱt 是噪声占几成。 时间越往后,第一份越小、第二份越大——抽一个时刻兑一次,就得到那一格的图。

把前向公式移项,就得到网络在猜的那张干净图:(带帽子的 ε̂ 就是网络猜的噪声)。

DDIM 的一步就是用 x̂0 和 ε̂ 按 t−1 的比例重新兑一次—— ,第 3 节里每一帧做的正是这件事。 所以「学会猜噪声就能出图」:每一步都指向「离真实数据更近」的方向,一千步累积起来就是一张图。

互动 · 反向那一步:把信号从噪声里「减」出来

🎬 自己验一遍

把上面那个时间步滑块拖到 0:噪声那一份缩成一个点,画面里几乎只剩信号;拖到 1000,只看得见噪声。
中间随便停一下:蓝点缩了多少(√ᾱ)、灰点涨了多少(√(1−ᾱ)), 加起来就正好是第三个画面里那张图——这就是第 2 节那九个方格背后的全部数学。

4

训练目标:简单到令人意外

DDPM 的训练循环(整个算法就这四步)

① 随机抽一张训练图 x₀,随机抽一个时间步 t,随机抽一组噪声 ε
② 用公式直接构造噪声图 xt = √ᾱt x₀ + √(1−ᾱt) ε
③ 让网络猜:我刚才加进去的是哪组噪声? 网络的输出就是 ε̂ —— 对噪声的预测
④ 损失 = ‖ε − ε̂‖²(把每个数的平方加起来),然后反向传播

训练目标就是「预测噪声」:学会在任意噪声水平下猜准噪声,从纯噪声开始反复去噪,就能生成图像。

5

噪声调度:一个被低估的关键

ᾱt 怎么从 1 衰减到 0?这个"衰减曲线"是一个超参数——它不被训练,但它决定了后面所有事情,对结果影响很大。

互动 · 对比三种噪声调度

调度形状问题
线性 Linear
DDPM 原版
每步加的噪声量均匀变大;ᾱ 前慢、中段最陡、尾部压平 尾部浪费:后 20% 里噪声已经饱和。 真正有用的变化集中在中间
余弦 Cosine
Improved DDPM
平滑的余弦曲线,中间变化最快 原论文报告:似然(给真实数据打多高的概率,越高越好)、 FID(生成图和真实图的特征差多远,越低越好)都更好
Sigmoid
Chen 2023
S 形曲线:中间变化最快,两端很平 一种形状更好控制的备选调度;页内实现 t = 1000 时 ᾱ = 1e-8
零终端 SNR 修正
Lin 2023
把调度重新缩放,强制 t = T 时信噪比正好为 0 修的是另一件事:常见调度最后一帧还不是纯噪声。一些新模型在用
⚠️ 为什么这个细节重要

扩散模型的采样慢(要跑几十到上千步)。换一条更合适的调度曲线几乎不增加训练成本, 却能让推理的每一步都落在信息变化最快的区间里。这是一次性价比很高的改进,却常被忽略。

6

加速:从 1000 步到 1 步

方法思路步数代价
DDIM把原版每步掺的随机数去掉(第 3 节),变成一条确定的路径(用 ODE——一条确定轨迹——求解) 20 ~ 100质量略降;失去"同一噪声不同结果"的多样性
DPM-Solver用高阶数值方法解同一个 ODE 10 ~ 20实现更复杂
蒸馏类
渐进蒸馏 / LCM
让"一步去噪"的学生模型模仿"多步"的老师(LCM 就是把这条思路用在潜空间扩散上) 1 ~ 4需要额外训练;质量有损失
一致性模型训练模型把轨迹(从噪声走到数据的路径)上任意点都映射到同一个终点 1 ~ 2需要精心设计;多样性下降
整流流 / 流匹配直接学一条尽可能直的从噪声到数据的路径 1 ~ 10训练更简单、更稳,是 2024 年后的主流方向

DDPM 之所以要 1000 步,是因为它把路径走成了一条弯曲、带随机扰动的曲线。 上面这些加速方法都在让这条路径少绕路,走到极致就是流匹配—— 直接学一条直线(下一章之后的主题)。

7

扩散模型的四个问题

问题具体表现什么时候真的会痛 → 换什么
① 采样慢 天生要迭代几十到上千次,每一步都要完整跑一遍网络。 但它也是优势:迭代次数可以换质量 要在手机或网页里实时出图 → DDIM、蒸馏、LCM(第 6 节那条加速线)
② 训练看真加噪,采样看自己上一步 训练时 xt 来自真实数据加噪,采样时来自模型自己的上一轮;这个错位叫曝光偏差(Ning 等,2023),误差会层层累积,步数一少质量就掉得快 想用很少的步数直接跑原模型 → 换确定性采样(DDIM),或蒸馏一个小步数模型
③ 无法直接控制 得靠引导:把一句话编码成一个向量,作为去噪器的额外输入——同一张噪声图,给「猫」就往猫的方向去噪 想单独调某个属性 → DDIM 反演(把一张真图倒推回它的起点噪声,再改条件重新生成)、prompt-to-prompt(改提示词里的某个词、其他地方保持不变)这类编辑方法,或后面的《潜空间扩散与 DiT》
④ 理论门槛高 变分下界(训练目标的来历)、分数匹配(让网络学「往哪个方向走,数据会变得更可能」)、SDE(把加噪看成连续时间的过程)—— 比 GAN 的"两个网络互相骗"难懂得多;好处是这三套(变分下界 / 分数匹配 / SDE)说的是同一个过程 想从零推导或改训练目标 → 先读拓展阅读里 Lilian Weng 那篇

尽管有这些问题,扩散模型在 2022 年之后接管了图像生成。原因就一条:训练太稳了。 GAN 要小心平衡两个网络;扩散模型只做回归(预测加了多少噪声),像有标准答案的题,几乎不会失败。 「能稳定训起来」的权重,常常高于「理论更优雅」或「采样更快」。

8

小结

这一章看起来是「三个公式加一堆技巧」。它其实只有一个想法—— 而这个想法跟「生成」这两个字关系不大,跟压缩关系很大。

它对应哪条线 ④ 学习即压缩——扩散模型把「生成」重新定义成 一个被精心设计的有损压缩器的逆运算。
一句话 这一章的做法,是先用一条固定公式把数据「压」成纯噪声 (每一步只丢一点信息,一千步丢光),然后只学一件事:把丢掉的那一点点捡回来。
生成 = 解压;整章唯一不需要训练的,恰好是负责「压」的那一步。
它牺牲了什么 牺牲了「一步到位」。GAN 一次前向就出图,扩散要几十到上千次。 换来的是训练稳定:把一个做不到的任务,换成几千个做得到的任务。 (回扣暗线 B:被换掉的正是采样速度。)
🎬 自己验一遍

回到第 2 节那张「拖动时间 t,看它落在九格的哪一格」。九个方格按时间从左到右排开, 首格标着「原图」,之后从 98% 一路掉到接近 0——那个百分比是 √ᾱ,也就是「信号还剩多少」。

那个瞬间你看到的就是「有损压缩」这四个字:滑块每往右走一格,原图的信息就少一点, 而这整个过程没有学习、没有参数、只是一个乘加公式。
再回到第 3 节点一下「▶ 开始生成」——那才是网络唯一要学会的事:把刚丢掉的捡回来。

它在暗线里站在哪

暗线这一章的回答
A 信息流动 所有张量的形状从头到尾没变:x₀ 是 3×512×512,x₁₀₀₀ 还是 3×512×512。 变的是每个数字里装的是信号还是噪声。所以「信息流」是一条形状不变、信息单调递减的坡: ᾱt(线性调度下)从 1 走到 0.00004。
压缩发生在数值的分布里,不在维度里——这跟第 3 阶段「往潜空间降维」的做法正好相反
B 什么被牺牲了 牺牲了采样步数,换训练稳定。GAN 的生成是 1 次前向,DDPM 是 1000 次。 训练时只学「单步去噪」,推理时却要连着用一千次,单步误差会复合(第 7 节第 ② 条)
C+D 参数账本 · 跑在什么上 原版 DDPM 的 U-Net 约 36M 参数,Stable Diffusion 1.5 约 860M,SDXL 约 2.6B。 但这些参数每生成一张图都要完整用 50~1000 次:860M 走 50 步 = 430 亿个权重值各搬一遍; 16 位存的 860M 约 1.7 GB(每个参数 2 字节 × 8.6 亿),走 50 步要读 86 GB——慢在读权重。
搬进潜空间能让要处理的特征图小 48 倍(算得少),但权重一个没少
🎯 前后钩子

它接住了上一章的什么:GAN(《GAN》)要求生成器一步把噪声变成图,两个网络必须精确平衡,一崩全崩; 拆成一千步就不需要平衡了。

它给下一章留了什么:一千步太慢。路径能不能走得直一点,十步走完? 这就是 《潜空间扩散与 DiT》 和整条加速线的起点。

一句话带走扩散模型

扩散模型 = 把"生成"拆成一千次"去噪"。
前向是固定公式,不用学;反向只学一件事:猜我往上加了多少噪声。
它战胜 GAN 靠的不是优雅,是训练稳定——代价是采样慢。所以 2023 年以来的加速研究, 主流的一条线都在做同一件事:让那条从噪声到数据的路径变直。

9

拓展阅读

上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。

📄 这一章的说法从哪来

💻 工业界怎么写

∑ 更严格的形式