深入理解扩散模型 (Diffusion Model):从原理到实践

2646 字
13 分钟
深入理解扩散模型 (Diffusion Model):从原理到实践

1. 扩散模型的核心思想#

1.1 什么是扩散?#

扩散模型的核心思想可以用一个直观的比喻来理解:

想象一下:

  1. 前向扩散:将一杯干净的水中滴入墨水,墨水分子逐渐扩散,最终整杯水变成均匀的黑色
  2. 逆向去噪:如果你能将这个过程倒放——从黑色的水逐步去除墨水分子——你就能恢复出干净的水

扩散模型正是基于这个原理:学习从”噪声”逆向恢复到”数据”的过程。

1.2 扩散过程的两个阶段#

扩散模型包含两个核心过程:

  1. 前向过程 (Forward Process):逐步向数据添加噪声,直到变成纯噪声
  2. 逆向过程 (Reverse Process):学习从噪声中逐步恢复出原始数据

1.3 扩散过程示意#

以下展示了扩散模型在不同时间步的状态变化:

阶段时间步描述状态
原始T=0干净的数据清晰的图像/信号
早期T=250轻度噪声细节开始模糊
中期T=500中度噪声主要结构仍可见
后期T=750重度噪声仅剩轮廓
最终T=1000纯噪声完全随机

前向过程(训练时):从 T=0 到 T=T,逐渐添加噪声 逆向过程(生成时):从 T=T 到 T=0,逐步去除噪声生成图像

2. 前向扩散过程 (Forward Process)#

2.1 数学定义#

前向过程是一个预设的马尔可夫链,它逐步向数据添加高斯噪声。假设原始数据为 x0x_0,前向过程定义为:

q(xtxt1)=N(xt;1βtxt1,βtI)q(x_t | x_{t-1}) = \mathcal{N}(x_t; \sqrt{1 - \beta_t} x_{t-1}, \beta_t I)

其中 βt\beta_t 是第 tt 步的噪声调度参数,0<β1<β2<<βT<10 < \beta_1 < \beta_2 < \cdots < \beta_T < 1

2.2 关键性质:可直接采样任意时刻#

得益于高斯噪声的重参数化性质,我们可以直接计算出任意时刻 tt 的噪声图像 xtx_t

xt=αˉtx0+1αˉtϵx_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1 - \bar{\alpha}_t} \epsilon

其中:

  • ϵN(0,I)\epsilon \sim \mathcal{N}(0, I) 是标准高斯噪声
  • αt=1βt\alpha_t = 1 - \beta_t
  • αˉt=i=1tαi\bar{\alpha}_t = \prod_{i=1}^{t} \alpha_i

这个性质非常关键:我们不需要逐步迭代就能直接得到任意时刻的噪声图像,这大大简化了训练过程。

2.3 前向过程代码实现#

import torch
import numpy as np
def forward_diffusion(x0, t, betas):
"""
前向扩散过程:直接从 x0 计算 xt
x0: 原始图像 tensor
t: 时间步
betas: 噪声调度序列
"""
alphas = 1 - betas
alpha_bars = torch.cumprod(alphas, dim=0)
# 确保 t 是一维张量
t = t.unsqueeze(-1) if t.dim() > 0 else t
# 采样噪声
epsilon = torch.randn_like(x0)
# 重参数化采样
sqrt_alpha_bar = torch.sqrt(alpha_bars[t])
sqrt_one_minus_alpha_bar = torch.sqrt(1 - alpha_bars[t])
xt = sqrt_alpha_bar * x0 + sqrt_one_minus_alpha_bar * epsilon
return xt, epsilon

3. 逆向去噪过程 (Reverse Process)#

3.1 学习逆向分布#

逆向过程是扩散模型的核心——我们需要一个神经网络来学习 pθ(xt1xt)p_\theta(x_{t-1} | x_t)

理论上,逆向分布也是高斯分布:

pθ(xt1xt)=N(xt1;μθ(xt,t),Σθ(xt,t))p_\theta(x_{t-1} | x_t) = \mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \Sigma_\theta(x_t, t))

其中 μθ\mu_\thetaΣθ\Sigma_\theta 是由神经网络预测的参数。

3.2 简化预测目标#

