1 生成模型的基本问题
Lecture 13 从监督学习和无监督学习的区别切入:监督学习的数据是 \((x, y)\),目标是学习从输入 \(x\) 到标签或输出 \(y\) 的映射,例如分类、检测、语义分割、图像字幕等;无监督学习只有数据 \(x\),目标是学习数据中的隐藏结构,例如聚类、降维和密度估计。
生成模型(Generative Model)属于无监督或条件生成学习的核心方向。它不是只回答“这个输入是什么类别”,而是试图学习数据本身的分布,或者学习在某个条件下数据会如何出现。
1.1 判别模型、生成模型与条件生成模型
| 模型类型 | 学习对象 | 典型用途 | 关键直觉 |
|---|---|---|---|
| 判别模型(Discriminative Model) | \(p(y \mid x)\) | 分类、检测、分割 | 给定输入后,在可能标签之间分配概率 |
| 无条件生成模型(Generative Model) | \(p(x)\) | 采样新数据、异常检测、无标签特征学习 | 所有可能数据样本竞争概率质量 |
| 条件生成模型(Conditional Generative Model) | \(p(x \mid y)\) | 文生图、图像到视频、按类别生成 | 给定条件 \(y\) 后,生成符合条件的数据 \(x\) |
判别模型必须对任何输入给出标签分布,即使输入是不合理的噪声图像,它也会在已有类别中分配概率。生成模型则可以给“不像真实数据”的输入很低的概率,因此它天然适合做异常检测、数据建模和采样。
条件生成模型在实践中最常见。比如语言模型根据上文生成下一个 token,文生图模型根据文本提示生成图像,视频生成模型根据文本或前几帧预测后续内容。它们都在建模 \(p(x \mid y)\),其中 \(y\) 是条件,\(x\) 是多种可能输出之一。



判别模型、无条件生成模型与条件生成模型
1.2 为什么需要生成模型
生成模型的核心价值是建模不确定性和多模态输出。很多任务不是“一题一个标准答案”:同一句文字可以对应很多合理图像,同一段视频开头可以有很多可能后续,同一个类别也可以有无限多种视觉表现。若只预测一个平均结果,模型会丢失真实世界的多样性。
例如文本提示“一个人在白板前讲生成模型”并不唯一:人物姿势、教室布局、白板内容、光照都可以不同。条件生成模型要学的不是某一张图,而是条件 \(y\) 下所有合理图像的分布 \(p(x \mid y)\)。
2 生成模型的分类谱系
3 自回归模型(Autoregressive Models)
3.1 引入
自回归模型的输入和输出是:
- 输入: 已经看到的前缀,也就是 \(x_1,\dots,x_{t-1}\)。
- 输出: 下一个元素 \(x_t\) 的概率分布,也就是 \(p(x_t\mid x_1,\dots,x_{t-1})\)。
例如有一句话:
1 | 我 喜欢 吃 苹果 |
训练语言模型时,这句话会被拆成一系列“根据前文预测下一个词”的任务:
| 输入给模型的内容 | 模型应该输出什么 |
|---|---|
我 |
下一个词是 喜欢
的概率要高 |
我 喜欢 |
下一个词是 吃 的概率要高 |
我 喜欢 吃 |
下一个词是 苹果
的概率要高 |
生成时也一样:模型先根据已有前缀输出下一个 token 的概率分布,从中选择或采样一个 token,把它接到序列后面,再继续预测下一个 token。这样一步一步生成完整句子。
计算机视觉里的例子是 PixelCNN / PixelRNN。它们把图像按某种顺序展开成序列,例如从左到右、从上到下扫描像素。模型看到前面已经扫描过的像素,输出下一个像素值的概率分布。若每个像素通道是 8-bit,则下一个子像素可以看成 \(0\) 到 \(255\) 的 256 类分类问题。更现代的图像生成系统常不直接预测原始像素,而是先把图像压缩成较短的 latent tokens,再自回归地预测下一个 latent token。
所以,自回归模型的目标是把复杂联合分布拆成一串条件分布。只要数据能被看作序列,就可以用概率链式法则:
\[ p(x) = p(x_1, x_2, \dots, x_T) = \prod_{t=1}^{T} p(x_t \mid x_1, \dots, x_{t-1}) \]
这个公式是自回归模型的核心。它把“直接学习整个高维分布”变成“每一步预测下一个元素”。
3.2 最大似然估计
上面的链式法则本身只是概率恒等式,它没有说明模型长什么样,也没有参数 \(W\)。它只告诉我们:如果 \(x\) 是一个序列,那么联合分布可以拆成一串条件分布:
\[ p(x)=\prod_{t=1}^{T}p(x_t\mid x_{<t}) \]
自回归模型进一步做一个建模假设:每个条件分布都由一个带参数的模型来估计。例如神经网络参数记为 \(W\),那么模型学习的是:
\[ p(x_t\mid x_{<t})\approx p_W(x_t\mid x_{<t}) \]
因此,模型自己定义出来的序列概率是:
\[ p_W(x)=\prod_{t=1}^{T}p_W(x_t\mid x_{<t}) \]
这时就可以把整个右边看成一个显式函数:
\[ f(x,W)=\prod_{t=1}^{T}p_W(x_t\mid x_{<t}) \]
生成模型若能写成这样的显式密度 \(p_W(x)=f(x,W)\),通常可以用最大似然估计(Maximum Likelihood Estimation, MLE)训练。给定训练集 \(\{x^{(i)}\}_{i=1}^{N}\),目标是最大化训练数据的概率:
\[ W^* = \arg\max_W \prod_i p(x^{(i)}) \]
实际优化时使用 log trick,把乘积变成求和:
\[ W^* = \arg\max_W \sum_i \log p(x^{(i)}) = \arg\max_W \sum_i \log f(x^{(i)}, W) \]
这样更稳定,也方便用梯度下降优化。
3.3 图像上的自回归模型
图像也可以被看成序列。例如按扫描线顺序,把图像拆成 8-bit 子像素值,每个子像素是 \(0\) 到 \(255\) 的分类问题。PixelRNN 和 PixelCNN 就属于这种思路。
问题是原始像素序列太长。\(1024 \times 1024\) RGB 图像有大约三百万个子像素,如果逐个预测,训练和采样都非常昂贵。因此后来的图像生成系统常把图像先压缩成 latent tile 或离散 token,再在这些更短的表示上做自回归建模。Lecture 14 末尾提到“Autoregressive Models Strike Back”,指的就是自回归模型在离散 latent 上重新变得实用。
4 变分自编码器(Variational Autoencoders, VAE)
4.1 AE:普通的自编码器

