人工智能:扩散模型(Diffusion Model)原理与图像生成实战

1.1 本章学习目标与重点
学习目标十分清晰:掌握扩散模型的核心运作机理,理解前向扩散与反向扩散的完整流程,并能独立完成基于扩散模型的图像生成实战。重点在于吃透噪声添加与去除的内在机制,学会用 PyTorch 搭建 DDPM 模型,最终实现手写数字图像的高质量生成。
1.2 扩散模型的核心思想
1.2.1 为什么需要扩散模型
传统生成模型如 GAN 虽然功能强大,但训练不稳定、模式崩溃等问题始终困扰着开发者。扩散模型则另辟蹊径——它不直接生成,而是把生成过程拆解成“逐步加噪”和“逐步去噪”两个方向明确的阶段。这种基于概率的建模方式,让训练过程变得稳定,生成的图像质量也更高。
扩散模型的灵感源自非平衡热力学,其核心是将复杂的生成问题分解为多个简单的马尔可夫链步骤。在图像生成、文本生成、语音合成等领域,扩散模型的表现已全面超越传统生成模型,成为当前最热门的生成范式之一。
1.2.2 扩散模型的基本框架
扩散模型包含两个核心过程:前向扩散过程和反向扩散过程。
- 前向扩散过程:从真实数据出发,逐步向数据中添加高斯噪声。经过 T 步后,数据会变成完全随机的噪声。
- 反向扩散过程:从随机噪声出发,训练一个神经网络逐步去除噪声。经过 T 步后,噪声还原为真实的数据分布。
整个过程遵循马尔可夫链的假设——每一步的状态只跟前一步有关,这大大简化了建模与计算。
1.3 前向扩散过程详解
前向扩散过程是一个固定的、非训练的过程。它的目标是通过逐步添加噪声,将真实图像 x₀ 转换为随机噪声 xₜ。
1.3.1 前向扩散的数学原理
前向扩散每一步都按以下公式向图像中添加噪声:
xₜ = √αₜ·xₜ₋₁ + √(1-αₜ)·εₜ
其中:
- xₜ 表示第 t 步添加噪声后的图像
- αₜ 是一个预先设定的噪声系数,满足 0 < αₜ < 1
- εₜ 是服从标准正态分布的高斯噪声
为了方便计算,通常会定义累计乘积系数:
αₜ = ∏ᵢ₌₁ᵗ αᵢ
通过这个累计系数,可以直接从 x₀ 计算出任意步的 xₜ:
xₜ = √αₜ·x₀ + √(1-αₜ)·ε
⚠️ 注意:前向扩散的步数 T 是一个超参数。T 越大,前向扩散越充分,反向扩散的效果越好,但训练和生成的时间也会相应增长。
1.3.2 前向扩散过程的代码实现
import torch
import numpy as np
import matplotlib.pyplot as plt
# 定义扩散过程的超参数
T = 1000 # 扩散步数
beta_start = 0.0001 # 初始噪声系数
beta_end = 0.02 # 最终噪声系数
# 生成线性变化的beta序列
beta = torch.linspace(beta_start, beta_end, T)
alpha = 1 - beta
alpha_bar = torch.cumprod(alpha, dim=0) # 累计乘积
# 前向扩散函数:从x0生成xt
def forward_diffusion(x0, t, device):
"""
x0: 原始图像 (batch_size, channels, height, width)
t: 扩散步数 (batch_size,)
"""
# 生成高斯噪声
eps = torch.randn_like(x0).to(device)
# 获取累计系数
alpha_bar_t = alpha_bar[t].reshape(-1, 1, 1, 1).to(device)
# 计算xt
xt = torch.sqrt(alpha_bar_t) * x0 + torch.sqrt(1 - alpha_bar_t) * eps
return xt, eps
# 测试前向扩散过程
# 加载MNIST数据集的一张图像作为示例
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
dataset = MNIST(root='./data', train=True, download=True, transform=ToTensor())
x0, _ = dataset[0]
x0 = x0.unsqueeze(0) # 增加batch维度 (1, 1, 28, 28)
device = torch.device('cuda' if torch.cuda.is_a vailable() else 'cpu')
# 可视化不同步数的扩散效果
plt.figure(figsize=(15, 3))
for i, t in enumerate([0, 100, 200, 500, 800, 999]):
xt, _ = forward_diffusion(x0, torch.tensor([t]), device)
xt = xt.squeeze().cpu().detach().numpy()
plt.subplot(1, 6, i+1)
plt.imshow(xt, cmap='gray')
plt.title(f't={t}')
plt.axis('off')
plt.show()
1.4 反向扩散过程与模型训练
1.4.1 反向扩散的数学原理
反向扩散是前向扩散的逆过程。目标很直接——训练一个神经网络 εθ,从 xₜ 中预测出添加的噪声 ε,然后逐步消除它,还原出 x₀。
反向扩散的核心公式:
pθ(xₜ₋₁|xₜ) =