为了简化训练,DDPM 论文提出了一个关键技巧:让网络预测噪声 ϵθ\epsilon_\theta,而不是直接预测均值

由前向过程的公式:

xt=αˉtx0+1αˉtϵx_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1 - \bar{\alpha}_t} \epsilon

我们可以推导出:

x0=xt1αˉtϵαˉtx_0 = \frac{x_t - \sqrt{1 - \bar{\alpha}_t} \epsilon}{\sqrt{\bar{\alpha}_t}}

因此,预测噪声就等价于预测原始图像,简化了学习目标。

3.3 逆向过程代码实现#

import torch
import torch.nn.functional as F
def p_sample(model, xt, t, betas):
"""
从 xt 采样 xt-1
"""
t = torch.tensor([t])
# 模型预测噪声
epsilon_theta = model(xt, t)
# 提取参数
beta_t = betas[t]
alpha_t = 1 - beta_t
alpha_bar_t = alpha_t.prod() # 简化的 cumprod
# 计算均值
mean = (1 / torch.sqrt(alpha_t)) * (
xt - (beta_t / torch.sqrt(1 - alpha_bar_t)) * epsilon_theta
)
# 如果是最后一步,直接返回均值
if t[-1] == len(betas) - 1:
return mean
# 计算方差
variance = beta_t
# 采样
noise = torch.randn_like(xt)
return mean + torch.sqrt(variance) * noise
def reverse_process(model, shape, betas):
"""
从纯噪声生成图像
"""
# 从纯噪声开始
xt = torch.randn(shape)
# 逐步去噪
for t in reversed(range(len(betas))):
xt = p_sample(model, xt, t, betas)
return xt

4. 噪声调度 (Noise Scheduling)#

4.1 为什么需要噪声调度?#

噪声调度(Noise Scheduling)决定了噪声如何随时间步增加——它直接影响模型的训练稳定性和生成质量。

4.2 常见的调度策略#

调度类型特点应用
线性 (Linear)均匀递增DDPM
余弦 (Cosine)平滑衰减Stable Diffusion
二次 (Quadratic)前期慢后期快early β scheduling
Scaled Linear缩放线性OpenAI guided diffusion

4.3 噪声调度可视化#

4.3 噪声调度对比#

不同调度策略下噪声水平的变化对比:

噪声水平
1.0 │ ▓▓▓▓▓▓▓▓▓▓
│ ▓▓▓▓▓▓▓▓
0.8 │ ▓▓▓▓▓▓▓▓
│ ▓▓▓▓▓▓▓▓ ← 二次 (Quadratic)
0.6 │ ▓▓▓▓▓▓▓▓ ●───●───●───●───●───●───●───●───●
│ ▓▓▓▓▓▓▓▓ ← 余弦 (Cosine) ─────────────────────────
0.4 │ ▓▓▓▓▓▓▓▓ ●───●───●───●───●───●───●───●───●───●───●───●───●───●───●
│ ← 线性 (Linear) ────────────────────────────────
0.2 │
0.0 │●───────────────────────────────────────────────────────────────
└────────────────────────────────────────────────────────────────
T=0 T=1000
调度类型特点前期噪声增长后期噪声增长适用场景
线性 (Linear)均匀递增DDPM 原始论文
余弦 (Cosine)平滑衰减很慢很快Stable Diffusion
二次 (Quadratic)前期慢后期快很慢很快早期实验

推荐:现代扩散模型(如 Stable Diffusion)普遍采用余弦调度,因为它在训练前期保持较高的信号水平,有助于模型学习有意义的特征。

4.4 调度策略代码对比#

def get_betas_schedule(schedule_type, T, beta_start=1e-4, beta_end=0.02):
"""生成不同类型的噪声调度序列"""
if schedule_type == "linear":
# 线性调度:从 beta_start 线性增加到 beta_end
return torch.linspace(beta_start, beta_end, T)
elif schedule_type == "cosine":
# 余弦调度:更平滑的过渡
steps = T + 1
x = torch.linspace(0, T, steps)
alphas_cumprod = torch.cos(((x / T) + 0.008) * torch.pi / 2) ** 2
alphas_cumprod = alphas_cumprod / alphas_cumprod[0]
betas = 1 - (alphas_cumprod[1:] / alphas_cumprod[:-1])
return torch.clip(betas, beta_start, beta_end)
elif schedule_type == "quadratic":
# 二次调度:前期慢后期快
return beta_start + (beta_end - beta_start) * (torch.linspace(0, 1, T) ** 2)

