导读
扩散模型作为近年来最热门的生成式 AI 技术之一,凭借其稳定的训练过程和高质量的生成效果,正在逐步取代传统的 GAN。本文将深入解析其前向扩散与反向扩散机制,并基于 PyTorch 从零搭建一个 DDPM 模型,完成手写数字图像的生成实战。

核心思想
为什么需要扩散模型
传统的生成对抗网络(GAN)常面临训练不稳定、模式崩溃等挑战。扩散模型则通过概率建模的方式,将复杂的生成问题拆解为多个简单的马尔可夫链步骤。它模仿非平衡热力学的过程,在图像、文本和语音合成等领域展现出了超越传统模型的表现。
基本框架
扩散模型包含两个核心过程:
- 前向扩散过程:从真实数据出发,逐步添加高斯噪声。经过 T 步后,数据会变成完全随机的噪声。
- 反向扩散过程:从随机噪声出发,训练神经网络逐步去除噪声。经过 T 步后,噪声还原为真实的数据分布。
整个过程遵循马尔可夫链假设,即每一步的状态只与前一步有关。
前向扩散过程详解
前向扩散是一个固定的、无需训练的过程。它的目标是通过逐步添加噪声,将真实图像 $x_0$ 转换为随机噪声 $x_T$。
数学原理
前向扩散过程的每一步,都会按照以下公式向图像中添加噪声:
$$ x_t = \sqrt{\alpha_t} x_{t-1} + \sqrt{1 - \alpha_t} \epsilon_t $$
其中:
- $x_t$ 表示第 t 步添加噪声后的图像
- $\alpha_t$ 是一个预先设定的噪声系数,满足 $0 < \alpha_t < 1$
- $\epsilon_t$ 是服从标准正态分布的高斯噪声
为了计算方便,通常会定义累计乘积系数:
$$ \bar{\alpha}t = \prod{i=1}^t \alpha_i $$
通过累计系数,可以直接从 $x_0$ 计算出任意步的 $x_t$:
$$ x_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1 - \bar{\alpha}_t} \epsilon $$
⚠️ 注意:前向扩散的步数 T 是一个超参数。T 越大,前向扩散越充分,反向扩散的效果越好,但训练和生成的时间也会越长。
代码实现
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)
():
eps = torch.randn_like(x0).to(device)
alpha_bar_t = alpha_bar[t].reshape(-, , , ).to(device)
xt = torch.sqrt(alpha_bar_t) * x0 + torch.sqrt( - alpha_bar_t) * eps
xt, eps
torchvision.datasets MNIST
torchvision.transforms ToTensor
dataset = MNIST(root=, train=, download=, transform=ToTensor())
x0, _ = dataset[]
x0 = x0.unsqueeze()
device = torch.device( torch.cuda.is_available() )
plt.figure(figsize=(, ))
i, t ([, , , , , ]):
xt, _ = forward_diffusion(x0, torch.tensor([t]), device)
xt = xt.squeeze().cpu().detach().numpy()
plt.subplot(, , i + )
plt.imshow(xt, cmap=)
plt.title()
plt.axis()
plt.show()


