Diffusion Model 的基本原理与模型架构
如果需要简洁地说明扩散模型的基本原理,可以沿着刚才的顺序表达:
扩散模型先定义前向加噪过程,把真实数据逐渐变成接近高斯分布的噪声,再学习对应的反向生成过程。以经典 DDPM 为例,训练时随机采样时间步,通过闭式公式直接构造带噪样本,再训练网络预测加入的噪声。生成时从高斯噪声出发,反复调用同一个网络,并根据采样公式逐步更新样本,最终得到图片。网络骨干可以采用 U-Net,也可以采用 DiT 等 Transformer 架构。
如果继续介绍 Stable Diffusion,就接着解释它怎样降低图像生成的计算开销:
经典 Stable Diffusion 把扩散放在自编码器的潜空间中。训练图片先编码成 latent,扩散模型在 latent 上学习;生成时从潜空间噪声开始,逐步生成干净 latent,最后通过解码器恢复图片。文生图时,文本编码器提供条件特征,并通过交叉注意力等机制参与去噪预测。
Diffusion Model(扩散模型)是一类生成模型。理解它时,可以先抓住这样一个整体过程:
逐渐加噪 → 学习去噪 → 从噪声逐渐生成数据。
其中,"怎样加噪、怎样学习、怎样一步步生成"描述的是生成方法;"用什么神经网络完成预测"描述的是网络架构。经典 DDPM 经常使用 U-Net,DiT 则使用 Transformer。Stable Diffusion 又把自编码器、文本编码器和潜空间中的生成模型组合成一个完整系统。
这些名称之间的关系,等看完完整流程后再回过头整理会更容易。我们先从最经典的 DDPM 开始,看看一张图片怎样变成噪声,以及模型怎样学会从噪声生成图片。
1 先看 Diffusion 到底在做什么
假设我们希望模型生成图片。训练集中有一张真实图片,记作 x 0 x_0 x0。
训练时,我们向这张图片加入不同程度的噪声,得到带噪图片 x t x_t xt,再让模型学习如何去噪:
真实图片 x 0 x_0 x0 → 加噪得到 x t x_t xt → 让模型学习去噪
生成时,从一张随机高斯噪声开始,反复执行去噪更新:
x T ⟶ x T − 1 ⟶ ⋯ ⟶ x 0 x_T \;\longrightarrow\; x_{T-1} \;\longrightarrow\; \cdots \;\longrightarrow\; x_0 xT⟶xT−1⟶⋯⟶x0
在这条生成路径中, x T x_T xT 是起始噪声, x 0 x_0 x0 是最终生成的图片。下标 t t t 表示当前处于哪个噪声水平;在这里采用的 DDPM 记号中, t t t 越大,通常意味着噪声越强。
先保留这个整体认识:训练时利用真实图片构造去噪任务,生成时把学到的去噪能力反复用起来。 下面分别展开这两个过程。
2 第一步 Forward Process 逐渐加噪
从真实图片 x 0 x_0 x0 开始,我们不断加入高斯噪声:
x 0 → x 1 → x 2 → ⋯ → x T x_0 \rightarrow x_1 \rightarrow x_2 \rightarrow \cdots \rightarrow x_T x0→x1→x2→⋯→xT
开始时,图像只受到一点干扰,仍然能看出物体。随着加噪继续,结构和细节越来越难辨认。噪声累计足够多以后,末端样本的分布就接近标准高斯分布,图像看起来基本只剩下噪声。
在经典 DDPM 中,每一步写成:
q ( x t ∣ x t − 1 ) = N ( 1 − β t x t − 1 , β t I ) q(x_t \mid x_{t-1}) = \mathcal{N}\left( \sqrt{1-\beta_t}\,x_{t-1}, \beta_t I \right) q(xt∣xt−1)=N(1−βt xt−1,βtI)
这个式子表示:给定上一步的图片 x t − 1 x_{t-1} xt−1,下一步 x t x_t xt 从一个高斯分布中采样。实际操作可以写得更直观:
x t = 1 − β t x t − 1 + β t η t , η t ∼ N ( 0 , I ) x_t = \sqrt{1-\beta_t}\,x_{t-1} + \sqrt{\beta_t}\,\eta_t, \qquad \eta_t \sim \mathcal{N}(0,I) xt=1−βt xt−1+βt ηt,ηt∼N(0,I)
也就是先把原来的信号适当缩小,再加上一份新采样的高斯噪声。 β t \beta_t βt 控制这一步加入的噪声方差;每一步取多大的 β t \beta_t βt,由噪声调度决定。
不过实际训练不会真的一步一步执行:
x 0 → x 1 → ⋯ → x t x_0 \rightarrow x_1 \rightarrow \cdots \rightarrow x_t x0→x1→⋯→xt
例如,这次训练需要第 500 步的带噪图片,并不需要先把前面 499 步全部算出来。因为这个加噪过程有一个很方便的性质:可以从原图直接采样任意时间步的带噪图片。
具体公式是:
x t = α ˉ t x 0 + 1 − α ˉ t ϵ ϵ ∼ N ( 0 , I ) x_t = \sqrt{\bar{\alpha}_t}\,x_0 + \sqrt{1-\bar{\alpha}_t}\,\epsilon \qquad \epsilon \sim \mathcal{N}(0,I) xt=αˉt x0+1−αˉt ϵϵ∼N(0,I)
这里:
α t = 1 − β t , α ˉ t = ∏ s = 1 t α s \alpha_t = 1-\beta_t, \qquad \bar{\alpha}t = \prod{s=1}^{t}\alpha_s αt=1−βt,αˉt=s=1∏tαs
α ˉ t \bar{\alpha}_t αˉt 把前面各步对信号的保留程度累计起来。因此,可以把 x t x_t xt 直观地理解为:
一部分原始图片,加上一部分随机噪声。
随着 t t t 增大, α ˉ t \bar{\alpha}_t αˉt 通常越来越小,原始图片的成分逐渐减弱,噪声的成分逐渐增强。
所以,在一次训练中,我们只需要拿到原图 x 0 x_0 x0,随机抽一个时间步 t t t,再采样一份噪声 ϵ \epsilon ϵ,就能直接构造这次要用的 x t x_t xt。它与逐步加噪到第 t t t 步得到的样本服从相同的条件分布;训练不必真的沿着整条加噪路径走一遍。
这也为下一步提供了一个很重要的条件:这张带噪图片是我们自己构造的,因此我们知道这次用了哪一份噪声 ϵ \epsilon ϵ。
Forward process基本上是人为规定好的数学过程,没有什么需要学习的参数。真正需要神经网络学习的是 Reverse Process
Diffusion 有一个很典型的特点:
训练时可以随机抽一个 (t) 一步训练;生成时却通常需要进行多步迭代。
这也是 Diffusion 推理速度长期以来比 GAN / VAE 一次前向生成慢的重要原因之一。
这个生成包括训练时候的去噪生成吗?训练的时候去噪生成也需要多步迭代吗
不需要。经典 Diffusion 训练时的"去噪训练"通常只做一步网络预测,不会真的从 (x_t) 一路迭代生成到 (x_0)。
这里的"生成"容易把训练 和推理混在一起。
训练时:只训练某一个随机时间步
假设真实图片是 (x_0)。
先随机采样:
t = 700 , ϵ ∼ N ( 0 , I ) t=700,\qquad \epsilon\sim\mathcal N(0,I) t=700,ϵ∼N(0,I)
直接构造:
x 700 = α ˉ 700 x 0 + 1 − α ˉ 700 ϵ x_{700} = \sqrt{\bar\alpha_{700}}x_0+ \sqrt{1-\bar\alpha_{700}}\epsilon x700=αˉ700 x0+1−αˉ700 ϵ
然后只进行一次模型前向:
x 700 , 700 → U-Net/DiT ϵ ^ \boxed{ x_{700},700 \xrightarrow{\text{U-Net/DiT}} \hat\epsilon } x700,700U-Net/DiT ϵ^
计算:
L = ∥ ϵ − ϵ ^ ∥ 2 L=\|\epsilon-\hat\epsilon\|^2 L=∥ϵ−ϵ^∥2
然后反向传播、更新参数。
到这里这一条训练样本就结束了。
不会继续:
x 700 → x 699 → x 698 → ⋯ → x 0 x_{700}\rightarrow x_{699}\rightarrow x_{698}\rightarrow\cdots\rightarrow x_0 x700→x699→x698→⋯→x0
因此训练过程更准确地叫去噪目标训练,而不是实际完成一次完整的去噪生成。
推理/生成时:才需要多步迭代
真正生成一张新图片时,没有真实 (x_0) 给你。
只能先随机采样纯噪声:
x T ∼ N ( 0 , I ) x_T\sim\mathcal N(0,I) xT∼N(0,I)
然后:
x T → M o d e l x T − 1 → M o d e l x T − 2 → ⋯ → x 0 x_T \xrightarrow{Model} x_{T-1} \xrightarrow{Model} x_{T-2} \rightarrow\cdots\rightarrow x_0 xTModel xT−1Model xT−2→⋯→x0
也就是说同一个 U-Net / DiT 会被调用很多次:
text
纯噪声 x_T
↓ Model
x_{T-1}
↓ Model
x_{T-2}
↓ Model
...
↓ Model
生成图片 x_0
所以我们说:
训练:随机一个 t ,通常一次模型预测 \boxed{\text{训练:随机一个 }t\text{,通常一次模型预测}} 训练:随机一个 t,通常一次模型预测
推理:多个 t ,多次模型预测 \boxed{\text{推理:多个 }t\text{,多次模型预测}} 推理:多个 t,多次模型预测
那为什么只训练一步,推理却能连续去噪?
因为训练过程中,每个 batch 都会随机抽不同的 (t)。
比如:
t = 13 , 487 , 920 , 231 , ... t=13,\quad 487,\quad 920,\quad 231,\ldots t=13,487,920,231,...
训练足够久以后,模型实际上学会了各种噪声程度下应该怎么处理:
( x t , t ) → 去噪方向 (x_t,t)\rightarrow \text{去噪方向} (xt,t)→去噪方向
因此推理时就可以把这些能力串起来:
x 1000 → x 999 → ⋯ → x 1 → x 0 \boxed{ x_{1000}\rightarrow x_{999}\rightarrow\cdots\rightarrow x_1\rightarrow x_0 } x1000→x999→⋯→x1→x0
可以类比成:训练时随机抽一道"第 (t) 阶段怎么去噪"的题来练;推理时把各阶段的能力连续使用,完成整条生成过程。
3 第二步 Reverse Process 学习去噪
加噪的规则是事先规定好的。真正需要学习的是反方向:给你一张带噪图片 x t x_t xt,怎样得到噪声更少的 x t − 1 x_{t-1} xt−1?
从概率模型的角度,我们希望学习:
p_\\theta(x_ {t-1}\\mid x_t)
其中, θ \theta θ 表示神经网络的参数。这个分布描述了:在当前样本为 x t x_t xt 时,反向生成的下一步可能是什么样子。
经典 DDPM 中有一种很巧妙、也很容易实现的做法:
让神经网络预测构造 x t x_t xt 时加入的噪声。
回到刚才的加噪公式:
x t = α ˉ t x 0 + 1 − α ˉ t ϵ x_t = \sqrt{\bar{\alpha}_t}\,x_0 + \sqrt{1-\bar{\alpha}_t}\,\epsilon xt=αˉt x0+1−αˉt ϵ
训练时, x 0 x_0 x0 是已知的训练图片, ϵ \epsilon ϵ 是程序自己采样的噪声, x t x_t xt 是计算出来的结果。于是我们把 x t x_t xt 和 t t t 输入网络:
ϵ ^ = ϵ θ ( x t , t ) \hat{\epsilon} = \epsilon_\theta(x_t,t) ϵ^=ϵθ(xt,t)
ϵ θ \epsilon_\theta ϵθ 是这个噪声预测网络, ϵ ^ \hat{\epsilon} ϵ^ 是它的输出。我们希望网络的预测接近已知的 ϵ \epsilon ϵ:
ϵ ^ ≈ ϵ \hat{\epsilon} \approx \epsilon ϵ^≈ϵ
为什么还要输入时间步 t t t?因为模型需要知道这张图片目前受到了多强的噪声干扰。在轻噪声和重噪声状态下,图像中可利用的信息不同,网络需要据此调整预测。
有了已知的目标噪声,就可以直接比较"真实加入的噪声"和"网络预测的噪声"。最经典的简化训练目标是:
L s i m p l e = E x 0 , t , ϵ ∥ ϵ − ϵ θ ( x t , t ) ∥ 2 2 L_{\mathrm{simple}} = \mathbb{E}_{x_0,t,\epsilon} \left \\left\\\| \\epsilon-\\epsilon_\\theta(x_t,t) \\right\\\|_2\^2 \\right Lsimple=Ex0,t,ϵ∥ϵ−ϵθ(xt,t)∥22
也就是:你加入了什么噪声,就让模型把这份噪声预测出来。
这项损失会惩罚预测误差。随着模型看过越来越多图片,以及同一类图片在不同噪声水平下的样子,它逐渐学会根据带噪状态和时间步估计噪声。这里的监督目标来自加噪程序本身,无需人为标注。
把一次训练更新连起来,就是:
- 从训练集中取真实图片 x 0 x_0 x0。
- 随机采样时间步 t t t 和高斯噪声 ϵ \epsilon ϵ。
- 直接计算 x t = α ˉ t x 0 + 1 − α ˉ t ϵ x_t=\sqrt{\bar{\alpha}_t}x_0+\sqrt{1-\bar{\alpha}_t}\epsilon xt=αˉt x0+1−αˉt ϵ。
- 把 ( x t , t ) (x_t,t) (xt,t) 输入网络,得到 ϵ ^ \hat{\epsilon} ϵ^。
- 比较 ϵ ^ \hat{\epsilon} ϵ^ 与 ϵ \epsilon ϵ,反向传播并更新网络参数。
实际通常按一批样本计算。反复抽取图片、时间步和噪声,使同一个网络能够学习不同噪声水平下的去噪任务。
4 生成图片时 把学到的预测能力反复用起来
到这里,训练出了一个怎样的网络就清楚了。对于刚才这个 DDPM 例子,单次网络调用完成的是:
( x t , t ) ⟶ ϵ ^ (x_t,t)\longrightarrow\hat{\epsilon} (xt,t)⟶ϵ^
可以把它理解为:给我"当前时间步的带噪图片",我来估计其中的噪声。
那预测噪声为什么有助于生成图片?因为加噪公式把原图、带噪图和噪声联系在了一起。如果知道噪声,就可以把公式移项,恢复原图;把真实噪声换成网络的预测,就得到对干净图片的估计:
x ^ 0 = x t − 1 − α ˉ t ϵ ^ α ˉ t \hat{x}_0 = \frac{ x_t-\sqrt{1-\bar{\alpha}_t}\,\hat{\epsilon} }{ \sqrt{\bar{\alpha}_t} } x^0=αˉt xt−1−αˉt ϵ^
这说明了噪声预测与去噪之间的联系。不过在噪声很强时,网络的一次预测还不够准确。经典生成过程会先依据当前预测,按采样公式把样本更新到更低的噪声水平,再重新预测。
因此,生成一张图片时,先从标准高斯分布采样起始噪声:
x T ∼ N ( 0 , I ) x_T \sim \mathcal{N}(0,I) xT∼N(0,I)
然后把 ( x T , T ) (x_T,T) (xT,T) 输入网络,根据预测结果计算下一步 x T − 1 x_{T-1} xT−1;再把 ( x T − 1 , T − 1 ) (x_{T-1},T-1) (xT−1,T−1) 输入同一个网络,继续得到 x T − 2 x_{T-2} xT−2。这样不断重复:
x T → x T − 1 → x T − 2 → ⋯ → x 0 x_T \rightarrow x_{T-1} \rightarrow x_{T-2} \rightarrow \cdots \rightarrow x_0 xT→xT−1→xT−2→⋯→x0
整个过程中,同一个去噪网络会被反复调用很多次。 每一步都使用当前的样本和当前时间步,网络参数在生成时保持固定。
这里也就能区分训练和生成了:训练时有真实图片,可以直接构造随机时间步的训练样本;生成时从噪声开始,需要依靠模型把当前样本一步步推进到图片。
负责"根据预测结果算出下一步"的部分,通常称为采样器。DDPM 和 DDIM 可以采用不同的采样构造;DDIM 能在兼容的训练目标下使用不同的生成轨迹和较少的采样步数。先理解网络给出预测、采样器利用预测更新样本,后面再看具体采样公式就容易对上各个部分。
5 去噪网络怎样实现 先看 U-Net
前面一直用 ϵ θ ( x t , t ) \epsilon_\theta(x_t,t) ϵθ(xt,t) 表示网络,还没有规定它内部长什么样。
经典图像扩散模型中,最常见的选择之一是 U-Net。于是单次预测可以画成:
x t ⟶ U-Net ⟶ ϵ ^ x_t \longrightarrow \text{U-Net} \longrightarrow \hat{\epsilon} xt⟶U-Net⟶ϵ^
时间步也要进入网络,通常先变成一个时间步嵌入:
t ⟶ E m b ( t ) t \longrightarrow \mathrm{Emb}(t) t⟶Emb(t)
两部分合起来,就是下面的表达式,其中 UNet 表示 U-Net:
ϵ θ ( x t , t ) = U N e t ( x t , E m b ( t ) ) \epsilon_\theta(x_t,t) = \mathrm{UNet}\left(x_t,\mathrm{Emb}(t)\right) ϵθ(xt,t)=UNet(xt,Emb(t))
U-Net 的基本结构,是先逐层下采样,再逐层上采样:
text
带噪图片 x_t
│
▼
高分辨率特征 ──────────────────► 高分辨率特征
│ ▲
下采样 上采样
▼ │
中分辨率特征 ──────────────► 中分辨率特征
│ ▲
下采样 上采样
▼ │
低分辨率特征 ───► 瓶颈层 ────────┘
右侧高分辨率特征 → 输出层 → 预测噪声
横向的连接就是 Skip Connection(跳跃连接):把下采样路径中某个尺度的特征,直接传给上采样路径中相应尺度的层。
为什么这样的结构适合去噪?因为判断噪声时,模型既需要较大范围的图像信息,也需要局部细节。下采样让后续层能够综合更大范围的信息;上采样逐步恢复空间分辨率;跳跃连接则让较早的细节特征能够直接传到后面的层。
例如,模型既要利用整体形状判断这里可能是一只狗,又要处理毛发、轮廓等局部信息。多尺度特征与跳跃连接有助于把这两类信息结合起来。实际扩散 U-Net 中还常包含残差块和注意力模块。
注意,图中的整个 U-Net 只对应一次网络调用。生成图片时,前一节的多步过程会反复调用这个完整网络。
6 从像素空间走到潜空间 理解 Stable Diffusion
现在已经知道怎样在图片上加噪,以及怎样用 U-Net 预测噪声。如果直接在 RGB 图片上执行这些操作,就是 Pixel-space Diffusion(像素空间扩散)。
例如,一张图片的形状是:
x 0 ∈ R 3 × 512 × 512 x_0\in\mathbb{R}^{3\times512\times512} x0∈R3×512×512
那么带噪图片 x t x_t xt 仍然是这个大小,网络需要反复处理相应的图像张量。随着图像分辨率提高,这种多步计算的开销会变大。
这就自然引出了另一个想法:能不能先把图片压缩成更小的表示,再在这种表示上做扩散?
这就是 Latent Diffusion(潜空间扩散) 的核心思路,也是经典 Stable Diffusion 的关键组成部分。
先用自编码器的编码器把图片变成 latent:
x ⟶ VAE Encoder ⟶ z 0 x \longrightarrow \text{VAE Encoder} \longrightarrow z_0 x⟶VAE Encoder⟶z0
例如,在经典 Stable Diffusion 的一种常见配置中:
3 × 512 × 512 ⟶ 4 × 64 × 64 3\times512\times512 \longrightarrow 4\times64\times64 3×512×512⟶4×64×64
图片被转换成空间尺寸更小的潜变量张量。接下来,扩散过程发生在这个 z z z 上:
z 0 → z 1 → ⋯ → z T z_0\rightarrow z_1\rightarrow\cdots\rightarrow z_T z0→z1→⋯→zT
加噪、噪声预测和损失的思路,与前面在图片上做扩散相同,只是处理对象从 x x x 换成了 z z z。训练时,同样可以直接构造随机时间步的 z t z_t zt。
生成时,先采样潜空间中的高斯噪声,再逐步生成干净的 latent:
z T → z T − 1 → ⋯ → z 0 z_T\rightarrow z_{T-1}\rightarrow\cdots\rightarrow z_0 zT→zT−1→⋯→z0
最后,把 z 0 z_0 z0 交给解码器,恢复成图片:
z 0 ⟶ VAE Decoder ⟶ x z_0 \longrightarrow \text{VAE Decoder} \longrightarrow x z0⟶VAE Decoder⟶x
这样,前面学过的 VAE 就接上来了:编码器把图片转换成 latent,扩散模型学习生成 latent,解码器再把 latent 转换成图片。
把训练和生成分开画,会更清楚:
text
训练潜空间扩散模型
真实图片
│
▼
VAE Encoder
│
▼
干净 latent z_0
│
├── 随机时间步 t
└── 随机噪声 ε
│
▼
直接构造带噪 latent z_t
│
▼
去噪网络预测 ε
│
▼
与已知噪声比较,更新去噪网络
text
生成新图片
随机潜空间噪声 z_T
│
▼
反复调用去噪网络,并由采样器更新
│
▼
干净 latent z_0
│
▼
VAE Decoder
│
▼
生成图片
在经典两阶段方案中,自编码器先训练好,随后固定它来训练扩散模型。纯文生图时没有输入图片需要编码,因此从 z T z_T zT 开始,最后使用解码器即可;图生图任务有输入图片,才需要先用编码器取得它的 latent。
7 让文字参与生成 Text-to-Image 的条件输入
前面描述的流程已经可以从噪声生成图片。但如果希望指定"生成什么",例如:
a black dog running on the beach
还需要让去噪网络知道这段文字的含义。
首先,把文字交给 Text Encoder(文本编码器) 。它把文本转换为一组特征,记作 c c c:
text ⟶ Text Encoder ⟶ c \text{text} \longrightarrow \text{Text Encoder} \longrightarrow c text⟶Text Encoder⟶c
经典 Stable Diffusion 使用过 CLIP 文本编码器;具体文本编码器会随模型版本变化。这里先关注它的职责:把文字转换成后续网络可以使用的条件特征。
于是,采用噪声预测时,去噪网络的输入从 ( z t , t ) (z_t,t) (zt,t) 扩展为:
ϵ θ ( z t , t , c ) \epsilon_\theta(z_t,t,c) ϵθ(zt,t,c)
这三个输入分别告诉网络:
- z t z_t zt:当前的带噪图像表示是什么样。
- t t t:当前处于哪个噪声水平。
- c c c:希望生成什么内容。
这样,同样是从噪声开始,预测过程就可以受到"黑狗""奔跑""海滩"等文本信息的影响。
在经典 Stable Diffusion 的 U-Net 中,文本条件主要通过 Cross-Attention(交叉注意力) 注入。如果已经了解 Q、K、V,可以这样对应:
Q Q Q 来自图像特征的投影, K K K 和 V V V 来自文本特征的投影。
然后计算:
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V \mathrm{Attention}(Q,K,V) = \mathrm{softmax} \left( \frac{QK^\mathsf{T}}{\sqrt{d_k}} \right)V Attention(Q,K,V)=softmax(dk QKT)V
直观上,每个图像位置会根据自己的特征,去选择当前更需要参考哪些文本信息。生成狗的相关区域可能更关注 "black""dog",背景相关区域可能更关注 "beach"。这些是学习到的注意力关联。
因此,文生图的过程可以连成:
text
文字 → 文本编码器 → 文本条件 c
│
▼
随机 latent → 反复进行有条件的去噪更新 → 干净 latent
│
▼
VAE Decoder
│
▼
图片
文字条件会参与多步生成,影响图像内容逐渐形成的过程。
8 有了整体流程 再理解不同的模型家族
到这里,我们已经能把经典文生图系统串起来了:自编码器提供潜空间,文本编码器提供条件,去噪网络给出预测,采样器推进生成,最后解码为图片。
这时再看 DDPM、DDIM、Stable Diffusion、DiT 等名称,就会发现它们经常描述的是不同层面的选择。
理解模型名称时先区分这些维度
| 维度 | 回答的问题 | 常见选择或例子 |
|---|---|---|
| 生成方法 | 如何连接噪声分布与数据分布 | DDPM、Score-based SDE、Flow Matching |
| 数据空间 | 在哪种表示上生成 | 像素空间、潜空间 |
| 网络架构 | 用什么网络完成预测 | U-Net、DiT 等 Transformer |
| 预测目标 | 网络具体输出什么 | 噪声 ε、干净样本 x 0 x_0 x0、v 或速度场 |
| 采样方法 | 如何利用预测推进生成 | DDPM 采样、DDIM、ODE 求解器 |
| 条件信息 | 生成结果受什么控制 | 无条件、类别、文本、其他图像 |
| 层次 | 解决的问题 | 例子 |
|---|---|---|
| 生成/数学框架 | 数据怎么从噪声变过来? | DDPM、Score/SDE、Flow Matching |
| 预测目标 | 网络到底预测什么? | (\epsilon)、(x_0)、(v)、score/vector field |
| Backbone | 用什么神经网络预测? | U-Net、Transformer/DiT |
| 数据空间 | 在哪里进行生成? | Pixel Space、Latent Space |
这些维度可以组合。例如,一个模型可以同时属于"潜空间生成""Transformer 架构"和"文本条件生成"。DDPM、Stable Diffusion、DiT 因而不构成互斥且一一对应的架构分类。
从生成过程看,DDPM 给出了经典的离散时间加噪与反向生成框架。Score-based 模型从不同噪声水平下的 score 来描述生成,SDE 则提供了连续时间的随机过程表述。Flow Matching、Rectified Flow 是与这些研究相联系的连续流生成方法,常通过学习速度场,把噪声逐渐转成数据。
从处理空间看,可以在原始像素空间生成,也可以像前面介绍的 Latent Diffusion 一样,在自编码器的潜空间中生成。
从网络架构看,可以用 U-Net,也可以使用 Transformer。DiT(Diffusion Transformer) 就属于后一条架构路线,下一节具体展开。
从采样方式看,训练好的网络需要配合相应的更新规则。DDIM 就是与 DDPM 训练目标兼容的一类生成与采样构造,它与"使用 U-Net 还是 Transformer"是不同的问题。
所以,一个模型完全可以同时具备"潜空间""Transformer""文本条件"这几个特点。Stable Diffusion 或 FLUX 这样的具体模型系列,则要结合版本,看它究竟采用了哪些组件与方法。
这个分类的作用,是帮助我们把每个名称放回刚才的完整流程中:它究竟改变了流程的哪一部分?
9 DiT 用 Transformer 完成去噪预测
前面已经看过 U-Net。如果希望用 Transformer 承担预测任务,可以先把这个变化理解为:
z t ⟶ U-Net ⟶ ϵ ^ z_t \longrightarrow \text{U-Net} \longrightarrow \hat{\epsilon} zt⟶U-Net⟶ϵ^
变成:
z t ⟶ Transformer ⟶ ϵ ^ z_t \longrightarrow \text{Transformer} \longrightarrow \hat{\epsilon} zt⟶Transformer⟶ϵ^
这里为了便于对照,仍然以预测噪声为例。网络输出的具体目标可以另外选择。
Transformer 处理的是 token 序列,因此首先需要把带噪 latent 变成 token。假设:
z t ∈ R C × H × W z_t\in\mathbb{R}^{C\times H\times W} zt∈RC×H×W
将它在空间上切成若干个 patch:
z t ⟶ { p 1 , p 2 , ... , p N } z_t\longrightarrow\{p_1,p_2,\ldots,p_N\} zt⟶{p1,p2,...,pN}
再把每个 patch 投影成一个 D D D 维 token,得到:
X ∈ R N × D X\in\mathbb{R}^{N\times D} X∈RN×D
这一步和 ViT 很相似:把空间上的小块转换成序列中的元素,再用 Transformer 建模它们之间的关系。
完整过程大致是:
text
带噪 latent z_t
│
▼
Patchify / Projection
│
▼
Token 序列,加上位置信息
│
▼
Transformer Blocks ◄── 时间步及其他条件
│
▼
输出投影并重排回空间张量
│
▼
噪声或其他指定目标的预测
原始 DiT 在潜空间中用 Transformer 替换常见的 U-Net 骨干,并研究了时间步、类别等条件的注入方式。后续模型还可以发展不同的图文交互结构。
因此,"把 U-Net 换成 Transformer"能说明 DiT 在完整系统中替换了哪个部件;进一步看内部结构,就会看到 patch 划分、token 序列、注意力计算和输出重排这些不同之处。
无论采用哪一种骨干,前面那条联系仍然成立:网络接收当前带噪状态和时间等条件,给出预测,再由生成过程使用这个预测推进样本。
10 再向外扩展 网络也可以预测其他量
刚才一直用 ϵ θ \epsilon_\theta ϵθ 表示网络,是为了把经典 DDPM 的噪声预测讲清楚。但扩散模型也可以使用其他预测目标。
一种选择是直接预测干净样本:
x ^ 0 = x θ ( x t , t ) \hat{x}0=x\theta(x_t,t) x^0=xθ(xt,t)
前面已经看到,给定 x t x_t xt、噪声水平和噪声预测,可以计算干净样本的估计。因此,预测噪声与预测干净样本之间有数学联系。具体模型可以选择不同的参数化,并配合相应的损失和采样公式。
还有一种常见选择是 v v v-prediction。在一种常用定义中,令:
a t = α ˉ t , s t = 1 − α ˉ t a_t=\sqrt{\bar{\alpha}_t}, \qquad s_t=\sqrt{1-\bar{\alpha}_t} at=αˉt ,st=1−αˉt
则训练目标为:
v t = a t ϵ − s t x 0 v_t=a_t\epsilon-s_t x_0 vt=atϵ−stx0
它是信号与噪声的一个特定组合,网络学习预测这个组合。
在 Flow Matching 或 Rectified Flow 中,也经常看到:
v θ ( x t , t ) v_\theta(x_t,t) vθ(xt,t)
这里通常表示沿所定义生成路径的速度场 :告诉当前状态在这个时间应该朝什么方向、以怎样的速度变化,再通过数值求解逐步生成数据。它的具体定义由所选路径决定,不能仅凭都使用字母 v v v 就认为它与前面的扩散 v v v-prediction 完全相同。
第一次学习时,先把 DDPM 的"已知加噪规则 → 构造训练样本 → 学习预测 → 反复更新生成"理解清楚,再扩展到这些目标与生成路径,会更容易看清它们之间的关系。
11 把原理 架构与完整系统放到一起
现在可以回到最开始的问题:Diffusion Model 是否存在不同家族,以及不同的模型架构?
可以这样整理已经走过的内容:
text
扩散与相关的连续流生成模型
│
├─ 生成过程怎样定义
│ ├─ DDPM
│ ├─ Score-based / SDE
│ └─ Flow Matching / Rectified Flow
│
├─ 在什么空间中生成
│ ├─ Pixel Space
│ └─ Latent Space
│ └─ 自编码器负责图像与 latent 的转换
│
├─ 由什么网络完成预测
│ ├─ U-Net
│ └─ Transformer,例如 DiT
│
├─ 网络预测什么
│ ├─ 噪声 ε
│ ├─ 干净样本 x_0
│ └─ v 或所定义路径的速度场
│
├─ 怎样利用预测生成下一步
│ └─ 与模型兼容的采样器或求解器
│
└─ 如何控制生成内容
└─ 文本等条件,经编码后参与网络预测
这张图中的各条分支是不同维度,可以组合。对于经典的 U-Net 型 Stable Diffusion,可以把它放回我们已经理解的流程:
图片通过自编码器进入潜空间;扩散模型在 latent 上学习生成;文字通过文本编码器变成条件,参与 U-Net 的预测;生成时从潜空间噪声开始,经过多步更新得到 latent,再由解码器输出图片。
DiT 让我们看到,负责预测的骨干可以换成 Transformer。DDIM 让我们看到,生成时的采样轨迹也可以调整。Flow Matching 等方法则进一步改变了训练所依据的路径和预测目标。
这样,"扩散模型的原理"和"某个具体模型的架构"就能联系起来:前者说明生成为什么按这样的过程进行,后者说明由哪些网络部件把这个过程实现出来。
12 总结
如果需要简洁地说明扩散模型的基本原理,可以沿着刚才的顺序表达:
扩散模型先定义前向加噪过程,把真实数据逐渐变成接近高斯分布的噪声,再学习对应的反向生成过程。以经典 DDPM 为例,训练时随机采样时间步,通过闭式公式直接构造带噪样本,再训练网络预测加入的噪声。生成时从高斯噪声出发,反复调用同一个网络,并根据采样公式逐步更新样本,最终得到图片。网络骨干可以采用 U-Net,也可以采用 DiT 等 Transformer 架构。
如果继续介绍 Stable Diffusion,就接着解释它怎样降低图像生成的计算开销:
经典 Stable Diffusion 把扩散放在自编码器的潜空间中。训练图片先编码成 latent,扩散模型在 latent 上学习;生成时从潜空间噪声开始,逐步生成干净 latent,最后通过解码器恢复图片。文生图时,文本编码器提供条件特征,并通过交叉注意力等机制参与去噪预测。
后续要深入 DDPM 的数学,可以从前面已经出现的三个分布接着看:
q ( x t ∣ x t − 1 ) , q ( x t ∣ x 0 ) , p θ ( x t − 1 ∣ x t ) q(x_t\mid x_{t-1}), \qquad q(x_t\mid x_0), \qquad p_\theta(x_{t-1}\mid x_t) q(xt∣xt−1),q(xt∣x0),pθ(xt−1∣xt)
它们分别对应单步加噪、从原图直接构造任意时间步的样本,以及学习到的反向生成。先把这三个分布与训练、生成的实际步骤对上,再推导损失和反向采样公式。
来源与延伸阅读
正文沿分享对话的介绍顺序整理,关键公式与方法可结合以下原论文阅读。
- 原分享对话 解释扩散模型原理架构
- DDPM --- Denoising Diffusion Probabilistic Models
- DDIM --- Denoising Diffusion Implicit Models
- Latent Diffusion --- High-Resolution Image Synthesis with Latent Diffusion Models
- DiT --- Scalable Diffusion Models with Transformers
- Progressive Distillation for Fast Sampling of Diffusion Models
- Score-Based Generative Modeling through Stochastic Differential Equations
- Flow Matching for Generative Modeling
- Flow Straight and Fast --- Learning to Generate and Transfer Data with Rectified Flow