5. U-Net 骨干网络#

5.1 为什么选择 U-Net?#

大多数扩散模型使用 U-Net 作为噪声预测网络,原因在于:

  1. 编码器-解码器结构:能捕捉多尺度特征
  2. 跳跃连接:保留低级细节信息,对重建图像至关重要
  3. 对称性:编码器和解码器镜像对称,简化设计

5.2 U-Net 在扩散模型中的改进#

class DiffusionUNet(nn.Module):
def __init__(self, in_channels=3, out_channels=3, base_channels=128):
super().__init__()
# 编码器(下采样)
self.enc1 = ResidualBlock(in_channels, base_channels)
self.enc2 = ResidualBlock(base_channels, base_channels * 2)
self.enc3 = ResidualBlock(base_channels * 2, base_channels * 4)
# 瓶颈
self.bottleneck = ResidualBlock(base_channels * 4, base_channels * 4)
# 解码器(上采样)
self.dec1 = ResidualBlock(base_channels * 8, base_channels * 2) # 拼接跳跃连接
self.dec2 = ResidualBlock(base_channels * 4, base_channels)
self.dec3 = ResidualBlock(base_channels * 2, out_channels)
# 时间步嵌入
self.time_mlp = nn.Sequential(
SinusoidalPosEmb(base_channels),
nn.Linear(base_channels, base_channels * 4),
nn.SiLU(),
nn.Linear(base_channels * 4, base_channels)
)
def forward(self, x, t):
# 编码
e1 = self.enc1(x)
e2 = self.enc2(F.max_pool2d(e1, 2))
e3 = self.enc3(F.max_pool2d(e2, 2))
# 瓶颈 + 时间嵌入
b = self.bottleneck(e3)
t_emb = self.time_mlp(t)
# 解码(带跳跃连接)
d1 = self.dec1(torch.cat([F.interpolate(b, e3.shape[2:], mode='nearest'), e3], dim=1))
d2 = self.dec2(torch.cat([F.interpolate(d1, e2.shape[2:], mode='nearest'), e2], dim=1))
d3 = self.dec3(torch.cat([F.interpolate(d2, e1.shape[2:], mode='nearest'), e1], dim=1))
return d3

5.3 关键组件#

  1. 残差块 (Residual Block):包含 Group Normalization 和 SiLU 激活
  2. 时间步嵌入 (Time Embedding):使用正弦位置编码让网络感知当前时间步
  3. 注意力机制:在高级特征上加入自注意力,增强全局建模能力

6. 条件扩散 (Conditional Diffusion)#

6.1 分类器引导 (Classifier Guidance)#

为了让扩散模型根据条件生成(如文本描述),早期方法使用分类器引导:

ϵ^=ϵθ(xt,t)+sxlogpϕ(yxt)\hat{\epsilon} = \epsilon_\theta(x_t, t) + s \cdot \nabla_x \log p_\phi(y|x_t)

其中 ss 是引导强度,xlogpϕ(yxt)\nabla_x \log p_\phi(y|x_t) 是分类器梯度。

6.2 无分类器引导 (Classifier-Free Guidance)#

无分类器引导是更优雅的方案,不需要额外的分类器:

ϵ^=ϵθ(xt,t,)+w(ϵθ(xt,t,c)ϵθ(xt,t,))\hat{\epsilon} = \epsilon_\theta(x_t, t, \emptyset) + w \cdot (\epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \emptyset))

其中:

  • cc 是条件(如文本嵌入)
  • \emptyset 是空条件(无条件)
  • ww 是引导强度(通常 5-15)
引导强度的经验值
  • w=1w = 1:无引导
  • w=35w = 3-5:轻度引导,保留多样性
  • w=710w = 7-10:中度引导,平衡质量与多样性
  • w=1215w = 12-15:强度引导,高质量但多样性降低

6.3 交叉注意力机制#