普通自编码器学习的是
\[ x \rightarrow z \rightarrow \hat{x} \]
即用 encoder 把输入压缩成特征 \(z\),再用 decoder 重建输入。如果把 AE 当成生成模型来用,需要先找一个 latent code \(z\),然后把 \(z\) 输入 decoder,最后得到生成样本 \(\hat{x}\)。但问题在于,latent 空间可能是断裂的、稀疏的、不规则的:
1 | 有效 z 区域 空洞 有效 z 区域 |
因此如果随便采样一个 \(z\),decoder 可能从没在训练中见过这个区域,就会输出不合理图像。
VAE 是对普通自编码器的概率化改造。它的想法是:假设数据由潜变量 \(z\) 生成,先从简单先验 \(p(z)\) 中采样,再通过 decoder 得到 \(x\)。常见先验是标准高斯:
\[ z \sim p(z)=\mathcal{N}(0,I), \quad x \sim p_\theta(x \mid z) \]
4.2 补充:多维高斯分布的基本知识
VAE 里反复出现 \(\mathcal{N}(\mu,\Sigma)\),它表示多维高斯分布(Multivariate Gaussian / Multivariate Normal)。一维高斯分布写作:
\[ x\sim \mathcal{N}(\mu,\sigma^2) \]
其中 \(\mu\) 是均值,决定分布中心;\(\sigma^2\) 是方差,决定分布有多分散。它的概率密度函数是:
\[ p(x)=\frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) \]
多维高斯处理的是向量。若 \(z\in\mathbb{R}^d\),则:
\[ z\sim \mathcal{N}(\mu,\Sigma) \]
其中 \(\mu\in\mathbb{R}^d\) 是均值向量,表示每个维度的中心位置;\(\Sigma\in\mathbb{R}^{d\times d}\) 是协方差矩阵(covariance matrix),描述每个维度的方差以及不同维度之间的相关性。
例如二维时:
\[ \Sigma= \begin{bmatrix} \sigma_1^2 & \mathrm{cov}(z_1,z_2)\\ \mathrm{cov}(z_2,z_1) & \sigma_2^2 \end{bmatrix} \]
对角线上的 \(\sigma_1^2,\sigma_2^2\) 是各维度自己的方差;非对角线上的协方差表示两个维度是否倾向于一起变大或一起变小。协方差为正,两个维度倾向于同向变化;协方差为负,两个维度倾向于反向变化;协方差接近 0,则二者相关性弱。
\(d\) 维高斯的概率密度函数是:
\[ p(z)= \frac{1}{(2\pi)^{d/2}|\Sigma|^{1/2}} \exp\left( -\frac{1}{2}(z-\mu)^T\Sigma^{-1}(z-\mu) \right) \]
这里 \(|\Sigma|\) 是协方差矩阵的行列式,\(\Sigma^{-1}\) 是协方差矩阵的逆。中间的二次型
\[ (z-\mu)^T\Sigma^{-1}(z-\mu) \]
可以理解为“考虑了方差和相关性之后,\(z\) 离均值 \(\mu\) 有多远”。它不是普通欧氏距离,而是 Mahalanobis distance 的平方形式。
VAE 中通常不用完整协方差矩阵,而是用对角高斯:
\[ \Sigma=\operatorname{diag}(\sigma_1^2,\sigma_2^2,\dots,\sigma_d^2) \]
这表示各 latent 维度之间近似独立。这样 encoder 只需要输出每个维度的均值和方差,而不用输出完整的 \(d\times d\) 协方差矩阵。若 latent 维度 \(d_z=128\),完整协方差每个样本需要 \(128\times128\) 个数,而对角协方差只需要 \(128\) 个方差参数。
VAE 的先验常设为标准高斯:
\[ p(z)=\mathcal{N}(0,I) \]
意思是均值向量为 0,协方差矩阵为单位矩阵 \(I\),即每个维度方差为 1,维度之间互不相关。直觉上,二维标准高斯是以原点为中心、各方向均匀扩散的圆形分布;若协方差不是单位矩阵,分布可能被拉伸成椭圆。
4.3 VAE 的两个网络
4.3.1 网络结构

| 网络 | 数学记号 | 输入 | 输出 | 作用 |
|---|---|---|---|---|
| Encoder / inference network | \(q_\phi(z \mid x)\) | 数据 \(x\) | latent 分布参数,如 \(\mu_{z\mid x}, \Sigma_{z\mid x}\);再从该分布 采样 得到 \(z\) | 近似真实后验 \(p_\theta(z \mid x)\) |
| Decoder / generative network | \(p_\theta(x \mid z)\) | latent code \(z\) | 数据分布参数,如 \(\mu_{x\mid z}\);再取均值或 采样 得到 \(\hat{x}\) | 从潜变量生成数据 |
VAE 输出的是分布参数,而不是 \(\hat{x}\) 本身。常见设定是: \[ q_\phi(z \mid x)=\mathcal{N}(\mu_{z\mid x}, \Sigma_{z\mid x}) \]
\[ p_\theta(x \mid z)=\mathcal{N}(\mu_{x\mid z}, \sigma^2 I) \]
若 decoder 的输出分布是高斯,最大化 \(\log p_\theta(x\mid z)\) 等价于最小化重建误差 \(\|x-\mu_{x\mid z}\|_2^2\)。这解释了为什么 VAE 训练目标里会出现 reconstruction loss。
4.3.2 参数形状
从张量形状看,假设输入图像 \(x\) 的形状是 \((B,C,H,W)\),其中 \(B\) 是 batch size,latent 维度是 \(d_z\)。最常见的 VAE 使用对角协方差: \[ q_\phi(z\mid x)=\mathcal{N}(\mu_\phi(x),\operatorname{diag}(\sigma_\phi^2(x))) \]
因此 encoder 通常输出两组形状相同的向量:
| 参数 | 常见张量形状 | 说明 |
|---|---|---|
| \(\mu_{z\mid x}\) | \((B,d_z)\) | 每个样本对应一个 latent 均值向量 |
| \(\log\sigma^2_{z\mid x}\) 或 \(\sigma^2_{z\mid x}\) | \((B,d_z)\) | 每个 latent 维度一个方差;实践中常输出 log-variance |
理论上完整协方差矩阵 \(\Sigma_{z\mid x}\) 的形状可以是 \((B,d_z,d_z)\),但这会带来较高计算成本,所以实践中通常只学习对角协方差,也就是每个 latent 维度一个独立方差。
decoder 的输出形状取决于对 \(p_\theta(x\mid z)\) 的假设。若使用高斯输出分布:
\[ p_\theta(x\mid z)=\mathcal{N}(\mu_\theta(z),\sigma^2I) \]
那么 decoder 通常输出:
| 参数 | 常见张量形状 | 说明 |
|---|---|---|
| \(\mu_{x\mid z}\) | \((B,C,H,W)\) | 重建图像或数据的均值,常被直接当作 \(\hat{x}\) |
| \(\sigma^2I\) | 固定标量,或可广播到 \((B,C,H,W)\) | 入门 VAE 中常固定不学;若学习方差,也可输出 \(\log\sigma^2_{x\mid z}\),形状为 \((B,C,H,W)\) |
4.4 VAE 损失函数推导
VAE 的训练目标是最大化数据的边缘似然(marginal likelihood)\(p_\theta(x)\),也就是希望模型给真实训练样本较高概率:
\[ p_\theta(x)=\int p_\theta(x,z)\,dz =\int p_\theta(x\mid z)p(z)\,dz \]
这里的 \(p_\theta(x)\) 不是 decoder 单独直接输出的量。decoder 给出的是条件分布 \(p_\theta(x\mid z)\),再结合先验 \(p(z)\),对所有可能的 latent code \(z\) 积分后,才得到边缘分布 \(p_\theta(x)\)。难点在于这个积分通常不可计算。
不过可以把 \(p_\theta(x)\) 写成:
\[ p_\theta(x)=\frac{p_\theta(x,z)}{p_\theta(z\mid x)} \]
对两边取对数:
\[ \log p_\theta(x) = \log p_\theta(x,z)-\log p_\theta(z\mid x) \]
这个式子仍然包含真实后验 \(p_\theta(z\mid x)\),它不可计算。于是引入可计算的近似后验 \(q_\phi(z\mid x)\),并在右边加减同一项 \(\log q_\phi(z\mid x)\):
\[ \log p_\theta(x) = \log p_\theta(x,z) -\log q_\phi(z\mid x) + \log q_\phi(z\mid x) -\log p_\theta(z\mid x) \]
因为左边 \(\log p_\theta(x)\) 与 \(z\) 无关,所以可以对 \(z\sim q_\phi(z\mid x)\) 取期望:
\[ \log p_\theta(x) = \mathbb{E}_{z\sim q_\phi(z\mid x)} \left[ \log p_\theta(x,z)-\log q_\phi(z\mid x) \right] + \mathbb{E}_{z\sim q_\phi(z\mid x)} \left[ \log q_\phi(z\mid x)-\log p_\theta(z\mid x) \right] \]
第二项正是 KL 散度:
\[ \mathbb{E}_{z\sim q_\phi(z\mid x)} \left[ \log q_\phi(z\mid x)-\log p_\theta(z\mid x) \right] = D_{\mathrm{KL}}(q_\phi(z\mid x)\,\|\,p_\theta(z\mid x)) \]
因此有:
\[ \log p_\theta(x) = \underbrace{ \mathbb{E}_{z\sim q_\phi(z\mid x)} \left[ \log p_\theta(x,z)-\log q_\phi(z\mid x) \right] }_{\mathrm{ELBO}} + D_{\mathrm{KL}}(q_\phi(z\mid x)\,\|\,p_\theta(z\mid x)) \]
KL 散度永远非负,所以:
\[ \log p_\theta(x)\ge \mathrm{ELBO} \]
这就是“证据下界”(Evidence Lower Bound, ELBO)这个名字的来源:它是 log-likelihood \(\log p_\theta(x)\) 的一个下界。由于真实后验 \(p_\theta(z\mid x)\) 不可计算,不能直接最大化 \(\log p_\theta(x)\);但 ELBO 可计算,所以 VAE 转而最大化 ELBO。
接下来把联合概率拆开:
\[ p_\theta(x,z)=p_\theta(x\mid z)p(z) \]
代入 ELBO:
\[ \mathrm{ELBO} = \mathbb{E}_{z\sim q_\phi(z\mid x)} \left[ \log p_\theta(x\mid z)+\log p(z)-\log q_\phi(z\mid x) \right] \]
整理后得到最常见的形式:
\[ \mathrm{ELBO} = \mathbb{E}_{z\sim q_\phi(z\mid x)}[\log p_\theta(x\mid z)] - D_{\mathrm{KL}}(q_\phi(z\mid x)\,\|\,p(z)) \]
- 第一项是 重建项:要求 decoder 能从 \(z\) 还原 \(x\)。
- 第二项是 KL 正则项:要求 encoder 输出的 latent 分布不要偏离先验 \(p(z)\) 太远。
- 两者的张力很重要:重建项追求保留信息,KL 项追求 latent 空间规整、可采样。
实际训练通常写成最小化 loss,也就是最大化 ELBO 的相反数:
\[ \mathcal{L}_{\mathrm{VAE}}(x) = - \mathbb{E}_{z\sim q_\phi(z\mid x)}[\log p_\theta(x\mid z)] + D_{\mathrm{KL}}(q_\phi(z\mid x)\,\|\,p(z)) \]
这就是常说的 VAE loss = reconstruction loss + KL loss。如果 \(p_\theta(x\mid z)\) 设为高斯分布,那么负的重建 log-likelihood 常对应 L2 重建误差;如果 \(x\) 是二值图像或归一化像素,也可能使用 Bernoulli likelihood,对应交叉熵形式的重建损失。
4.5 VAE 的训练过程
VAE 训练过程是,encoder 和 decoder 联合训练,目标是最大化 ELBO,或者等价地最小化 reconstruction loss + KL loss。对一个 mini-batch 的输入 \(x\),训练步骤如下。
Encoder 输入数据 \(x\),输出 latent 分布参数。
\[ q_\phi(z\mid x)=\mathcal{N}(\mu_{z\mid x}, \Sigma_{z\mid x}) \]
实践中常用对角高斯,所以 encoder 通常输出 \(\mu_{z\mid x}\) 和 \(\log\sigma^2_{z\mid x}\)。
从 encoder 给出的分布中得到 latent code \(z\)。
直接写是:
\[ z\sim q_\phi(z\mid x) \]
但普通采样操作不可直接反向传播,所以训练时使用 重参数化技巧(reparameterization trick):
\[ \epsilon\sim\mathcal{N}(0,I),\quad z=\mu_{z\mid x}+\sigma_{z\mid x}\odot \epsilon \]
这样随机性来自外部噪声 \(\epsilon\),而 \(z\) 仍然是 \(\mu_{z\mid x}\) 和 \(\sigma_{z\mid x}\) 的可微函数,梯度可以传回 encoder。
Decoder 输入 \(z\),输出数据分布参数。
\[ p_\theta(x\mid z)=\mathcal{N}(\mu_{x\mid z},\sigma^2I) \]
常见实现中 decoder 输出 \(\mu_{x\mid z}\),也就是重建图像 \(\hat{x}\) 的均值。
计算重建项。
重建项来自:
\[ -\mathbb{E}_{z\sim q_\phi(z\mid x)}[\log p_\theta(x\mid z)] \]
如果 decoder 的输出分布设为高斯,这一项常对应 MSE;如果设为 Bernoulli,则常对应 binary cross-entropy。它要求 decoder 能从采样到的 \(z\) 还原原始输入 \(x\)。
计算 KL 正则项。
\[ D_{\mathrm{KL}}(q_\phi(z\mid x)\,\|\,p(z)) \]
其中 \(p(z)\) 通常是标准高斯 \(\mathcal{N}(0,I)\)。这一项要求 encoder 产生的 latent 分布不要离标准高斯太远,从而让训练后的 latent 空间可以被稳定采样。
反向传播并同时更新 encoder 和 decoder。
总损失为:
\[ \mathcal{L}_{\mathrm{VAE}} = \text{reconstruction loss} + \text{KL loss} \]
反向传播时,重建项主要推动 decoder 学会从 \(z\) 生成 \(x\),也推动 encoder 保留有用信息;KL 项推动 encoder 输出的分布靠近先验 \(p(z)\)。两者共同决定 latent 表示既要有信息,又要规整可采样。
这就是 VAE 和普通 AE 在训练上的关键区别:普通 AE 只训练 \(x\rightarrow z\rightarrow \hat{x}\) 的重建;VAE 训练的是两个概率分布 \(q_\phi(z\mid x)\) 和 \(p_\theta(x\mid z)\),并通过 KL 项把 latent 空间约束到一个可采样的先验附近。

