共计 2142 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍
扩散模型(Denoising Diffusion Probabilistic Models, DDPM)是一种基于马尔可夫链的生成模型,通过逐步添加和去除噪声来学习数据分布。相比 GAN,DDPM 训练更稳定,生成样本多样性更好,且理论保障更强。在 CIFAR-10 这类小尺寸图像生成任务上表现优异。

环境配置
- Python 3.8+
- PyTorch 1.12+
- torchvision
- matplotlib
- numpy
推荐使用 conda 创建虚拟环境:
conda create -n ddpm python=3.8
conda activate ddpm
pip install torch torchvision matplotlib numpy
数据预处理
CIFAR-10 包含 6 万张 32×32 彩色图像,分为 10 类。预处理关键步骤:
- 标准化:将像素值从 [0,255] 线性缩放至[-1,1]
- 数据增强:随机水平翻转(训练时)
- 分批加载:常用 batch_size=128
PyTorch 实现代码:
from torchvision import datasets, transforms
transform = transforms.Compose([transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
train_set = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=128, shuffle=True)
模型架构
DDPM 包含两个核心过程:
前向过程(加噪)
定义噪声调度表 β_t,逐步添加高斯噪声:
# 线性噪声调度
def linear_beta_schedule(timesteps):
beta_start = 0.0001
beta_end = 0.02
return torch.linspace(beta_start, beta_end, timesteps)
反向过程(去噪)
使用 U -Net 预测噪声:
import torch.nn as nn
class Block(nn.Module):
def __init__(self, in_ch, out_ch, time_emb_dim):
super().__init__()
self.time_mlp = nn.Linear(time_emb_dim, out_ch)
self.conv1 = nn.Conv2d(in_ch, out_ch, 3, padding=1)
self.conv2 = nn.Conv2d(out_ch, out_ch, 3, padding=1)
def forward(self, x, t):
h = self.conv1(x)
time_emb = self.time_mlp(t)[:, :, None, None]
return self.conv2(h + time_emb)
训练流程
关键超参数设置:
- 学习率:2e-4
- 迭代次数:1000
- 时间步:1000
- 优化器:Adam
完整训练代码框架:
model = UNet()
optimizer = torch.optim.Adam(model.parameters(), lr=2e-4)
for epoch in range(1000):
for batch in train_loader:
optimizer.zero_grad()
# 随机采样时间步
t = torch.randint(0, timesteps, (batch.shape[0],))
# 前向加噪
noise = torch.randn_like(batch)
noisy = q_sample(batch, t, noise)
# 预测噪声
pred_noise = model(noisy, t)
# 计算损失
loss = F.mse_loss(pred_noise, noise)
loss.backward()
optimizer.step()
推理实现
采样生成新图像:
def sample(model, image_size, batch_size=16):
# 初始随机噪声
img = torch.randn((batch_size, 3, image_size, image_size))
for t in reversed(range(timesteps)):
# 逐步去噪
img = p_sample(model, img, t)
return img
避坑指南
- 训练不稳定
- 检查噪声调度:β_t 不应增长过快
-
降低学习率尝试
-
生成图像模糊
- 增加模型容量
-
延长训练时间
-
显存不足
- 减小 batch_size
- 使用混合精度训练
性能优化
- 采样加速
- DDIM 采样方法
-
减少采样步数
-
质量提升
- 条件生成
- 更大模型架构
思考题
- 如何修改噪声调度策略来平衡生成速度与质量?
- 为什么 DDPM 在反向过程中需要预测噪声而非直接预测图像?
- 如何将 DDPM 扩展到更高分辨率的图像生成?
希望通过这篇实战指南,能帮助你顺利实现第一个扩散模型项目。在实际操作中遇到问题时,建议先简化实验设置(如减小图像尺寸或模型规模),待流程跑通后再逐步增加复杂度。
正文完
