Tensor NotesNotes on machine learning
Generative

扩散模型的噪声调度:DDPM、DDIM 与 Flow Matching

扩散模型的噪声调度:DDPM、DDIM 与 Flow Matching题图

训练一个扩散模型,噪声调度的影响可能比网络结构还大。这篇梳理从 DDPM 的线性调度到今天流匹配的演化脉络,重点是每一步为什么要改。

一、前向过程做了什么

扩散模型的前向过程是往数据里逐步加高斯噪声,直到完全变成标准正态。定义每一步保留信号的比例 αt,累积量 ᾱt = Π αs,则任意时刻可以一步采样:

xt = √ᾱt · x0 + √(1 − ᾱt) · ε, ε ~ N(0, I)

这个闭式解是扩散模型能高效训练的关键——不需要真的迭代 T 步,直接随机采一个 t 就能构造训练样本。训练目标退化成一个简单的回归:

def training_step(model, x0):
    t     = torch.randint(0, T, (x0.shape[0],), device=x0.device)
    eps   = torch.randn_like(x0)
    a_bar = alpha_bar[t].view(-1, 1, 1, 1)
    xt    = a_bar.sqrt() * x0 + (1 - a_bar).sqrt() * eps
    return F.mse_loss(model(xt, t), eps)

整个模型学的就是:给我一张带噪图和噪声强度,把噪声预测出来。

二、线性调度的问题

DDPM 原论文用的是 β 从 1e-4 到 0.02 的线性递增。画出 ᾱt 曲线会发现它在后段掉得非常快:

线性、余弦与 sigmoid 三种噪声调度的信号保留曲线对比
图 1 · 三种调度下 ᾱ 随时间的变化。线性调度在中后段迅速塌到接近 0

后果是相当大一部分时间步是浪费的。当 ᾱ 已经接近 0,xt 和纯噪声在数值上几乎无法区分,模型在这些步上学不到有效信号,但训练和采样都得照样走一遍。在 64×64 分辨率上这个浪费还不明显,到 256×256 就很严重了——因为分辨率越高,相邻像素的冗余越多,同样的噪声强度对图像的实际破坏更小,需要更激进的加噪才能真正抹掉信息。

余弦调度

改进版本直接定义 ᾱ 而不是 β:

t = cos²( (t/T + s) / (1 + s) · π/2 ), s ≈ 0.008

这条曲线在中段下降平缓,两端有明显的平台。实践中它把 FID 改善了一大截,在 256 分辨率上通常是 15%–25% 的相对提升。偏移量 s 的作用是防止 t = 0 附近 β 太小导致数值问题。

分辨率相关的一个细节同一个调度在不同分辨率下的有效噪声水平不同。把在 64×64 上调好的调度直接搬到 512×512,实际信噪比会偏高,模型学到的去噪能力偏弱。正确做法是按分辨率对调度做偏移:分辨率翻倍,log-SNR 大约要下移 2·log 2。

三、DDIM:把采样和训练解耦

DDPM 的采样必须一步一步走完 T 步,1000 步生成一张图在工程上不可接受。DDIM 的洞察是:训练目标只约束了边缘分布 q(xt|x0),并没有唯一确定反向过程。可以构造一族非马尔可夫的反向过程,共享同一个训练好的模型,但允许跳步。

DDIM 的更新式(η = 0 时确定性):

xt−1 = √ᾱt−1 · x̂0 + √(1 − ᾱt−1) · εθ(xt, t)

其中 x̂0 = (xt − √(1−ᾱt)·εθ) / √ᾱt 是当前对原图的估计。这个式子里 t−1 可以换成任意更小的 t′,于是 50 步甚至 20 步采样成为可能。

确定性还带来一个副产品:同一个初始噪声总是生成同一张图,噪声空间变成了可插值的隐空间。这是很多图像编辑方法的基础。

四、参数化的选择:预测 ε、x₀ 还是 v

模型输出什么,影响的是不同噪声水平下损失的隐式加权。

参数化形式低噪声时高噪声时
ε-pred预测噪声任务简单,梯度信号弱表现好
x₀-pred预测原图表现好近乎不可能,噪声主导
v-predv = √ᾱ·ε − √(1−ᾱ)·x₀两端都平衡

v-预测在高分辨率和蒸馏场景里几乎是默认选择,因为它在整个噪声区间上都保持了合理的信噪比,不会出现某一段几乎学不动的情况。迁移成本很低:只是在损失函数里换一个目标构造方式,网络结构完全不动。

五、流匹配:把路径拉直

最近的主流方向是把问题重新表述为常微分方程。流匹配不再谈"加噪去噪",而是直接学一个速度场,把噪声分布沿着某条路径推到数据分布。最简单的线性插值路径

xt = (1 − t) · x0 + t · ε, 目标速度 v = ε − x0

训练目标就是回归这个速度:loss = mse(model(x_t, t), eps - x0)。几乎不能更简单了。

好处是路径几乎是直线,而直线用欧拉法积分需要的步数极少。实践中 8–20 步就能得到接近收敛的质量,而 DDIM 通常需要 30–50 步。此外它天然支持不同模态之间的映射(起点不一定要是高斯噪声),在图像到图像、文本到语音上都有直接应用。

# 采样:一个朴素欧拉积分器
x = torch.randn(shape)
ts = torch.linspace(1.0, 0.0, steps + 1)
for i in range(steps):
    t, dt = ts[i], ts[i] - ts[i+1]
    x = x - dt * model(x, t)      # 速度场沿路径反向积分

六、实际选型

  • 从零训练新模型:直接上流匹配 + 线性路径 + v 风格参数化,代码最简单,采样步数最少。
  • 已有 DDPM 权重要提速:换 DDIM 采样器,零成本;再不够就做几步蒸馏。
  • 高分辨率:无论哪条路线,都要按分辨率调整 log-SNR 偏移,这一步的收益经常被低估。
  • 需要精确可控的编辑:确定性采样器(DDIM η=0 或流匹配的 ODE 求解)是前提,随机采样器会破坏可逆性。

下一篇想写引导强度(CFG scale)与多样性的权衡,那个话题里有不少反直觉的结论。

上一篇:RLHF 到 DPO:偏好对齐的三年演化…下一篇:INT4/INT8 量化推理:从 GPTQ …

继续阅读

Related