4.6 VAE 的解耦表示
latent vector \(z=(z_1,z_2,\dots,z_d)\) 的不同维度可能会对应数据中不同的变化因素(factors of variation)。例如在人脸图像中,某些维度可能控制脸的朝向,某些维度可能控制表情、光照或发型。
观察这种性质的常见方法是:固定其他维度,只改变某一个 latent 维度,然后看 decoder 生成图像发生什么变化。例如固定 \(z_2\),只改变 \(z_1\):
\[ (z_1,z_2)=(-2,0),(-1,0),(0,0),(1,0),(2,0) \]
如果生成图像主要只在“朝向”上变化,就可以说 \(z_1\) 学到了某种较独立的变化因素。类似地,固定 \(z_1\) 只改变 \(z_2\),如果生成图像主要改变表情,就说明 \(z_2\) 可能对应表情因素。
VAE 常用标准高斯先验 \(p(z)=\mathcal{N}(0,I)\)。这个先验的协方差矩阵是单位矩阵,意味着不同 latent 维度在先验中相互独立。训练中的 KL 项会鼓励 \(q_\phi(z\mid x)\) 靠近这个独立的先验,因此 VAE 有倾向把不同变化因素分散到不同维度里。
不过要注意:普通 VAE 不保证 一定学到完美解耦表示。标准高斯先验和 KL 正则只是提供了这种倾向;如果想更强地解耦,后续方法如 \(\beta\)-VAE 会增大 KL 项权重,让 latent 表示更规整,但也可能牺牲重建质量。
4.7 VAE 的采样与局限
训练完成后,生成过程很简单:
- 从先验中采样 \(z\sim\mathcal{N}(0,I)\)。
- 输入 decoder,得到 \(p_\theta(x\mid z)\) 或其均值。
- 从输出分布采样或直接取均值作为生成结果。
VAE 的优点是有明确概率解释、训练相对稳定、latent 空间连续;缺点是生成图像常偏模糊。直观原因是高斯 likelihood 与重建损失鼓励输出“平均合理结果”,当真实图像有多种可能细节时,平均会变糊。
5 生成对抗网络(Generative Adversarial Networks, GAN)
GAN 由 Goodfellow 等人在 2014 年提出,目标是从真实数据分布 \(p_{\mathrm{data}}(x)\) 中采样,但不显式计算 \(p(x)\)。
GAN 引入简单 latent prior:
\[ z \sim p(z) \]
这里 \(p(z)\) 一般就是一个简单、容易采样的先验分布,通常采用多维标准高斯分布或均匀分布,高斯分布用得多一些。
然后用 生成器(Generator)把 \(z\) 映射为样本: \[ x_{\mathrm{fake}} = G(z) \]
同时训练 判别器(Discriminator)\(D(x)\),让它判断输入是真实样本还是生成样本。\(D(x)\) 的取值范围是 \([0,1]\),越接近 1 说明 \(x\) 越可能是正样本;越接近 \(0\) 说明 \(x\) 越可能是负样本。
5.1 GAN 的 minimax 目标
经典 GAN 目标是:
\[ \min_G \max_D \mathbb{E}_{x\sim p_{\mathrm{data}}}[\log D(x)] + \mathbb{E}_{z\sim p(z)}[\log(1-D(G(z)))] \]
判别器希望真实样本得分高、生成样本得分低;生成器希望骗过判别器,让 \(D(G(z))\) 尽可能高。这就是“对抗”的含义。
可以把训练理解成一个动态游戏:
- 固定 \(G\) 训练 \(D\): 判别器学习区分真实和生成样本。
- 固定 \(D\) 训练 \(G\): 生成器学习产生更像真实数据的样本。
- 循环迭代: 如果训练理想,生成分布逐渐接近真实分布。
5.2 交替梯度更新:GAN 不是普通的单一 loss 最小化
5.2.1 更新梯度
GAN 的训练不是在最小化一个所有网络共享的普通 loss,而是在做一个 minimax game。令
\[ V(G,D)= \mathbb{E}_{x\sim p_{\mathrm{data}}}[\log D(x)] + \mathbb{E}_{z\sim p(z)}[\log(1-D(G(z)))] \]
则训练目标可以写作:
\[ \min_G\max_D V(G,D) \]
因此两个网络的更新方向相反:
\[ D \leftarrow D+\alpha_D\frac{\partial V}{\partial D} \]
\[ G \leftarrow G-\alpha_G\frac{\partial V}{\partial G} \]
判别器 \(D\) 要增大目标函数,因为它在 \(\max_D\);生成器 \(G\) 要减小目标函数,因为它在 \(\min_G\)。这和普通监督学习里“所有参数一起最小化一个训练损失”不同。
这个差异带来一个实践后果:GAN 没有一个简单可靠的总 loss 曲线可以直接看训练是否变好。 判别器 loss 下降不一定代表生成器变好;生成器 loss 变化也会受到判别器强弱影响。GAN 训练更像两个玩家不断追逐对方的策略,而不是一个模型朝固定目标稳步下降。
5.2.2 如何交替
一次 GAN 训练并不是把真实图片和噪声一起送进一个普通网络,然后统一反向传播;它更像是在同一个 mini-batch 级别上轮流训练两个玩家。设真实图片 batch size 为 \(m\),一次常见训练 step 可以写成:
第一步:训练判别器 \(D\),暂时固定生成器 \(G\)。
从真实数据集中采样一批图片:
\[ x_1,\dots,x_m\sim p_{\mathrm{data}}(x) \]
再从 latent prior 中采样一批噪声:
\[ z_1,\dots,z_m\sim p(z) \]
通过生成器得到一批假图片:
\[ \hat{x}_i=G(z_i) \]
然后把真实图片和假图片都送入判别器:
\[ D(x_i),\qquad D(G(z_i)) \]
判别器的目标是让真实图片输出接近 \(1\),让假图片输出接近 \(0\)。如果把最大化目标改写成常见的最小化 loss,可以写成:
\[ \mathcal{L}_D = -\frac{1}{m}\sum_{i=1}^m \log D(x_i) -\frac{1}{m}\sum_{i=1}^m \log(1-D(G(z_i))) \]
这一步反向传播时,只更新判别器 \(D\) 的参数。虽然假图片来自 \(G(z)\),但在训练 \(D\) 时通常把 \(G(z)\) 当成已经生成好的样本,不让梯度更新到 \(G\)。
第二步:训练生成器 \(G\),暂时固定判别器 \(D\)。
再采样一批噪声:
\[ z_1,\dots,z_m\sim p(z) \]
生成假图片并送入判别器:
\[ D(G(z_i)) \]
此时判别器只负责给出训练信号,不更新 \(D\) 的参数。生成器希望自己的假图片被判别器认为是真的,所以希望 \(D(G(z_i))\) 越接近 \(1\) 越好。实践中常用非饱和生成器损失:
\[ \mathcal{L}_G = -\frac{1}{m}\sum_{i=1}^m \log D(G(z_i)) \]
这一步反向传播时,梯度会穿过判别器的计算图传回生成器,但优化器只更新 \(G\) 的参数。也就是说,\(D\) 在这里像一个“可微的评分器”:它告诉 \(G\) 当前假图片哪里不够像真图,但自己暂时不学习。
把整个过程写成伪代码就是:
1 | for each epoch: |
这里的 \(m\) 通常就是 mini-batch size。理论上,真实样本数 \(N_x\) 和噪声样本数 \(N_z\) 不一定必须相等,因为两个期望可以分别用不同数量的 Monte Carlo samples 估计:
\[ \frac{1}{N_x}\sum_{i=1}^{N_x}\log D(x_i) + \frac{1}{N_z}\sum_{j=1}^{N_z}\log(1-D(G(z_j))) \]
但实践中通常直接取:
\[ N_x=N_z=m \]
这样实现最简单,也让判别器在一个 step 中看到的 real/fake 数量比较平衡。
还有一些实现会每更新一次 \(G\),先更新 \(D\) 多次,比如 \(k\) 次 \(D\) step 对应 \(1\) 次 \(G\) step。这可以控制两个玩家的相对强弱:如果 \(D\) 太弱,给不出有用信号;如果 \(D\) 太强,\(G\) 可能很难得到有效梯度。所以 GAN 的交替训练本质上是在维护一个动态平衡。
5.3 原始 generator loss 的梯度饱和问题
GAN 的原始 minimax 形式中,生成器通过最小化
\[ \mathbb{E}_{z\sim p(z)}[\log(1-D(G(z)))] \]
来训练。但在训练早期会出现问题。刚初始化时,\(G\) 和 \(D\) 都是随机的。\(G(z)\) 生成出来的东西通常离真实图像分布很远,比如噪声块、奇怪纹理、没有结构的图像。对 \(D\) 来说,区分“真实训练图像”和“随机生成图像”是一个相对简单的二分类任务,所以经过少量更新后,\(D(G(z))\) 很容易接近 \(0\)。
\[ D(G(z))\approx 0 \]
在这种情况下,\(\log(1-D(G(z)))\) 对生成器参数的有效梯度可能非常小,导致生成器学得很慢。
常用解决方法是改用非饱和生成器损失(non-saturating generator loss): \[ \mathcal{L}_G=-\mathbb{E}_{z\sim p(z)}[\log D(G(z))] \]
直觉上,生成器的目标仍然是让判别器认为 fake 是 real,也就是让 \(D(G(z))\) 越接近 \(1\) 越好。但把目标写成最小化 \(-\log D(G(z))\) 后,当 \(D(G(z))\) 很小时,生成器能得到更强的梯度信号。
5.4 为什么 minimax 目标是合理的
给定一个固定的生成器 \(G\),它生成分布 \(p_G(x)\)。此时判别器要在真实样本和生成样本之间做最优二分类。数学上可以证明,对任意固定的 \(p_G\),最优判别器(即内层 max 的最优解)为:
\[ D_G^*(x)= \frac{p_{\mathrm{data}}(x)} {p_{\mathrm{data}}(x)+p_G(x)} \]
这个式子很有直觉:
- 如果某个 \(x\) 只出现在真实数据中,\(p_{\mathrm{data}}(x)\) 大而 \(p_G(x)\) 小,则 \(D_G^*(x)\) 接近 \(1\)。
- 如果某个 \(x\) 主要由生成器产生,\(p_G(x)\) 大而 \(p_{\mathrm{data}}(x)\) 小,则 \(D_G^*(x)\) 接近 \(0\)。
- 如果生成分布已经等于真实分布,即 \(p_G(x)=p_{\mathrm{data}}(x)\),则
\[ D_G^*(x)=\frac{1}{2} \]
这意味着判别器无法判断输入是真实还是生成,只能像随机猜测一样输出 \(0.5\)。因此,外层对 \(G\) 的优化最终希望达到:
\[ p_G(x)=p_{\mathrm{data}}(x) \]
这说明 GAN 的目标在理想条件下是合理的:如果判别器和生成器都有足够能力、优化能成功收敛,那么生成器分布会匹配真实数据分布,判别器已经无法区分真实数据和生成数据,只能给出 \(\frac{1}{2}\) 的概率。
但课件也给出了两个警告:
- 有限容量问题: 实际神经网络不一定能表示理论上的最优 \(D\) 和最优 \(G\)。
- 有限数据与优化问题: 理论最优不保证用有限数据、有限 batch、梯度下降交替更新时一定收敛。
所以 GAN 的理论目标很漂亮,但训练过程并不自动稳定。这也是后面许多 GAN 变体改进 loss、正则化、归一化和网络结构的原因。
5.5 GAN 架构:DCGAN
GAN 中生成器 \(G\) 和判别器 \(D\) 都是神经网络。在图像生成任务里,早期常用卷积神经网络(CNN)来构造二者。课件指出,GAN 在 ViT 大规模流行之前已经逐渐退潮,所以经典 GAN 架构主要还是 CNN 风格。
DCGAN(Deep Convolutional GAN)是第一个能在真实的、复杂的数据集上比较稳定工作的 GAN 架构之一。它的基本思想是:
- 生成器从 latent vector \(z\) 出发,经过一系列上采样或转置卷积,逐步生成图像。
- 判别器接收真实图像或生成图像,经过卷积下采样,输出 real/fake 概率。
- 卷积结构利用图像的局部空间相关性,比纯 MLP 更适合生成自然图像。
从生成模型发展史看,DCGAN 的意义不只是“用了卷积”,而是证明了 GAN 可以从简单数据集走向更真实的图像生成任务。它为后续更强的图像 GAN 架构奠定了基础。
5.6 GAN 架构:StyleGAN 与 AdaIN
StyleGAN 使用更复杂的生成器设计,是高质量人脸生成中非常有代表性的 GAN 架构。StyleGAN 通过自适应归一化(Adaptive Instance Normalization, AdaIN)在每一层注入风格信息和噪声。
AdaIN 的形式为:
\[ \operatorname{AdaIN}(x,w,b)_i = w_i\frac{x_i-\mu_i(x)}{\sigma_i(x)}+b_i \]
其中:
| 符号 | 含义 | PyTorch 风格形状 |
|---|---|---|
| \(x\) | 当前层的 feature map | [N, C, H, W] |
| \(x_i\) | 第 \(i\) 个通道的 feature map | [N, H, W] |
| \(\mu_i(x)\) | 对每个样本、每个通道,在空间维度 \(H,W\) 上计算的均值 | [N, C, 1, 1] |
| \(\sigma_i(x)\) | 对每个样本、每个通道,在空间维度 \(H,W\) 上计算的标准差 | [N, C, 1, 1] |
| \(w_i\) | 对每个样本、每个通道归一化后特征的缩放(scale),由 style code 生成 | [N, C, 1, 1] |
| \(b_i\) | 对每个样本、每个通道归一化后特征的平移(shift),由 style code 生成 | [N, C, 1, 1] |
style code 对应图中的 \(\mathbf{w} \in \mathcal{W}\)。 这个操作可以理解为:先把中间特征标准化,再用由 latent code(对应图中的 \(\mathbf{z} \in \mathcal{Z}\) 预测出的 scale 和 shift 重新调制特征。这样 latent 不只是作为网络最开始的输入,而是可以在生成器的多个层级控制图像属性。粗层可能影响姿态、脸型、整体布局;细层可能影响纹理、发丝、局部细节。

StyleGAN 的重要直觉是:好的生成器不只是把 \(z\) 一次性解码成图像,而是在多尺度特征生成过程中持续注入可控的风格信息。
5.7 Latent Space Interpolation:latent 空间插值
课件第 33-34 页展示了 GAN 的一个重要现象:训练好的 GAN 往往有较平滑的 latent space。给定两个 latent vectors \(z_0\) 和 \(z_1\),可以在二者之间做线性插值:
\[ z_t=t z_0+(1-t)z_1 \]
再输入生成器:
\[ x_t=G(z_t) \]
如果 latent 空间学得好,随着 \(t\) 连续变化,生成图像 \(x_t\) 也会在语义上平滑变化。例如一张人脸可能逐渐改变年龄、姿态、发型或表情,而不是突然跳到完全无关的图像。这里有一些demo。
这个现象说明生成器学到的不是简单记忆训练集图片,而是把连续 latent 空间映射到了数据流形(data manifold)附近。它也是 GAN 常被用于图像编辑、属性控制和语义方向探索的重要原因。
不过插值平滑并不等于模型完美。GAN 可能会发生模式崩塌(mode collapse)问题,即 latent 空间可能只覆盖真实分布的一小部分模式,此时插值看起来平滑,但多样性不足。例如单张人脸图很清晰、很真实,但采样 100 张以后发现它们都长得差不多。
5.8 GAN 的优缺点
| 方面 | 说明 |
|---|---|
| 优点 | 形式简单;采样快;生成结果可以很锐利;图像质量曾长期非常强;latent 空间通常有平滑插值性质 |
| 缺点 | 没有可靠的整体 loss
曲线;训练不稳定;可能模式崩塌(mode collapse); 不能直接计算样本 likelihood;评估困难;难以稳定扩展到特别大的模型和数据 |
GAN 大约在 2016 到 2021 年间是图像生成的主流方法之一。后来扩散模型逐渐成为高质量图像与视频生成的主流,但 GAN 的思想仍然重要:它展示了可以不显式建模 \(p(x)\),而通过判别器提供训练信号来学习从简单噪声分布到真实数据分布的直接采样映射。
6 扩散模型
扩散模型这个领域,术语和记号比较混乱,不同论文可能用 DDPM、score-based model、flow matching、rectified flow 等不同形式描述相关思想。课程用 Rectified Flow 给出一个较直观、现代的解释,再继续讲条件生成、Classifier-Free Guidance、noise schedule、Latent Diffusion、DiT、文生图/视频和蒸馏。
核心思路是:从真实数据 \(x\sim p_{\mathrm{data}}\) 出发,构造一个从数据到噪声的连续路径;然后训练神经网络学习如何沿反方向从噪声回到数据。扩散模型和 GAN 一样通常不能直接给出简单的 \(p(x)\) 公式,但它能通过一个迭代过程从简单噪声分布中采样出高质量数据。
6.1 扩散模型的基本直觉:从加噪到去噪
扩散模型的 第一步 是选择一个简单的噪声分布:
\[ z\sim p_{\mathrm{noise}} \]
实际中最常见的是单位高斯分布(unit Gaussian),也就是 \(z\sim p_{\text{noise}} =\mathcal{N}(0,I)\)。这类分布容易采样、形状规则,因此适合作为生成过程的起点。
第二步 是把真实数据 \(x\) 在不同噪声等级 \(t\) 下逐渐腐蚀,得到带噪样本 \(x_t\)。这里 \(t\) 可以理解为“噪声强度”或“时间步”:
- 当 \(t=0\) 时,几乎没有噪声,\(x_t\) 接近真实干净数据 \(x\)。
- 当 \(t=1\) 时,样本几乎完全变成噪声,\(x_t\) 接近从 \(p_{\mathrm{noise}}\) 采样得到的随机噪声。
- 当 \(0<t<1\) 时,\(x_t\) 是介于真实图像和纯噪声之间的中间状态。
这一步叫前向加噪过程(forward noising / diffusion process)。它不是模型要学习的部分,而是人为设计出来的训练数据构造方式。给定一张真实图像,我们可以按不同 \(t\) 生成许多不同噪声程度的版本。
第三步 是训练一个神经网络: \[ f_\theta(x_t,t) \]
它的输入是带噪样本 \(x_t\) 和当前噪声等级 \(t\),目标是 去掉一点噪声,也就是预测从当前状态往更干净状态移动的方向。对于每个中间步 \(x_t\),\(f_\theta\) 都是一样的,也就是它们共享同一个神经网络。注意这里的“去噪”不是传统图像处理里把一张噪声图恢复清晰,而是在学习数据分布的反向动力学:模型需要知道在当前噪声程度下,哪些结构更像真实图像,哪些成分更像随机噪声。
第四步 发生在推理或采样阶段。此时没有真实图像 \(x\),只有从噪声分布中采样的初始点: \[ x_1\sim p_{\mathrm{noise}} \]
然后反复应用 \(f_\theta\),让样本从高噪声状态一步步走向低噪声状态,最终生成近似无噪声的样本 \(x_0\)。因此扩散模型的生成过程可以概括为:
\[ x_1\rightarrow x_{t_k}\rightarrow \cdots \rightarrow x_{t_1}\rightarrow x_0 \]
其中 \(x_1\) 是纯噪声,\(x_0\) 是最终生成图像。训练时,模型学习如何从任意噪声等级的 \(x_t\) 往更干净的数据方向移动;采样时,模型把这个局部去噪能力重复很多次,组合成完整生成过程。

这个直觉也解释了扩散模型为什么通常采样较慢:一次网络前向传播只完成一小步去噪,高质量生成往往需要多步迭代。后面讲到的 Rectified Flow、Generalized Diffusion 和扩散蒸馏,本质上都在尝试用更好的路径、更好的预测目标或更少的步骤来实现从噪声到数据的生成。
6.2 Rectified Flow 的训练公式:data→noise
Rectified Flow 假设我们有一个简单噪声分布 \(p_{\mathrm{noise}}\),例如单位高斯分布,以及真实数据分布 \(p_{\mathrm{data}}\) 的训练样本。在每次训练迭代中,先采样真实数据、噪声和时间:
\[ x\sim p_{\mathrm{data}}, \quad z\sim p_{\mathrm{noise}}, \quad t\sim U(0,1) \]
这里 \(t\) 表示路径上的位置。课程先用均匀分布 \(U(0,1)\),后面再讨论为什么实践中常改成非均匀 noise schedule。
构造中间状态: \[ x_t=(1-t)x+tz \]
当 \(t=0\) 时,\(x_t=x\),是干净数据;当 \(t=1\) 时,\(x_t=z\),是纯噪声。
目标速度为: \[ v_{\mathrm{gt}}=z-x \]
在二维空间中可视化如下:

网络预测: \[ v_{\mathrm{pred}}=f_\theta(x_t,t) \]
损失函数:
\[ \mathcal{L}=\|v_{\mathrm{gt}}-v_{\mathrm{pred}}\|_2^2 \]
直觉上,模型看到一个带噪中间点 \(x_t\) 和时间 \(t\),要预测从真实数据点 \(x\) 指向噪声点 \(z\) 的速度 \(v=z-x\)。训练目标看起来非常简单,只要让网络预测这个向量即可。Rectified Flow 的核心训练循环只有几行代码,因此它是一个简单、可扩展的生成建模框架。
1 | for x in dataset: |
6.3 Rectified Flow 的采样过程:noise→data
训练时学的是数据到噪声的速度;采样时实际要反过来走,从噪声到数据。
训练好 \(f_\theta\) 后,采样时没有真实图像 \(x\),只有噪声。Rectified Flow 从噪声端开始,逐步沿着模型预测的反方向走回数据端。
设采样步数为 \(T\)。常见选择大约是 \(T=50\)。采样过程可以写成:
从噪声分布采样初始点:
\[ x_1\sim p_{\mathrm{noise}} \]
令时间从 \(1\) 逐步走到 \(0\),例如:
\[ t=1,1-\frac{1}{T},1-\frac{2}{T},\dots,0 \]
在每个时间步,用网络预测速度:
\[ v_t=f_\theta(x_t,t) \]
沿着去噪方向更新样本:
\[ x\leftarrow x-\frac{v_t}{T} \]
最后返回 \(x_0\) 作为生成样本。
第四步中,这里的负号很重要。训练时 \(v=z-x\) 是从数据指向噪声的方向;采样时我们从噪声出发,要往数据方向走,所以更新时要减去预测速度。可以把这个过程理解成用 Euler 方法求解一个从噪声分布流向数据分布的连续动力系统。
此外,\(v_t\) 除以的是 \(T\) 而不是什么别的数,是为了保持 scale 一致。如果不除以 \(T\),每一步都走一个完整的 \(v_t\),走 \(T\) 次会严重过冲( overshoot)。除以 \(T\) 后,\(T\) 步加起来才覆盖约 \(1\) 个单位的时间区间,从噪声端走到数据端。
在二维空间中可视化如下(\(T=3\)):



伪代码:
1 | sample = torch.randn(x_shape) |
6.4 Conditional Rectified Flow
无条件生成模型学习的是 \(p(x)\),而条件生成模型学习的是:
\[ p(x\mid y) \]
其中 \(y\) 可以是类别标签、文本提示词、图像条件、视频首帧等。Conditional Rectified Flow 的训练和无条件版本非常像,只是模型额外接收条件 \(y\):
\[ v_{\mathrm{pred}}=f_\theta(x_t,y,t) \]
目标仍然是预测真实速度:
\[ v_{\mathrm{gt}}=z-x \]
因此损失可以写成:
\[ \mathcal{L}=\|f_\theta(x_t,y,t)-v_{\mathrm{gt}}\|_2^2 \]
这样训练后,采样时给定条件 \(y\),模型就会把噪声推向符合该条件的数据区域。例如 \(y\) 是“猫”,采样路径会朝猫图像分布移动;\(y\) 是文本 prompt,采样路径会朝符合文本描述的图像或视频移动。

Conditional training 伪代码:
1 | for (x, y) in dataset: |
Conditional sampling 伪代码:
1 | y = user_input() # 这里增加了一个y |
6.5 Classifier-Free Guidance(CFG)
6.5.1 改进
条件生成里一个关键问题是:能不能控制模型“多强调条件 \(y\)”?如果条件强调得弱,生成结果可能多样但不够贴合提示;如果条件强调得强,结果更贴合提示,但可能牺牲多样性或产生伪影。
Classifier-Free Guidance(CFG)的训练技巧是:训练时随机丢弃条件 \(y\)。这样同一个模型既能做条件预测,也能做无条件预测:
\[ v_{\emptyset}=f_\theta(x_t,y_{\emptyset},t) \]
\[ v_y=f_\theta(x_t,y,t) \]
其中 \(y_{\emptyset}\) 表示空条件或被丢弃的条件。直观上:
- \(v_{\emptyset}\) 指向无条件数据分布 \(p(x)\),也就是“生成一个像真实数据的东西”。
- \(v_y\) 指向条件数据分布 \(p(x\mid y)\),也就是“生成一个符合条件 \(y\) 的东西”。
在数值上,\(y_\phi\) 是一个空条件的 embedding,它可以由上游的编码器得到。例如,如果条件 \(y\) 是文本 prompt,那么 \(y_\phi\) 就可以是空字符串的 embedding,即: \[ y_\phi = \text{text-encoder}(\text{''}) \]

采样时,CFG 把这两个方向线性组合: \[ v_{\mathrm{cfg}}=(1+w)v_y-wv_{\emptyset} \]
其中 \(w\) 是 guidance scale。这个公式也可以写成:
\[ v_{\mathrm{cfg}}=v_y+w(v_y-v_{\emptyset}) \]
所以 CFG 的直觉是:先走条件方向 \(v_y\),再额外沿着“条件方向和无条件方向的差”多推一把。这个差值可以理解为“条件 \(y\) 带来的额外约束”。\(w\) 越大,模型越强调条件。但是也不能太大,否则 \(v_{cfg}\) 的 scale 也会很大。
6.5.2 为啥就 classifier free 了
CFG 叫 classifier-free,重点在 free from classifier,也就是“不需要额外分类器”。早期的 classifier guidance 会额外训练一个判别/分类模型 \(p(y\mid x)\),让它判断图像 \(x\) 有多符合条件 \(y\)。采样时,再用这个分类器对图像的梯度来推生成过程:
\[ \nabla_x\log p(y\mid x) \]
这个梯度的意思是:“如果想让当前样本更像类别/条件 \(y\),应该往哪个方向改 \(x\)?”所以早期方法需要两个模型:一个扩散模型负责生成,一个分类器负责告诉它怎么更符合条件。
CFG 的做法是把这个额外分类器省掉。训练时随机把 \(y\) 替换成 \(y_{\emptyset}\),于是同一个扩散模型同时学会两种输出:有条件时的方向 \(v_y\),以及无条件时的方向 \(v_{\emptyset}\)。采样时用二者的差 \(v_y-v_{\emptyset}\) 近似“条件带来的额外推动”,因此不再需要单独的 \(p(y\mid x)\) 分类器。
CFG 在实践中非常重要,几乎是现代高质量条件扩散生成的标配。但它也有代价:每个采样步通常要分别计算 \(v_y\) 和 \(v_{\emptyset}\),因此采样成本大约翻倍。
CFG training 伪代码是:
1 | for (x, y) in dataset: |
6.6 中间噪声与 Noise Schedule
6.6.1 Optimal Prediction:为什么中间噪声最难
这里的“最难”,指的是模型最难从输入 \((x_t,t)\) 中预测出正确的去噪方向 \(v\)。在 \(t=0\) 附近,样本几乎是干净数据;在 \(t=1\) 附近,样本几乎是纯噪声。这两端相对容易,因为 \(x_t\) 的状态比较明确:
- 满噪声端 \(t=1\): 此时 \(x_t=z\)。给定纯噪声点,最优方向大致和真实数据分布的均值有关。
- 无噪声端 \(t=0\): 此时 \(x_t=x\)。给定真实数据点,最优方向大致和噪声分布的均值有关。
但中间噪声最困难,因为 \(x_t\) 同时混合了数据的结构和噪声,很多不同的 \((x,z)\) 组合可能产生相似甚至相同的 \(x_t\),网络面对的是高度模糊的反推问题。

更具体地说,训练目标是 MSE:
\[ \|f_\theta(x_t,t)-v\|_2^2 \]
对于同一个 \(x_t\),可能存在很多不同的真实数据 \(x\) 和噪声 \(z\) 能产生它,而这些不同组合对应的真实速度 \(v=z-x\) 并不相同。MSE 下的最优预测不是任选一个可能方向,而是对所有可能方向取平均。也就是说,中间噪声难在模型不能确定“这个带噪样本到底应该往哪个真实数据模式移动”。
6.6.2 Noise Schedule:如何采样时间 \(t\)
如果训练时简单使用
\[ t\sim U(0,1) \]
那么所有噪声等级获得相同训练权重。但之前说了,中间噪声更难、更重要。于是实践中常用非均匀 noise schedule,让训练更关注困难区域。
一种常见选择是 logit-normal sampling。它不是直接让 \(t\) 服从高斯,因为 \(t\) 必须在 \([0,1]\) 内;而是先采样一个实数 \(u\):
\[ u\sim\mathcal{N}(\mu,\sigma^2) \]
再通过 sigmoid 映射到 \((0,1)\):
\[ t=\operatorname{sigmoid}(u)=\frac{1}{1+e^{-u}} \]
等价地说:
\[ \operatorname{logit}(t)=\log\frac{t}{1-t} \]
服从高斯分布。通过调整 \(\mu,\sigma\),可以让 \(t\) 更多落在中间噪声区域。
一个 batch 中 \(t\) 的采样过程是,先从 \(u\sim\mathcal{N}(\mu,\sigma^2)\) 中采样 \(N\) 个 \(u\),然后根据 \(t=\operatorname{sigmoid}(u)\) 生成 \(N\) 个 \(T\)。至于 \(\mu\) 和 \(\sigma\) 怎么取,可以有以下几种情况:
| 参数 | 效果 |
|---|---|
| \(\mu=0,\sigma\) 较小 | 大量 \(t\) 在 \(0.5\) 附近,强烈关注中间噪声 |
| \(\mu=0,\sigma\) 较大 | \(t\) 覆盖更宽,既有中间也有两端 |
| \(\mu<0\) | \(u\) 偏负,所以 \(t\) 更多靠近 \(0\),更关注低噪声 |
| \(\mu>0\) | \(u\) 偏正,所以 \(t\) 更多靠近 \(1\),更关注高噪声 |
对于高分辨率数据,常把采样分布向更高噪声区域移动,用来处理像素之间的强相关性。高分辨率图像里相邻像素高度相关,低噪声区域的局部预测可能太容易,模型更需要在较高噪声下学习全局结构和语义。
6.8 Latent Diffusion Models(LDM)
6.8.1 基本 Pipeline
Rectified Flow / diffusion 直接在高分辨率像素空间上运行会非常昂贵。假设图像是 \(1024\times1024\times3\),像素维度巨大,扩散模型每一步都要处理完整图像,计算和显存压力很高。因此现代图像生成常使用 Latent Diffusion Models(LDMs)。
LDM 的核心做法是:先训练一个 encoder-decoder,把图像压缩到低分辨率 latent 空间,再在 latent 空间里做扩散。

第一阶段训练 encoder 和 decoder,得到 latent 表示,这会显著降低扩散模型需要处理的空间分辨率。Encoder / decoder 通常是带 attention 的 CNN。
第二阶段训练 diffusion model。此时 encoder 固定不动,真实图像先被 encoder 压缩成 latent,再给 latent 加噪,扩散模型学习在 latent 空间去噪。
第三阶段进行采样,流程是:
- 随机采样一个 latent 噪声。(通常从标准高斯分布采样)
- 在 latent 空间迭代地用扩散模型去噪。
- 用 decoder 把干净 latent 解码成最终图像。
LDM 现在非常常见,因为它把高分辨率图像生成的主要计算转移到更小的 latent 空间中,在质量和效率之间取得较好平衡。
6.8.2 现代 Pipeline
那么 encoder-decoder 怎么训练?答案是:它通常是一个 VAE,但和前面入门 VAE 有一些工程差异。
LDM 的 encoder-decoder 需要满足两个目标:
- latent 要足够紧凑,方便扩散模型处理。
- decoder 要能从 latent 重建出清晰图像。
因此它通常使用 VAE 式训练,并带有很小的 KL prior 权重。KL 项仍然约束 latent 空间不要太乱,但权重较小,避免过强正则导致重建质量下降。
问题是:普通 VAE 的 decoder 输出容易偏模糊。为了解决这个问题,现代 LDM pipeline 往往加入 GAN discriminator,让重建图像不仅在像素或感知损失上接近原图,还要能骗过判别器,从而提升纹理和细节锐度。
所以现代的 LDM pipeline 为:
\[ \text{Modern LDM pipelines}=\text{VAE}+\text{GAN}+\text{diffusion} \]
6.9 Diffusion Transformer(DiT)
Diffusion Transformer(DiT)把扩散模型的主干网络换成标准 Transformer block。关键问题不在于 Transformer 能不能用于扩散,而在于如何把条件信息注入 Transformer。
扩散模型里的条件信息至少包括:
- diffusion timestep \(t\);
- 文本 embedding;
- 图像条件;
- 类别标签或其他控制信号。
常见注入方式有两类:
| 条件注入方式 | 常见用途 | 直觉 |
|---|---|---|
| Predict scale/shift | diffusion timestep \(t\) | 用时间步 embedding 生成归一化层或 block 内部的缩放和平移参数 |
| Cross-Attention / Joint Attention | 文本、图像等条件 | 让 noisy latent tokens 和条件 tokens 通过 attention 交互 |
Predict scale/shift 和前面讨论的 AdaLN 思想接近:先把条件 \(c\) 编码成向量,再用小网络或线性层生成每一层需要的 scale/shift,让网络知道当前处在什么时间步或什么条件下。
Cross-Attention / Joint Attention 则更适合文本和图像条件。例如文生图中,文本编码器会输出一串 text embeddings;图像 latent patch 形成 image tokens;扩散 Transformer 通过 attention 让 image tokens 查询文本信息,从而生成符合 prompt 的内容。
6.10 文生图系统
现代文生图系统通常是 LDM + DiT + 文本编码器的组合。整体流程如下:
- 输入文本 prompt。
- 预训练文本编码器将 prompt 转成 text embeddings,例如 T5 或 CLIP。
- 从随机 noisy latents 开始。
- Diffusion Transformer 接收 noisy latents、diffusion timestep 和 text embeddings。
- Transformer 逐步预测 clean latents 或速度方向。
- Decoder 把 clean latents 解码成图像。
这个例子说明:现代高分辨率文生图并不是直接在像素上扩散,而是在压缩 latent 上运行大型 Transformer,再由 decoder 还原图像。
6.11 文生视频
文生视频可以看作把图像 latent 扩展到时间维:
\[ t_{\mathrm{video}}\times h\times w\times c \]
输出视频则是:
\[ T\times H\times W\times 3 \]
相比图像,视频生成多了时间一致性问题:模型不仅要每一帧好看,还要保证物体运动、相机运动、身份、背景和物理关系在时间上连贯。因此 token 数量和计算成本都会显著增加。
视频扩散模型的规模会迅速变大。2024-2025 年视频扩散模型,快速发展,例如 Sora、MovieGen、HunyuanVideo、Cosmos、Wan 等。视频生成正在沿着大规模 latent diffusion + DiT + 多模态条件的路线快速扩展。
6.12 Diffusion Distillation:减少采样步数
扩散模型质量高,但一个主要缺点是采样慢。即使是 Rectified Flow,采样时也常需要运行扩散模型约 30 到 50 步。每一步都要做一次大型神经网络前向传播,文生图已经昂贵,文生视频更昂贵。
Diffusion Distillation 的目标是:把多步采样模型压缩成少步模型,甚至一步模型。直觉上,原模型像一个老师,学生模型学习老师从噪声到数据的整体轨迹,用更少步完成类似效果。
常见蒸馏方向包括:
| 方法方向 | 直觉 |
|---|---|
| Progressive distillation | 逐渐把多步采样压缩成更少步 |
| Consistency models | 训练模型在不同噪声时间之间保持一致映射 |
| Adversarial diffusion distillation | 引入对抗目标,改善少步生成质量 |
| Moment matching 等多步蒸馏 | 让学生模型匹配老师采样分布的统计性质 |
课件还提到,蒸馏有时可以把 CFG 的效果也 bake in 到模型里。也就是说,学生模型不一定还需要每一步分别跑条件和无条件预测,而是直接学到带 guidance 的生成行为,从而进一步降低采样成本。
总结起来,扩散模型的现代工程路线是:
\[ \text{高质量训练} \rightarrow \text{latent 空间降低成本} \rightarrow \text{DiT 扩展模型容量} \rightarrow \text{CFG 提升条件符合度} \rightarrow \text{distillation 加速采样} \]
6.13 Diffusion 的通用框架
本小节介绍扩散模型的统一框架。先采样真实数据、噪声和时间:
\[ x\sim p_{\mathrm{data}},\quad z\sim p_{\mathrm{noise}},\quad t\sim p_t \]
然后用一组时间相关函数构造带噪样本:
\[ x_t=a(t)x+b(t)z \]
再构造模型要预测的目标:
\[ v_{\mathrm{gt}}=c(t)x+d(t)z \]
模型输入 \(x_t\) 和 \(t\),输出预测:
\[ v_{\mathrm{pred}}=f_\theta(x_t,t) \]
训练损失为:
\[ \mathcal{L}=\|v_{\mathrm{gt}}-v_{\mathrm{pred}}\|_2^2 \]
这里继续用 \(v_{\mathrm{gt}}\) 表示广义预测目标,是为了避免和条件生成里的标签 / prompt \(y\) 混淆;但它不一定总是严格意义上的速度。比如 \(x\)-prediction 预测的是干净数据,\(\epsilon\)-prediction 预测的是噪声。
不同的扩散模型可以选择不同的 \(a(t),b(t),c(t),d(t)\)。首先是带噪路径 \(x_t=a(t)x+b(t)z\) 的常见选择:
| 形式 | \(a(t)\) | \(b(t)\) | 含义 |
|---|---|---|---|
| Rectified Flow | \(1-t\) | \(t\) | 在数据 \(x\) 和噪声 \(z\) 之间做线性插值;\(t=0\) 是数据,\(t=1\) 是噪声 |
| Variance Preserving (VP) | \(\sigma(t)\) | \(\sqrt{1-\sigma(t)^2}\) | 若 \(x,z\) 独立且方差都为 \(1\),则 \(x_t\) 的方差仍约为 \(1\) |
| Variance Exploding (VE) | \(1\) | \(\sigma(t)\) | 保留数据项,同时逐渐增大噪声强度;\(\sigma(1)\) 需要足够大以淹没数据中的信号 |
然后是预测目标 \(v_{\mathrm{gt}}=c(t)x+d(t)z\) 的常见选择:
| 预测目标 | \(v_{\mathrm{gt}}\) | \(c(t)\) | \(d(t)\) | 含义 |
|---|---|---|---|---|
| \(x\)-prediction | \(x\) | \(1\) | \(0\) | 直接预测干净数据 |
| \(\epsilon\)-prediction | \(z\) | \(0\) | \(1\) | 预测加入的噪声 |
| \(v\)-prediction | \(b(t)z-a(t)x\) | \(-a(t)\) | \(b(t)\) | 预测数据项和噪声项的组合方向 |
6.14 扩散模型的三种理解视角
扩散模型还可以从几个角度理解:
- Latent variable model: 已知前向加噪过程,学习近似反向去噪过程,并可优化类似 VAE 的变分下界。
- Score matching: 学习 score function \(s(x)=\nabla_x\log p(x)\),即指向高概率密度区域的向量场。
- SDE 视角: 连续加噪可写成随机微分方程 \(d\mathbf{x}=f(\mathbf{x},t)dt+g(t)d\mathbf{w}\),模型学习近似求解反向过程。
6.14.1 扩散模型是一种 Latent Variable Model
从 latent variable model 的角度看,扩散模型像一个有很多层 latent variables 的生成模型。前向过程从真实数据 \(x_0\) 出发,逐步加噪得到
\[ x_0 \rightarrow x_1 \rightarrow \cdots \rightarrow x_T \]
其中 \(x_T\) 接近简单噪声分布,例如标准高斯。这个前向加噪过程是人为设计的,所以我们知道如何从 \(x_0\) 得到不同噪声等级的 \(x_t\)。
生成时则要学习反向过程:
\[ x_T \rightarrow x_{T-1} \rightarrow \cdots \rightarrow x_0 \]
也就是从噪声一步步还原到数据。这里的中间状态 \(x_1,\dots,x_{T-1}\) 可以看作 latent variables。因为真实反向分布通常不可直接计算,所以用神经网络近似每一步的反向去噪分布或反向更新方向。这个视角和 VAE 有相似之处:两者都可以被看作带 latent variables 的概率模型,并且都可以推导出类似变分下界的训练目标。
6.14.2 扩散模型学习 Score Function
从 score matching 的角度看,扩散模型学习的是数据分布在不同噪声等级下的 score function:
\[ s(x_t,t)=\nabla_{x_t}\log p_t(x_t) \]
这里 \(p_t(x_t)\) 表示加噪到时间 \(t\) 后的样本分布。score function 的方向可以理解为:“如果想让当前点 \(x_t\) 变得更像高概率样本,应该往哪里移动。”
这个视角解释了为什么去噪和生成有关。一个带噪样本里既有数据的结构,也有随机噪声;如果模型能估计当前位置附近概率密度上升最快的方向,就可以把样本从低概率的噪声区域推向高概率的数据流形。反复应用这个方向,就能从纯噪声逐步走向真实数据分布附近。
6.14.3 扩散模型解决了随机微分方程
从 SDE(Stochastic Differential Equation,随机微分方程)的角度看,连续时间加噪过程可以写成:
\[ d\mathbf{x}=f(\mathbf{x},t)dt+g(t)d\mathbf{w} \]
其中 \(f(\mathbf{x},t)\) 是确定性的 drift 项,\(g(t)d\mathbf{w}\) 是随机噪声项。这个方程描述了样本如何随着时间逐渐从数据分布扩散到噪声分布。
生成时需要反过来求解从噪声到数据的过程。反向 SDE 的形式依赖于前面提到的 score function,所以神经网络学习 score 或等价的去噪目标后,就可以作为反向过程的一部分来采样。这个视角把扩散模型和连续动力系统、数值积分联系起来,也解释了为什么采样时会出现多步更新、步长、solver 等概念。
7 总结与易考点
7.1 四类生成模型对比
| 方法 | 密度形式 | 训练目标 | 采样方式 | 主要优点 | 主要缺点 |
|---|---|---|---|---|---|
| 自回归模型 | 显式、可计算 | 最大似然 / NLL | 逐 token 采样 | 概率清楚、效果强 | 长序列采样慢 |
| VAE | 显式但需近似 | ELBO | 从 prior 采样 latent 后 decode | 训练稳定、latent 连续 | 图像容易模糊 |
| GAN | 隐式 | 生成器-判别器 minimax | 一次前向生成 | 样本锐利、采样快 | 训练不稳定、无显式 likelihood |
| 扩散模型 | 隐式或多视角解释 | 去噪/flow/score matching 目标 | 从噪声迭代去噪 | 质量高、训练稳定 | 多步采样慢 |
7.2 必须掌握的公式
自回归分解:
\[ p(x)=\prod_{t=1}^{T}p(x_t\mid x_{<t}) \]
最大似然:
\[ W^*=\arg\max_W\sum_i\log p(x^{(i)}) \]
VAE 的 ELBO:
\[ \mathbb{E}_{z\sim q_\phi(z\mid x)}[\log p_\theta(x\mid z)] - D_{\mathrm{KL}}(q_\phi(z\mid x)\,\|\,p(z)) \]
GAN 目标:
\[ \min_G\max_D \mathbb{E}_{x\sim p_{\mathrm{data}}}[\log D(x)] + \mathbb{E}_{z\sim p(z)}[\log(1-D(G(z)))] \]
Rectified Flow:
\[ x_t=(1-t)x+tz,\quad v_{\mathrm{gt}}=z-x,\quad \mathcal{L}=\|f_\theta(x_t,t)-v_{\mathrm{gt}}\|_2^2 \]
Classifier-Free Guidance:
\[ v_{\mathrm{cfg}}=(1+w)v_y-wv_{\emptyset} \]
7.3 易混点
- 生成模型不一定都能算 \(p(x)\)。 自回归模型可以显式算;GAN 通常不能;扩散模型可从多个数学视角解释,但实践重点常是采样过程。
- VAE 不是普通 autoencoder 加噪声。 它有明确的潜变量概率模型,并通过 ELBO 同时训练 encoder 和 decoder。
- GAN 的 discriminator 不是最终分类器。 它是训练信号来源,最终生成时只需要 generator。
- 扩散的“去噪”不是简单滤波。 模型学习的是从噪声分布到数据分布的反向生成动力学。
- CFG 提升条件符合度,但有代价。 它通常增加采样计算量,并可能降低多样性。
- 现代图像生成常在 latent 空间完成。 这样比直接在像素空间扩散更省计算,也更适合高分辨率输出。
7.4 一句话串联两讲
Lecture 13 建立生成模型的概率基础:从 \(p(y\mid x)\) 到 \(p(x)\) / \(p(x\mid y)\),再讲自回归模型和 VAE 如何用显式或近似似然训练。Lecture 14 转向更强的现代生成方法:GAN 用对抗训练实现隐式采样,扩散模型用逐步去噪或 flow 学习从噪声到数据的路径,而 LDM、DiT、CFG 和蒸馏共同构成了今天图像与视频生成系统的主流工程形态。
\[\bar{\alpha}t = \prod_{s=1}^{t}\alpha_s\]