在 Stable Diffusion 等模型中,文本条件通过交叉注意力机制注入:

文本嵌入 → Cross-Attention → U-Net 特征

这允许模型在生成过程中”关注”文本的不同部分。

7. 扩散模型 vs GAN#

特性扩散模型GAN
训练稳定性稳定,使用简单的 MSE 损失不稳定,需要精心平衡对抗训练
生成多样性中等,容易发生模式坍缩
推理速度慢(需要多步迭代)快(单步生成)
损失函数简单的重构/MSE 损失对抗损失
理论基础渐近理论博弈论
超参数敏感性中等
推理加速

虽然扩散模型推理慢,但有多种加速方法:

  • DDIM:使用非马尔可夫噪声调度,减少步数到 20-50 步
  • LCM (Latent Consistency Models):直接在潜在空间生成,4-8 步即可
  • SDXL-Turbo:单步或极少步生成

8. 现代扩散模型应用#

8.1 图像生成#

模型特点开源
Stable DiffusionLatent Diffusion,高效
DALL-E 3GPT-4V 驱动,高保真
Imagen超分辨率级联,文字渲染强
Midjourney艺术风格优化
SDXL1024px 大图支持

8.2 视频生成#

  • Sora:OpenAI 的视频生成模型,基于扩散变换器
  • Stable Video Diffusion:Stability AI 的开源视频扩散
  • Runway Gen-2/3:创意视频生成

8.3 3D 生成#

  • Point-E:OpenAI 的 3D 点云生成
  • DreamFusion:Google 的 3D 物体生成
  • Zero-1-to-3:从单图重建 3D

8.4 音频合成#

  • AudioLDM:基于扩散的音频生成
  • Riffusion:音乐生成
  • SPEAR-TTS:文本转语音

9. 核心公式总结#

  1. 前向过程(第 t 步)
xt=αˉtx0+1αˉtϵ,ϵN(0,I)x_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1 - \bar{\alpha}_t} \epsilon, \quad \epsilon \sim \mathcal{N}(0, I)
  1. 逆向过程均值
μθ(xt,t)=1αt(xtβt1αˉtϵθ(xt,t))\mu_\theta(x_t, t) = \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{\beta_t}{\sqrt{1 - \bar{\alpha}_t}} \epsilon_\theta(x_t, t) \right)
  1. 无分类器引导
ϵ^=(1+w)ϵθ(xt,tc)wϵθ(xt,t)\hat{\epsilon} = (1 + w) \cdot \epsilon_\theta(x_t, t | c) - w \cdot \epsilon_\theta(x_t, t | \emptyset)

10. 总结与展望#

扩散模型的核心创新在于:

  1. 渐进式生成:通过多步迭代逐步去除噪声,生成高质量样本
  2. 稳定训练:简单的 MSE 损失替代对抗训练
  3. 条件生成:通过引导机制实现灵活的条件控制
  4. 潜在空间:Latent Diffusion 大幅提升效率

当前挑战

  • 推理速度仍有提升空间
  • 长视频生成的一致性问题
  • 3D 内容生成的质量和效率

未来方向

  • 端到端的单步或少步模型
  • 扩散模型与语言模型的深度融合
  • 多模态统一生成框架

参考资料#

  1. Ho, J., et al. (2020). “Denoising Diffusion Probabilistic Models.” NeurIPS.
  2. Rombach, R., et al. (2022). “High-Resolution Image Synthesis with Latent Diffusion Models.” CVPR.
  3. Ho, J., et al. (2022). “Cascaded Diffusion Models for High Fidelity Image Generation.” JMLR.
  4. Ho, J., & Salimans, T. (2022). “Classifier-Free Diffusion Guidance.” NeurIPS Workshop.
  5. Peebles, W., & Xie, Y. (2023). “Scalable Diffusion Models with Transformers.” ICCV.

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

深入理解扩散模型 (Diffusion Model):从原理到实践
https://aiattnstudio.link/posts/diffusion-model-principles/
作者
Federico
发布于
2026-07-14
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author

Federico

AI Research Lab

Hello, I'm Federico.

关于实验室 / About
公告

欢迎来到Federico的个人博客

分类
标签
站点统计
57文章
7分类
404标签