外观
2.4 生成模型:自回归与扩散
生成模型(Generative Models)试图用一个可学习分布逼近数据分布,并据此计算似然、补全缺失信息或生成新样本。真实数据分布通常未知,因此模型学到的是受数据、参数化方式与训练目标共同限制的近似。

图 2.4-1:DDPM 的 CelebA-HQ 与 CIFAR-10 无条件样本展示逐步去噪模型最终能够生成的高维图像分布。 出处:Jonathan Ho; Ajay Jain; Pieter Abbeel,Denoising Diffusion Probabilistic Models(2020),Figure 1。
在深度学习发展的历程中,生成模型经历了多次演进。生成对抗网络(GAN)[Goodfellow et al., 2014] 用生成器与判别器之间的博弈来学习数据分布;变分自编码器(VAE)[Kingma & Welling, 2013] 则给出了基于潜变量与变分推断的概率框架。近年来,**自回归模型(Autoregressive Models)与扩散模型(Diffusion Models)**成为两条重要路线。GPT 展示了大规模自回归预训练在自然语言处理中的潜力 [Radford et al., 2018],DDPM 则展示了扩散模型在图像生成上的高质量结果 [Ho et al., 2020]。
本节从概率链式法则推导自回归建模,再从高斯加噪过程推导扩散模型。重点是看清两条路线分别如何定义训练目标,以及它们在生成阶段为什么会产生不同的串行开销。
2.4.1 自回归模型
自回归模型的核心思想源于概率的链式法则。香农在信息论奠基论文中用有限阶马尔可夫过程构造了文本近似 [Shannon, 1948],这可以看作统计语言模型的重要早期思想。进入深度学习时代后,Bengio 等人提出神经概率语言模型 [Bengio et al., 2003],Transformer 又提供了更适合并行训练的序列架构 [Vaswani et al., 2017]。
图 2.4-2:PixelRNN 的因果掩码图明确标出生成当前像素时只能依赖左侧和上方已经生成的像素。 出处:Aaron van den Oord et al.,Pixel Recurrent Neural Networks(2016),Figure 2。
联合概率的分解
在高中数学中,我们学习过条件概率的定义。对于任意两个事件
现在,假设我们观察到的数据是一个序列,例如一段文本、一段语音或一串时间序列数据。我们将序列中的每一个元素视为一个随机变量,记作
利用概率的链式法则,我们可以将上述二维的条件概率推广到
将其写为连乘的形式:
其中
模型的参数化
链式法则本身精确成立,但随着时间步
假设我们使用一个具有参数
在工程实现上,我们通常采用固定长度的窗口(即马尔可夫假设)来截断历史信息,或者使用循环神经网络(RNN)将其压缩为隐状态,亦或是使用 Transformer 的因果注意力机制(Causal Attention)直接对历史序列进行并行化建模。为了使得推导过程更具象,我们将从一个最基础的一维时间序列预测任务入手。

