DDPM
DDPM:Denoising Diffusion Probabilistic Models,去噪扩散概率模型。它是现代扩散模型的经典形式之一,也是 Stable Diffusion、Imagen 等模型背后的核心思想之一。
DDPM 想解决什么问题?
生成模型的目标是学习真实数据分布:
x0∼q(x0)
其中 x0 可以是一张真实图片。
我们希望训练一个模型,能够从简单分布,比如标准高斯噪声:
xT∼N(0,I)
逐步生成真实图片:
xT→xT−1→⋯→x1→x0
DDPM 的核心思想是:
正向过程逐步给真实图片加噪声,直到变成纯高斯噪声;
反向过程学习如何一步步去噪,把高斯噪声还原成真实图片。
可以把它理解成:
image→slightly noisy image→⋯→pure noise
然后训练神经网络学会反过来:
pure noise→⋯→clean image
前向扩散过程:逐步加噪声
DDPM 定义一个固定的前向马尔可夫过程:
q(xt∣xt−1)=N(xt;1−βtxt−1,βtI)
其中:
- x0:真实数据,比如原图;
- xt:第 t 步加噪后的数据;
- βt:第 t 步加入的噪声强度;
- T:总扩散步数,常见如 1000;
- βt 通常是一个很小的正数,逐步增大。
这个公式的意思是:
xt=1−βtxt−1+βtϵt
其中:
ϵt∼N(0,I)
也就是说,每一步都做两件事:
- 把上一时刻的信号稍微缩小;
- 加入一点高斯噪声。
为了推导方便,定义:
αt=1−βt
于是前向过程可以写成:
q(xt∣xt−1)=N(xt;αtxt−1,(1−αt)I)
也就是:
xt=αtxt−1+1−αtϵt
继续定义:
αˉt=s=1∏tαs
注意:
αˉt=α1α2⋯αt
它表示从第 0 步到第 t 步,总共还保留下来的原始信号比例。
虽然前向过程是一步步定义的:
x0→x1→⋯→xt
但 DDPM 有一个非常重要的性质:
q(xt∣x0)=N(xt;αˉtx0,(1−αˉt)I)
也就是说,我们不需要真的一步步加噪,可以直接从 x0 采样出任意时刻的 xt:
xt=αˉtx0+1−αˉtϵ
其中:
ϵ∼N(0,I)
这个公式极其重要,训练 DDPM 基本就靠它。
上述公式的具体推导
先看第一步:
x1=α1x0+1−α1ϵ1
因为:
αˉ1=α1
所以:
x1=αˉ1x0+1−αˉ1ϵ
成立。
再看第二步:
x2=α2x1+1−α2ϵ2
把 x1 代进去:
x2=α2(α1x0+1−α1ϵ1)+1−α2ϵ2
展开:
x2=α1α2x0+α2(1−α1)ϵ1+1−α2ϵ2
前面第一项是信号:
α1α2x0=αˉ2x0
后面两项都是高斯噪声的线性组合。高斯分布有一个性质:独立高斯变量的线性组合仍然是高斯。
其方差为:
α2(1−α1)+(1−α2)
化简:
α2−α1α2+1−α2=1−α1α2=1−αˉ2
所以:
x2=αˉ2x0+1−αˉ2ϵ
推广到任意 t,得到:
xt=αˉtx0+1−αˉtϵ
这就是 DDPM 前向扩散的核心公式。
当前向扩散足够久,xT 接近纯噪声
因为:
αˉt=s=1∏tαs
而每个:
0<αs<1
所以随着 t 增大:
αˉt→0
于是:
xt=αˉtx0+1−αˉtϵ
会变成:
xT≈ϵ
也就是:
xT∼N(0,I)
这就完成了从真实图片到高斯噪声的过程。
反向过程:学习去噪
前向过程是已知的:
q(xt∣xt−1)
但是生成时,我们需要反过来:
pθ(xt−1∣xt)
也就是从噪声状态 xt 预测更干净一点的状态 xt−1。
DDPM 假设反向过程也是高斯分布:
pθ(xt−1∣xt)=N(xt−1;μθ(xt,t),Σθ(xt,t))
通常简化为:
pθ(xt−1∣xt)=N(xt−1;μθ(xt,t),σt2I)
也就是说,神经网络主要学习均值:
μθ(xt,t)
有些版本也学习方差,但经典 DDPM 中经常固定方差。
训练目标与理论推导
DDPM 是一个概率生成模型,所以理论上希望最大化数据似然:
pθ(x0)
但是直接最大化:
logpθ(x0)
很难,因为生成过程包含很多隐变量:
x1,x2,…,xT
完整的生成模型是:
pθ(x0:T)=p(xT)t=1∏Tpθ(xt−1∣xt)
其中:
p(xT)=N(0,I)
而数据似然是:
pθ(x0)=∫pθ(x0:T)dx1:T
这个积分非常难算。
所以 DDPM 使用变分推断,优化一个下界,也就是 ELBO。
我们有真实的前向扩散分布:
q(x1:T∣x0)
希望最大化:
logpθ(x0)
引入 q(x1:T∣x0):
logpθ(x0)=log∫pθ(x0:T)dx1:T
乘除同一个分布:
log∫q(x1:T∣x0)q(x1:T∣x0)pθ(x0:T)dx1:T
写成期望:
logEq(x1:T∣x0)[q(x1:T∣x0)pθ(x0:T)]
利用 Jensen 不等式:
logE[X]≥E[logX]
得到:
logpθ(x0)≥Eq[logq(x1:T∣x0)pθ(x0:T)]
这个下界就是 ELBO:
LELBO=Eq[logq(x1:T∣x0)pθ(x0:T)]
所以 DDPM 训练目标中,想要最大化数据似然,可以使用最大化 ELBO 来替代。
最大化 ELBO 等价于最小化负 ELBO:
−LELBO
把 ELBO 展开,进一步得到训练所需要的 loss 形式
生成过程:
pθ(x0:T)=p(xT)t=1∏Tpθ(xt−1∣xt)
前向过程:
q(x1:T∣x0)=t=1∏Tq(xt∣xt−1)
所以:
LELBO=Eq[logp(xT)+t=1∑Tlogpθ(xt−1∣xt)−t=1∑Tlogq(xt∣xt−1)]
这个式子还不够方便。因为我们想要学习的是反向过程,但是式子中依旧存在前向项 q(xt∣xt−1) 。因此需要转换成后向项,并且进一步改写成 KL 散度形式。
最终负 ELBO 可以分解为:
L=LT+t=2∑TLt−1+L0
其中:
LT=DKL(q(xT∣x0)∥p(xT))
Lt−1=DKL(q(xt−1∣xt,x0)∥pθ(xt−1∣xt))
L0=−logpθ(x0∣x1)
最核心的是中间这一项:
DKL(q(xt−1∣xt,x0)∥pθ(xt−1∣xt))
它的含义是:
让模型学习的反向分布 pθ(xt−1∣xt),尽量接近真实的反向后验分布 q(xt−1∣xt,x0)。
注意这里的真实反向后验不是:
q(xt−1∣xt)
而是:
q(xt−1∣xt,x0)
因为训练时我们知道原始图像 x0,所以可以构造这个后验。
- LELBO 推导到 KL 散度形式的过程
LELBO=Eq[logp(xT)+t=1∑Tlogpθ(xt−1∣xt)−t=1∑Tlogq(xt∣xt−1)]
训练时通常最小化负 ELBO,记作:
L=−LELBO
所以:
L=Eq[−logp(xT)−t=1∑Tlogpθ(xt−1∣xt)+t=1∑Tlogq(xt∣xt−1)]
因为前向过程是一个马尔可夫链,状态 xt 只依赖于 xt−1。所以:
q(xt∣xt−1)=q(xt∣xt−1,x0)
此时,我们对等式右边套用贝叶斯公式:
q(xt∣xt−1,x0)=q(xt−1∣x0)q(xt−1∣xt,x0)q(xt∣x0)
t=1∑Tlog(q(xt−1∣x0)q(xt−1∣xt,x0)q(xt∣x0))
=t=1∑Tlogq(xt−1∣xt,x0)+t=1∑Tlogq(xt∣x0)−t=1∑Tlogq(xt−1∣x0)
=t=1∑Tlogq(xt−1∣xt,x0)+logq(xT∣x0)−logq(x0∣x0)
由于给定 x0 时 x0 的概率是 1,所以 logq(x0∣x0)=logq(x0∣x1,x0)=0。
带入得到
L=Eq[logp(xT)q(xT∣x0)+t=2∑Tlogpθ(xt−1∣xt)q(xt−1∣xt,x0)−logpθ(x0∣x1)]
所以最终化简为:
L=LT+t=2∑TLt−1+L0
其中:
LT=DKL(q(xT∣x0)∥p(xT))
这表示:
前向加噪到最后得到的 q(xT∣x0),应该接近标准高斯先验 p(xT)。
实际中如果 T 足够大,q(xT∣x0) 已经很接近 N(0,I),所以这一项通常不是训练重点。
Lt−1=DKL(q(xt−1∣xt,x0)∥pθ(xt−1∣xt))
L0=−logpθ(x0∣x1)
至此我们得到了实际的训练目标的 Loss 表达式,其中模型主要需要学习的是 pθ(xt−1∣xt),而其学习的目标就是 真实反向后验 q(xt−1∣xt,x0)
- 真实反向后验 q(xt−1∣xt,x0) 推导
我们需要求:
q(xt−1∣xt,x0)
根据贝叶斯公式:
q(xt−1∣xt,x0)=q(xt∣x0)q(xt∣xt−1,x0)q(xt−1∣x0)
由于前向过程是马尔可夫的:
q(xt∣xt−1,x0)=q(xt∣xt−1)
所以:
q(xt−1∣xt,x0)=q(xt∣x0)q(xt∣xt−1)q(xt−1∣x0)
这三个分布都是高斯:
q(xt∣xt−1)=N(xt;αtxt−1,βtI)
q(xt−1∣x0)=N(xt−1;αˉt−1x0,(1−αˉt−1)I)
q(xt∣x0)=N(xt;αˉtx0,(1−αˉt)I)
因为高斯分布相乘后仍然是高斯,所以:
q(xt−1∣xt,x0)=N(xt−1;μ~t(xt,x0),β~tI)
其中真实后验方差为:
β~t=1−αˉt1−αˉt−1βt
真实后验均值为:
μ~t(xt,x0)=1−αˉtαˉt−1βtx0+1−αˉtαt(1−αˉt−1)xt
这个公式很关键,DDPM 的训练就是让模型预测的反向高斯分布接近这个真实后验。
推导细节:
q(xt−1∣xt,x0)∝q(xt∣xt−1)q(xt−1∣x0)
把 xt−1 当成变量,记:
z=xt−1
第一项:
q(xt∣z)=N(xt;αtz,βtI)
它的指数部分是:
−2βt1∣xt−αtz∣2
第二项:
q(z∣x0)=N(z;αˉt−1x0,(1−αˉt−1)I)
指数部分是:
−2(1−αˉt−1)1∣z−αˉt−1x0∣2
两项相乘,指数相加:
−21[βt1∣xt−αtz∣2+1−αˉt−11∣z−αˉt−1x0∣2]
只保留和 z 有关的项。
第一部分展开:
βt1∣xt−αtz∣2=βt1(xt2−2αtxtz+αtz2)
第二部分展开:
1−αˉt−11∣z−αˉt−1x0∣2=1−αˉt−11(z2−2αˉt−1x0z+αˉt−1x02)
合并 z2 项:
(βtαt+1−αˉt−11)z2
合并 z 项:
−2(βtαtxt+1−αˉt−1αˉt−1x0)z
因此后验分布的精度,也就是方差的倒数,为:
β~t1=βtαt+1−αˉt−11
化简:
β~t1=βt(1−αˉt−1)αt(1−αˉt−1)+βt
因为:
βt=1−αt
所以分子:
αt(1−αˉt−1)+βt=αt−αtαˉt−1+1−αt=1−αtαˉt−1
又因为:
αˉt=αtαˉt−1
所以:
1−αtαˉt−1=1−αˉt
因此:
β~t1=βt(1−αˉt−1)1−αˉt
所以:
β~t=1−αˉt1−αˉt−1βt
均值为:
μ~t=β~t(βtαtxt+1−αˉt−1αˉt−1x0)
代入 β~t:
μ~t=1−αˉt1−αˉt−1βt(βtαtxt+1−αˉt−1αˉt−1x0)
展开:
μ~t=1−αˉtαt(1−αˉt−1)xt+1−αˉtαˉt−1βtx0
这就得到了刚才的结果:
μ~t(xt,x0)=1−αˉtαˉt−1βtx0+1−αˉtαt(1−αˉt−1)xt
- 为什么在 “反向过程”章节中说模型主要是学习均值而不是方差
学习均值实际上就是在学习噪声估计
模型的训练目标是让反向过程的 pθ(xt−1∣xt)
尽可能接近真实反向后验 q(xt−1∣xt,x0)
已知真实后验方差为:
β~t=1−αˉt1−αˉt−1βt
真实后验均值为:
μ~t(xt,x0)=1−αˉtαˉt−1βtx0+1−αˉtαt(1−αˉt−1)xt
即训练过程中或者推理过程中,模型需要做的可以等价转换为预测 x0。此时可以理解为模型的训练目标就是让预测值 x^0
尽可能接近实际 x0
因为我们知道:
xt=αˉtx0+1−αˉtϵ
从这个式子可以解出 x0:
x0=αˉtxt−1−αˉtϵ
所以进一步的,模型的目标本质上就是在预测噪声 ϵθ(xt,t)
x^0=αˉtxt−1−αˉtϵθ(xt,t)
代回原来的均值估计,可以得到:
μ~t(xt,ϵ)=αt1(xt−1−αˉtβtϵ)
因此模型预测均值可以写成:
μθ(xt,t)=αt1(xt−1−αˉtβtϵθ(xt,t))
那么为什么经典 DDPM 为简化训练通常固定方差呢?
在 DDPM 中,反向过程被定义为 pθ(xt−1∣xt)=N(xt−1;μθ(xt,t),Σθ(xt,t))。作者提出,方差 Σθ 其实不需要学习,因为它被“夹”在两个极端假设之间。
这两个界限分别代表了我们对真实图像 x0 的认知极端:
1. 下界 (Lower Bound): β~t —— 假设我们完全知道 x0
在上文推导 q(xt−1∣xt,x0) 时,配方后不仅得到了均值,也得到了方差 β~t:
β~t=1−αˉt1−αˉt−1βt
这代表什么意义?这是在“给定起点 x0 和终点 xt”的条件下,倒推中间状态 xt−1 的不确定性。因为你连最终的清晰图都看到了,所以此时预测上一步状态的“不确定性”(方差) 是最小的。这就是理论上的最小方差(下界)。
2. 上界 (Upper Bound): βt —— 假设我们对 x0 一无所知
如果我们对生成的最终图像 x0 没有任何先验知识,我们可以假设 x0 也是一个标准正态分布 N(0,I) (完全的噪声)。
在作者的推导论述中提到,如果假设 x0∼N(0,I),那么前向过程和反向过程的方差近似是对称的。此时反向跳一步的方差 q(xt−1∣xt) 就约等于前向加噪一步的方差:
Σ≈βt
这是在没有任何 x0 信息指导下,我们瞎猜上一步状态时的最大不确定性。这就是理论上的最大方差(上界)。
在 DDPM 的设定中,总步数 T=1000。
- 在生成过程的早期 (t 很大,接近纯噪声时): αˉt 趋近于 0。此时看下界公式: β~t=1−01−0βt=βt。上下界完全重合!
- 在生成过程的末期 (t 很小,接近清晰图时): 虽然 β~t 和 βt 开始有差异,但在经典 DDPM 的参数设定中,βt 被设定为一个非常小的常数(如从 0.0001 到 0.02 线性递增)。因为基数极小,所以它们绝对数值上的差异微乎其微。
正因为在这个极小的区间内,取上限还是取下界对最终生成图像的质量影响不大,Ho et al. 在实验后决定:干脆不让神经网络学了,直接在 βt 或 β~t 里面挑一个当常数固定下来(论文中最终主要使用了上限 βt)。这样直接大幅简化了计算。
最终训练流程
之前我们说,中间的 KL 项是:
Lt−1=DKL(q(xt−1∣xt,x0)∥pθ(xt−1∣xt))
二者都是高斯分布:
q(xt−1∣xt,x0)=N(xt−1;μ~t,β~tI)
pθ(xt−1∣xt)=N(xt−1;μθ,σt2I)
如果方差固定,那么两个高斯分布的 KL 散度主要就变成两个均值之间的平方误差:
DKL∝∣μ~t−μθ(xt,t)∣2
由于 μ~t 可以用真实噪声 ϵ 表示,而 μθ 可以用预测噪声 ϵθ 表示,所以这个误差可以进一步转化为:
∣ϵ−ϵθ(xt,t)∣2
于是 DDPM 最常用的简化训练目标是:
Lsimple=Et,x0,ϵ[∣ϵ−ϵθ(αˉtx0+1−αˉtϵ,t)∣2]
这就是 DDPM 的经典训练损失。
因此最终的训练流程简化如下:
- 从数据集中采样真实图片 x0;
- 随机采样时间步 t∼Uniform(1,T);
- 采样噪声 ϵ∼N(0,I);
- 构造带噪图片:
xt=αˉtx0+1−αˉtϵ
- 用神经网络预测噪声:
ϵθ(xt,t)
- 最小化:
∣ϵ−ϵθ(xt,t)∣2
这就是整个训练。
采样过程
训练完成后,从纯噪声开始:
xT∼N(0,I)
然后对:
t=T,T−1,…,1
重复:
xt−1=μθ(xt,t)+σtz
其中:
z∼N(0,I)
而:
μθ(xt,t)=αt1(xt−1−αˉtβtϵθ(xt,t))
所以采样公式是:
xt−1=αt1(xt−1−αˉtβtϵθ(xt,t))+σtz
当 t>1 时加入噪声 z;当 t=1 时通常不再加噪声。
当 t 很小时:
xt
接近真实图片,只带一点点噪声。模型主要学习局部细节修复。
当 t 很大时:
xt
接近纯噪声,几乎看不出原图。模型需要学习数据分布的整体结构,比如:
- 图片里大概有什么物体;
- 物体布局是什么;
- 语义结构是什么;
- 图像整体风格是什么。
所以扩散模型不是一步生成图片,而是从粗到细逐步恢复:
global structure→object shape→texture details
这也是扩散模型生成质量很高的重要原因。
DDPM 的整体算法总结
训练算法
重复以下步骤:
x0∼q(x0)
t∼Uniform(1,…,T)
ϵ∼N(0,I)
构造:
xt=αˉtx0+1−αˉtϵ
优化:
θmin∣ϵ−ϵθ(xt,t)∣2
采样算法
先采样:
xT∼N(0,I)
然后对于:
t=T,T−1,…,1
执行:
xt−1=αt1(xt−1−αˉtβtϵθ(xt,t))+σtz
其中:
z∼N(0,I)
最终得到:
x0