图 2.4-3:WaveNet 的因果卷积堆栈把每个音频采样点限制为只读取过去,从网络结构上实现自回归顺序。 出处:Aäron van den Oord et al.,WaveNet: A Generative Model for Raw Audio(2016),Figure 2。
自回归模型的实现代码实践
为了验证理论,我们将构建一个最简单的自回归模型来预测连续的时间序列(我们选用带有随机噪声的正弦波)。模型仅利用过去固定长度
先生成一段含少量噪声的正弦波作为训练样本。
python
import torch
from torch import nn
from torch.utils import data
import matplotlib.pyplot as plt
# 生成总共1000个数据点
T = 1000
time = torch.arange(1, T + 1, dtype=torch.float32)
# 正弦波加上均值为0,标准差为0.2的高斯噪声
x = torch.sin(0.01 * time) + torch.normal(0, 0.2, (T,))为了将其转化为自回归预测问题,我们需要将一维的序列切分为特征-标签对。我们设定时间窗口大小
接着把原始序列重组为特征矩阵和标签向量。
python
tau = 4
features = torch.zeros((T - tau, tau))
for i in range(tau):
features[:, i] = x[i: T - tau + i]
labels = x[tau:].reshape((-1, 1))
batch_size = 16
dataset = data.TensorDataset(features, labels)
data_iter = data.DataLoader(dataset, batch_size, shuffle=True)这里用一个小型多层感知机(MLP)估计条件均值。因为任务是连续值回归,我们采用均方误差(MSE);若进一步假设观测噪声为固定方差的高斯分布,最小化 MSE 等价于最大化相应条件对数似然。
下面定义 MLP 与训练循环。
python
# 定义一个包含两个隐藏层的简单MLP
def get_net():
net = nn.Sequential(nn.Linear(tau, 10), nn.ReLU(),
nn.Linear(10, 10), nn.ReLU(),
nn.Linear(10, 1))
# 初始化权重
for m in net.modules():
if isinstance(m, nn.Linear):
nn.init.xavier_uniform_(m.weight)
return net
loss = nn.MSELoss()
net = get_net()
optimizer = torch.optim.Adam(net.parameters(), lr=0.01)
# 训练模型
epochs = 5
for epoch in range(epochs):
for X, y in data_iter:
optimizer.zero_grad()
l = loss(net(X), y)
l.backward()
optimizer.step()
print(f'epoch {epoch + 1}, loss: {l.item():f}')这个例子体现了自回归模型的核心逻辑:把序列任务拆成逐步条件预测。训练时可以并行计算多个已知目标位置,但生成时后一步依赖前一步的新输出,因此通常需要串行执行。
2.4.2 扩散模型
不同于自回归模型沿序列逐项生成数据,**扩散模型(Diffusion Models)**学习逐步逆转加噪过程。Sohl-Dickstein 等人从非平衡热力学得到启发,提出了相应的生成建模方法 [Sohl-Dickstein et al., 2015];Ho 等人的 DDPM 随后用简化的噪声预测目标取得了高质量图像生成结果 [Ho et al., 2020]。
要理解扩散模型,我们需要暂时放下对数据结构的特定假设(如序列长度),并将目光聚焦于数据在状态空间中的演化。
可以把前向过程理解为不断向清晰图像加入少量高斯噪声,使其逐步接近标准高斯分布。生成模型学习的不是字面意义上的逆物理过程,而是一个参数化的反向转移分布:从噪声样本出发,逐步得到更符合数据分布的样本。
前向过程:数学视角的加噪
我们将数据本身(例如一张清晰的图片)定义为随机变量
从高中统计学可知,一维正态分布的概率密度函数由均值和方差完全决定。在多维空间中,我们使用协方差矩阵。前向过程的单步转移概率定义为:
这里,
我们来仔细拆解该公式中的物理量含义。为什么均值要乘以一个衰减因子
若前一时刻近似具有零均值和单位方差,这一步会保持该方差。选择合适的噪声调度并取足够大的
前向高斯过程还有一个实用的代数性质:利用正态分布的闭包与重参数化,可以直接写出从
将
利用独立正态变量之和仍服从正态分布的性质,其新方差为

图 2.4-4:累积系数同时决定保留多少原始信号、注入多少标准高斯噪声,因此训练时可跳过中间链直接得到 x_t。
其中总噪声
训练时不必逐步模拟前向马尔可夫链;给定随机时间步
逆向过程:学习去噪分布
现在我们来看逆向过程。如果前向过程是向图像中加注不可逆的无序性,那么逆向过程的任务就是从纯高斯噪声
数学上,真实反向转移概率由贝叶斯公式给出:
这就轮到深度学习登场了。我们构建一个由参数
原始 DDPM 的常见设定是固定或预先指定反向方差,使网络主要学习均值相关参数;后续扩散模型也有学习方差的变体,因此这不是扩散模型的必要条件。
从证据下界 (ELBO) 到简化的损失函数
训练逆向网络时,可以从对数似然
其中,前向后验
DDPM 将反向均值重新参数化为噪声预测器
该公式深刻地揭示了扩散模型训练的本质:给定任意时间步
扩散模型前向过程的代码实践
逆向网络通常采用 U-Net 等结构,而前向加噪只需要几项张量运算。下面实现这一过程。
先定义总时间步
python
# 扩散步数
num_timesteps = 1000
# 线性方差调度策略(Variance Schedule)
# beta_t 从 1e-4 线性增加到 0.02
betas = torch.linspace(1e-4, 0.02, num_timesteps)
# 计算 alpha 和 alpha_bar
alphas = 1.0 - betas
alphas_bar = torch.cumprod(alphas, dim=0)
# 为了后续根据时间步 t 索引系数时保持张量维度正确
# 这里计算 sqrt(alpha_bar) 和 sqrt(1 - alpha_bar)
sqrt_alphas_bar = torch.sqrt(alphas_bar)
sqrt_one_minus_alphas_bar = torch.sqrt(1.0 - alphas_bar)有了这些预计算的系数,我们可以立刻实现该公式所描述的前向快速加噪。
函数 q_sample 可在一次计算中从
python
def q_sample(x_0, t, noise=None):
"""
实现了前向扩散过程 x_t = sqrt(alpha_bar_t) * x_0 + sqrt(1 - alpha_bar_t) * epsilon
"""
if noise is None:
noise = torch.randn_like(x_0)
# 提取当前批次中每一个样本对应的 sqrt_alphas_bar_t
sqrt_alphas_bar_t = sqrt_alphas_bar[t].view(-1, 1, 1, 1)
# 提取对应的 sqrt(1 - alphas_bar_t)
sqrt_one_minus_alphas_bar_t = sqrt_one_minus_alphas_bar[t].view(-1, 1, 1, 1)
# 根据重参数化公式叠加噪声
x_t = sqrt_alphas_bar_t * x_0 + sqrt_one_minus_alphas_bar_t * noise
return x_t由此可见,前向过程在代码层面只需几行张量运算即可实现,这种无需循环迭代的特性,使得扩散模型能够在 GPU 上以极高的批处理效率进行大规模并行训练。
2.4.3 比较与联系
自回归模型与扩散模型虽然采用了迥异的数学视角,但它们之间存在深刻的联系。 自回归模型用概率链式法则分解联合分布,适合具有明确顺序的离散或连续序列,但逐词元生成通常是串行的。扩散模型在每个去噪步内可以同时更新所有空间位置,却仍需多次调用网络。两者的速度和质量取决于具体参数化、采样器与数据类型,不能简单归结为“文本用自回归、图像用扩散”。
2.4.4 小结
- 自回归模型基于严格的概率链式法则进行联合分布建模,将高维生成任务转化为条件序列预测任务,在自然语言处理中占据核心地位。
- 扩散模型从非平衡热力学汲取灵感,其前向过程通过可控方差的马尔可夫链注入噪声破坏数据,逆向过程则由神经网络学习去除噪声以从混沌中恢复结构。
- 借助高斯分布的闭包性质,扩散前向过程可以写出闭式边缘分布,从而直接在任意时间步采样训练对。
- 两类模型都在逼近数据分布,但采用不同的分解方式,并把计算成本放在不同位置。
2.4.5 练习
- 在自回归模型中,如果我们不采用固定窗口,而是想捕捉无限长的历史依赖,我们应该采用什么样的神经网络架构?(提示:思考循环机制或是全局注意力机制。)
- 假设只有两个扩散步,
、 。计算 ,再求 中信号系数的平方与噪声系数的平方,验证两者之和为 1。 - 修改 2.4.1 节中的自回归代码,将其改写为一个具有单层 RNN(如
nn.RNN)的模型结构。观察其在正弦波预测任务上相比于简单的多层感知机是否有提升。 - 为什么我们在构建扩散模型的逆向网络时,通常选择预测噪声
而不是直接预测干净的图像 ?(提示:结合图像在高度加噪时 信息的保留量,思考哪一种预测目标对神经网络的梯度优化更为平滑和稳定。)

