第 6 讲 · 生成对抗网络与概率图模型 · Generative Adversarial Networks + Probabilistic Graphical Models

Generative AI · Lecture 06。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应 Maps to:CMU 10-423 / 10-623 / 10-723 Generative AI(Spring 2026;Aran Nayebi、Matt Gormley),Lecture 6 · Mon 2-Feb · GANs / PGM。 阅读材料:Goodfellow et al. (2014), Generative Adversarial Nets;Goodfellow (2016), NIPS 2016 Tutorial: Generative Adversarial Networks。 依据说明:本讲以原课第 6 讲公开的 slides(lecture6-gans.pdf)为主线:图像生成任务;GAN 的生成器(DCGAN)、判别器(PatchGAN)与极小极大博弈;GAN 的学习(交替训练、穿过随机噪声的反向传播、块坐标下降);条件 GAN;把模型做大、GAN 与扩散模型的对比、水印与溯源、社会影响;有向图模型(定义、定性与定量描述、高斯有向图、观测变量)、马尔可夫模型、“把 RNN-LM 画成有向图”的课堂练习、无向图、因子图(势函数表、配分函数、因子是张量)、局部归一化与全局归一化、推断的三个任务;无监督学习与隐变量模型;扩散模型和 VAE 的预告。最优判别器与 JS 散度、非饱和损失、模式崩塌等理论来自 Goodfellow et al. (2014) 原文和 2016 年的教程。“形状世界”上的实验和评估方法是本讲义自己设计的,不代表课堂上讲了什么。 配套代码 Code:code/lecture06/(6 个脚本 + 2 个模块;需要 PyTorch CPU 版;01、06 几秒,02–05 各约 1–1.5 分钟) 预计阅读时间:4 小时(含运行代码)


0. 本讲导航 · How to read this lecture

0.1 学习目标 Learning goals

学完这一讲,你应该能够:

  1. 说出图像生成的主要任务,区分”生成 p(x | y)“和”分类 p(y | x)”。
  2. 描述 GAN 的两个网络和极小极大目标;推导最优判别器和”目标 = −log 4 + 2·JS 散度”;解释”判别器是一个密度比估计器”。
  3. 解释交替训练、为什么用非饱和的生成器损失、为什么 JS 散度在分布不重叠时给不出梯度。
  4. 用实验描述模式崩塌和”追着跑”,并用”前向 KL 覆盖、反向 KL 寻模”解释 GAN 和最大似然的区别。
  5. 说出评估生成模型的几种方法(FID 式的 Fréchet 距离、分类器、拟合、最近邻),以及它们各自会被什么骗过。
  6. 写出有向图模型的分解,做祖先采样,解释观测变量、推断和”解释消除”;区分局部归一化与全局归一化,说出配分函数为什么难算。
  7. 解释为什么 GAN 不能做最大似然、隐变量模型是什么,以及扩散模型和 VAE 将要走的路。

0.2 先修与本讲范围 Prerequisites & scope

默认你已经会 Assumed本讲只给直觉,后面再展开 Previewed only
前置讲 P2:KL 散度、前向 / 反向 KL、高斯、EM、祖先采样扩散模型(第 7–8 讲)
第 1 讲:自动微分、RNN 语言模型变分推断、ELBO、VAE、重参数化(第 9 讲)
第 5 讲:卷积、CNN、“形状世界”文生图、潜空间扩散(第 12、14 讲)

0.3 本讲地图 Map

§1  图像生成:任务谱系
§2  GAN:生成器、判别器、极小极大博弈                                   ← 代码 03(第 0 部分)
§3  学习 GAN:交替训练、最优判别器与 JS、饱和、模式崩塌、和最大似然的对比  ← 代码 01、02、04
§4  形状世界上的 DCGAN:训练、评估、插值、记忆                           ← 代码 03
§5  条件 GAN;把模型做大;水印与溯源;社会影响                           ← 代码 05
§6  概率图模型:有向图、马尔可夫模型、无向图、因子图、推断                ← 代码 06
§7  无监督学习与隐变量;为什么 GAN 不能做最大似然;预告扩散和 VAE         ← 代码 01(第 4 部分)
§8–12  小结、误区、练习、延伸阅读、下一讲

0.4 本讲(以及第 7–9 讲)的尺子:怎样给”画出来的图”打分

分类器有准确率,语言模型有困惑度,GAN 却连 p(x)p(x) 都算不出来(§7.2)。它画得好不好,怎么打分?“好”至少有两层意思:质量(每一张像不像真的)和多样性(合起来有没有覆盖真实数据的各种情况)。只会画”正中间的一个圆”的模型,每张都很像,却漏掉了几乎所有数据。

形状世界是我们自己画的(第 5 讲 §0.4),所以可以做真实数据集上做不到的检查。shape_metrics.py 准备了四把尺子,第 6–9 讲的 GAN、扩散模型、VAE 都用同一套:

尺子做法主要看会被什么骗
形状裁判在真图上训练好的小 CNN(新图上准确率 0.992),看生成的图被判成哪类、有多确定四类的比例(缺了哪类)、确信度对空白图、怪图也会给出很高的确信度;对画得不标准的形状,和形状拟合常常意见不一致(§4.2)
Fréchet 距离(FD)真图和生成图都过一遍裁判,取分类前的 32 维特征,各拟合一个高斯,算两个高斯的 Fréchet 距离质量和多样性的综合裁判特征几乎不含位置信息;样本少时偏大
形状拟合渲染器可微,用梯度下降找”最像这张图的完美形状”(类别、中心、半径、角度),看残差每一张是不是一个干净的形状;位置 / 大小的分布不加约束时,空白图会被”很小的形状”拟合得很好(我们踩过这个坑,见 §4.2)
最近邻距离每张生成图和训练集里最像的那张差多少是不是在背训练集—

FD 就是图像生成领域最常用的指标 FID(Fréchet Inception Distance,Heusel et al., 2017)的缩小版:FID 用 ImageNet 上训练的 Inception 网络的特征。两个高斯 N(μ1,Σ1)\mathcal N(\mu_1, \Sigma_1)、N(μ2,Σ2)\mathcal N(\mu_2, \Sigma_2) 之间的 Fréchet 距离是

FD=∥μ1−μ2∥2+Tr ⁣(Σ1+Σ2−2 (Σ11/2Σ2Σ11/2)1/2).\mathrm{FD} = \lVert \mu_1 - \mu_2 \rVert^2 + \mathrm{Tr}\!\left(\Sigma_1 + \Sigma_2 - 2\,(\Sigma_1^{1/2}\Sigma_2\Sigma_1^{1/2})^{1/2}\right).

第一项比较”平均长什么样”,第二项比较”变化的范围”。只会画一种图的模型 Σ\Sigma 很小,第二项就大。注意 FD 即使对两批独立的真图也不是 0:我们的”满分”是 0.48(500 张 vs 500 张)。几个坏例子的分数(python3 shape_metrics.py 的自检):只画正中间同一个圆,FD 454(形状拟合却给满分——每张都是完美的圆);只画圆、位置随机,FD 274;把真图用 3×3 的窗口模糊一下,FD 45(形状拟合照样给满分,但边缘宽度从 0.61 变成 0.82、像素噪声从 0.030 降到 0.011——这两列是后来为第 8、9 讲加的)。


1. 图像生成:任务谱系 · The task of image generation

slides 列了五类任务:

  • 类别条件生成(class-conditional generation):给一个类别标签(海葵、脑珊瑚、蛞蝓、金翅雀……),采一张这一类的新图。图像分类是从图像预测标签 p(y∣x)p(y \mid x),类别条件生成正好反过来:p(x∣y)p(x \mid y)。
  • 超分辨率(super resolution):给一张低分辨率的图,生成一张高分辨率的重建。
  • 图像编辑:补全(inpainting,填上指定的缺失像素)、上色(colorization,给灰度图恢复颜色)、扩图(uncropping,生成图像缺失的一侧)。
  • 风格迁移(style transfer):把两张图”混合”——保留一张图的内容,用另一张图的风格呈现。
  • 文生图(text-to-image):给一段文字,采一张描绘它的图。slides 的例子来自 Gemini 2.5 Flash Image(Nano Banana)和 SDXL。

slides 还开了个玩笑:让 Stable Diffusion 画”一张讲解 GAN 的课程幻灯片”,画出来的东西完全不能用;GPT-5 好得多,但”不够详细”。文生图模型画得出好看的图,却画不出正确的文字和结构——这个话题第 12、14 讲还会回来。

为什么图像生成难?一张 28×28 的灰度图就是 784 维空间里的一个点;一张 1024×1024 的彩色图是 300 多万维。真实图像在这个空间里只占一个极薄的”流形”——随机撒的点几乎都是噪声。生成模型要学会把概率质量放到这块薄薄的流形上,而且要放得全。


2. GAN:生成器、判别器与极小极大博弈 · The GAN model

2.1 直觉:造假币的人和警察

Goodfellow 的比喻:生成器像造假币的团伙,判别器像警察。警察越会识别假币,造假的人就得做得越真;最后假币真到警察只能靠猜(判对的概率 1/2)。这个过程里没有人需要写出”真币的概率分布”——警察只要会二分类,造假的人只要会根据警察的反馈改进工艺。

2.2 两个确定性的网络

slides 的定义:GAN 由两个确定性的神经网络组成。

  1. 生成器 Generator GθG_\theta:输入一个随机噪声向量 z∼pz=N(0,σ2I)z \sim p_z = \mathcal N(0, \sigma^2 I),输出一张图 x=Gθ(z)x = G_\theta(z)。
  2. 判别器 Discriminator DϕD_\phi:输入一张图,输出它是真图的概率 Dϕ(x)=p(real∣x)D_\phi(x) = p(\text{real} \mid x)(真 = 1,假 = 0)。

注意”确定性”:给定 zz,Gθ(z)G_\theta(z) 是唯一的一张图;随机性只来自输入的 zz。所以生成器定义的分布 pgp_g 是”把 N(0,σ2I)\mathcal N(0, \sigma^2 I) 推过 GθG_\theta 之后得到的分布”——采样极其容易(采一个 zz,跑一次前向),可是它的密度 pg(x)p_g(x) 写不出来(§7.2)。

2.3 生成器:DCGAN 与”分数步长卷积”

slides 的例子是 DCGAN(Radford et al., 2016):一个”倒过来的 CNN”,用四层分数步长卷积(fractionally-strided convolution,不是反卷积 deconvolution)把图像一层层变大,最后一层是红绿蓝三个通道。

分数步长卷积也叫转置卷积(transposed convolution)。它做的事是:先在输入像素之间插 0(相当于”步长 1/2”),再做普通卷积,所以尺寸翻倍。03 的第 0 部分验证了这一点:ConvTranspose2d(核 4, 步长 2, 填充 1) 把 7×7 变成 14×14,和”插零到 13×13 → 四周补 2 圈 0 → 用翻转的核做普通卷积”的结果最大相差 2.4e-7(浮点舍入)。输出尺寸的公式是

Hout=(Hin−1)×stride−2×padding+kernel=(7−1)×2−2+4=14.H_{\text{out}} = (H_{\text{in}} - 1)\times \text{stride} - 2\times\text{padding} + \text{kernel} = (7-1)\times 2 - 2 + 4 = 14 .

为什么叫”转置”:普通卷积可以写成一个(稀疏的)矩阵乘法 y=Cxy = Cx;转置卷积就是乘以 C⊤C^\top,形状上”反过来”。它也正是普通卷积对输入求梯度时用的运算(第 5 讲 §2.7)。它不是卷积的逆(逆运算会把 yy 还原成 xx,转置做不到),所以 slides 特意说”不是反卷积”。

我们的形状世界生成器(gan_lab.DCGenerator,14.3 万参数):

z (32 维) → 全连接 → (64, 7, 7) → BN → ReLU
          → 转置卷积 → (32, 14, 14) → BN → ReLU
          → 转置卷积 → (1, 28, 28) → Sigmoid(像素值在 0 到 1 之间)

2.4 判别器:CNN 与 PatchGAN

判别器就是一个二分类 CNN。slides 的例子是 PatchGAN(Isola et al., 2017;Demir & Unal, 2018):不是对整张图给一个”真 / 假”,而是对每个小块分别判断。这样判别器更关注局部的纹理和细节,有助于避免生成模糊的图。我们的判别器(DCDiscriminator,约 1 万参数)用两个步长 2 的卷积把 28×28 降到 7×7,再接一个线性层输出一个 logit。

2.5 极小极大博弈

训练时 GAN 在玩一个两人的极小极大博弈(minimax game):

  1. 生成器想造出足够真的图,骗判别器把它们判成真的;
  2. 判别器想把真图和假图分开。

写成目标函数(slides 把两边分开写):

max⁡ϕ ∑ilog⁡Dϕ(x(i))+log⁡ ⁣(1−Dϕ(Gθ(z(i)))),min⁡θ ∑ilog⁡ ⁣(1−Dϕ(Gθ(z(i)))).\max_\phi\ \sum_i \log D_\phi(x^{(i)}) + \log\!\big(1 - D_\phi(G_\theta(z^{(i)}))\big), \qquad \min_\theta\ \sum_i \log\!\big(1 - D_\phi(G_\theta(z^{(i)}))\big).

判别器在最大化一个二分类器的对数似然(标签:真 = 1、假 = 0),生成器的输出是固定的;生成器在最小化”它的假图被判成假”的对数似然,判别器是固定的。合起来就是 Goodfellow et al. (2014) 的

min⁡θmax⁡ϕ V(Dϕ,Gθ)=Ex∼pdata[log⁡Dϕ(x)]+Ez∼pz[log⁡(1−Dϕ(Gθ(z)))].\min_\theta \max_\phi\ V(D_\phi, G_\theta) = \mathbb E_{x\sim p_{\text{data}}}[\log D_\phi(x)] + \mathbb E_{z\sim p_z}[\log(1 - D_\phi(G_\theta(z)))].

slides 的计算图把它画成:真图 x′x' 进判别器,标签 y′=1y' = 1,损失项 J′=log⁡D(x′)J' = \log D(x');假图 G(z)G(z) 进判别器,标签 y=0y = 0,损失项 J=log⁡(1−D(G(z)))J = \log(1 - D(G(z)));总的是 J+J′J + J'。


3. 学习 GAN · Learning for GANs

3.1 交替训练

slides:“目标函数是一个简单的可微函数;我们选的 G 和 D 都是可微的神经网络。训练在两件事之间交替:固定 G、对 D 反向传播;固定 D、对 G 反向传播。”

训练数据是 mm 张无标签的图 x(1),…,x(m)x^{(1)}, \ldots, x^{(m)}。优化过程像块坐标下降(block coordinate descent:轮流只优化一部分变量),但不是每次把 min 或 max 精确解出来,而是只走一步小批量 SGD。Goodfellow et al. (2014) 的算法 1 允许判别器每轮走 kk 步,生成器走 1 步;论文的实验用 k=1k = 1。

gan_lab.train_gan 就是这个循环:

for step in range(steps):
    # 1. 判别器:假图 detach(梯度不传回 G),最小化二分类交叉熵
    fake = G(z).detach()
    ld = softplus(-D(x_real)).mean() + softplus(D(fake)).mean()     # = −log D(x) − log(1 − D(G(z)))
    opt_d.zero_grad(); ld.backward(); opt_d.step()
    # 2. 生成器:梯度穿过 D 流回 G,但只更新 G 的参数
    lg = softplus(-D(G(z))).mean()                                   # 非饱和损失 −log D(G(z)),见 §3.4
    opt_g.zero_grad(); lg.backward(); opt_g.step()

两个细节:判别器输出的是 logit aa,D=σ(a)D = \sigma(a),于是 log⁡D=−softplus(−a)\log D = -\mathrm{softplus}(-a)、log⁡(1−D)=−softplus(a)\log(1 - D) = -\mathrm{softplus}(a),永远不会出现 log⁡0\log 0;生成器那一步虽然也算出了判别器参数的梯度,但只调用 opt_g.step(),判别器的梯度会在下一次 opt_d.zero_grad() 时清掉。

slides 的问题:有一个随机的高斯在里面,怎么对 G 反向传播? 答案:zz 是从一个固定的分布 N(0,σ2I)\mathcal N(0, \sigma^2 I) 里采的,它不依赖任何参数——对 θ\theta 来说,zz 就是一个普通的输入。我们需要的是 ∇θlog⁡(1−D(Gθ(z)))\nabla_\theta \log(1 - D(G_\theta(z))),而 Gθ(z)G_\theta(z) 对 θ\theta 是确定性的、可微的,链式法则直接穿过 DD 和 GG 就行。不需要对”采样”这个动作求导。(对比第 9 讲的 VAE:那里的随机变量 z∼qϕ(z∣x)z \sim q_\phi(z \mid x) 的分布依赖参数 ϕ\phi,才需要”重参数化技巧”把随机性挪到一个固定的噪声上——而 GAN 天生就是这种形式。)

3.2 最优判别器与 JS 散度

固定生成器,判别器最好能做到什么程度?把 VV 写成积分:

V(D,G)=∫(pdata(x)log⁡D(x)+pg(x)log⁡(1−D(x))) dx.V(D, G) = \int \Big( p_{\text{data}}(x)\log D(x) + p_g(x)\log(1 - D(x)) \Big)\, dx .

对每个 xx 单独最大化被积函数 alog⁡y+blog⁡(1−y)a\log y + b\log(1-y)(a=pdata(x)a = p_{\text{data}}(x),b=pg(x)b = p_g(x)),令导数 a/y−b/(1−y)=0a/y - b/(1-y) = 0,得到最优判别器

D∗(x)=pdata(x)pdata(x)+pg(x).D^*(x) = \frac{p_{\text{data}}(x)}{p_{\text{data}}(x) + p_g(x)} .

代回去,记 m=12(pdata+pg)m = \tfrac12(p_{\text{data}} + p_g):

V(D∗,G)=Epdata ⁣[log⁡pdata2m]+Epg ⁣[log⁡pg2m]=−log⁡4+KL(pdata ∥ m)+KL(pg ∥ m)=−log⁡4+2 JS(pdata ∥ pg).V(D^*, G) = \mathbb E_{p_{\text{data}}}\!\left[\log\frac{p_{\text{data}}}{2m}\right] + \mathbb E_{p_g}\!\left[\log\frac{p_g}{2m}\right] = -\log 4 + \mathrm{KL}(p_{\text{data}} \,\|\, m) + \mathrm{KL}(p_g \,\|\, m) = -\log 4 + 2\,\mathrm{JS}(p_{\text{data}} \,\|\, p_g).

JS 散度(Jensen–Shannon divergence)对称、非负,只在 pg=pdatap_g = p_{\text{data}} 时为 0。所以:判别器训练到最优时,生成器在最小化它和真实分布之间的 JS 散度;全局最优是 pg=pdatap_g = p_{\text{data}},此时 D∗≡1/2D^* \equiv 1/2,V=−log⁡4V = -\log 4。

01 的第 1 部分在一维网格上把每一项都算了出来(真实分布是 ±2 处的两个峰,“生成器”是 N(0.5,1)\mathcal N(0.5, 1)):

判别器V(D,G)V(D, G)
D∗D^*−0.68824
D≡0.5D \equiv 0.5(分不清真假)−1.38629
0.9D∗+0.050.9 D^* + 0.05(稍微偏一点)−0.71612
一刀切 1[x>0]1[x > 0]−32.9(log⁡0\log 0 按 log⁡10−12\log 10^{-12} 算,否则是 −∞)

而 −log⁡4+2×0.34902=−0.68824-\log 4 + 2 \times 0.34902 = -0.68824,和 V(D∗,G)V(D^*, G) 一致。

3.3 判别器是一个密度比估计器

由 D∗D^* 的公式,

D∗(x)1−D∗(x)=pdata(x)pg(x).\frac{D^*(x)}{1 - D^*(x)} = \frac{p_{\text{data}}(x)}{p_g(x)} .

一个”真 vs 假”的二分类器,其实在估计两个分布的密度比。01 从 4000 个真样本和 4000 个假样本训练了一个普通的小 MLP 二分类器,它学到的 DD 和 D∗D^* 平均只差 0.014(有概率质量的区域内,最大 0.063);在 x=1x = 1 处,真实比值 0.153,D/(1−D)D/(1-D) 估计 0.134。

这给了生成器一个很直观的学习信号:哪里真图比我的假图多,就往哪里挪。生成器从来不需要知道 pdatap_{\text{data}} 本身。这个”用分类器估计密度比”的思想在后面还会出现:第 11–12 讲的奖励模型、DPO 的推导里都有它的影子。

3.4 饱和:为什么实践中不用 slides 的生成器目标

slides 的生成器目标是 min⁡θlog⁡(1−D(G(z)))\min_\theta \log(1 - D(G(z)))。它对判别器 logit aa 的梯度是 −σ(a)=−D(G(z))-\sigma(a) = -D(G(z))。训练初期生成器很差,判别器很容易认出假图,D(G(z))≈0D(G(z)) \approx 0——梯度也 ≈ 0。生成器最需要指导的时候,信号最弱。这叫饱和(saturation)。

Goodfellow et al. (2014) 原文就建议换成 max⁡θlog⁡D(G(z))\max_\theta \log D(G(z)),即最小化 −log⁡D(G(z))-\log D(G(z)),它的梯度是 −(1−D(G(z)))-(1 - D(G(z))),在 D(G(z))≈0D(G(z)) \approx 0 时 ≈ −1,信号最强。这叫非饱和(non-saturating)损失。两者的不动点相同(都在 pg=pdatap_g = p_{\text{data}} 时最优),区别只在”离最优很远时”的梯度大小。

D(G(z))D(G(z))极小极大 log⁡(1−D)\log(1-D) 的梯度 =−D= -D非饱和 −log⁡D-\log D 的梯度 =−(1−D)= -(1-D)
0.001−0.0010−0.9990
0.01−0.0100−0.9900
0.5−0.5000−0.5000
0.9−0.9000−0.1000

01 的一维例子:真实数据在 2 附近,生成器 G(z)=μ+zG(z) = \mu + z 从 μ=−3\mu = -3 出发,判别器先单独训练好(此时假样本的平均 D(G(z))=0.0022D(G(z)) = 0.0022)。两种损失对 μ\mu 的梯度方向相同,大小差了 307 倍。

真实训练里会饱和吗? 一开始我以为在 GAN 训练里随处可见,实验却说”要看情况”:

  • 02(二维)和 03(图像)里,两个网络学习率相同、交替各走一步,D(G(z))D(G(z)) 始终在 0.15 以上,饱和根本没有发生;二维例子里极小极大版本甚至覆盖了更多模式(四个种子 7、6、7、8 个 vs 非饱和的 3、3、2、8 个)。
  • 04 让判别器”远远强于”生成器(每步先更新 5 次,学习率大 5 倍):第 100 步时假图的平均 D(G(z))D(G(z)) 是 0.0032(非饱和)和 0.0000(极小极大)。极小极大版本从此再也没起来——600 步里 D(G(z))D(G(z)) 一直是 0.0000,FD 从 6780 只降到 6523,样本是一片噪声;非饱和版本面对同样强的判别器,FD 从 981 降到 31.3。

结论:饱和是”判别器远远强于生成器”时的病,一旦发生就是恶性循环(判别器越强,生成器越学不动)。非饱和损失是便宜的保险,所以几乎所有实现都用它(gan_lab.g_loss 的默认值)。

3.5 当两个分布不重叠:JS 散度的盲区

JS≤ln⁡2\mathrm{JS} \le \ln 2,而且两个分布完全不重叠时恰好等于 ln⁡2\ln 2——不管它们相距多远。01 的第 3 部分:p=N(0,0.12)p = \mathcal N(0, 0.1^2),q=N(μ,0.12)q = \mathcal N(\mu, 0.1^2):

μ\mu00.10.20.515
JS00.1110.3370.6760.6930.693
Wasserstein-100.10.20.515

μ=1\mu = 1 和 μ=5\mu = 5 在 JS 看来完全一样:如果判别器是最优的,生成器面对的是一块平地,往哪边挪都一样,梯度为 0。高维图像空间里真实图像只占一个薄薄的流形,训练初期生成器的输出几乎不可能和它重叠——这是”判别器太强、生成器学不动”的另一个根源(Arjovsky & Bottou, 2017)。

两条出路:(1) WGAN(Arjovsky et al., 2017)把目标换成 Wasserstein 距离,它随 μ\mu 线性增长、永远指明方向;(2) 给数据加噪声,让两个分布重叠。扩散模型(第 7 讲)可以看成把第二条路走到了底:从”纯噪声”一路过渡到数据,每一步的两个分布都高度重叠。

3.6 模式崩塌与”追着跑”

02 用八个小高斯排成的一圈(半径 2,每个标准差 0.05)做数据。生成器(输入 8 维噪声)和判别器都是 3 层、128 宽的 MLP。

学习率 1e-4:整个训练过程中,任何时刻最多只覆盖 1 个模式——生成器把几乎所有样本都放在同一个地方(模式崩塌,mode collapse)。但这个地方在移动:样本最多的模式依次是 0、1、1、3、4、5、7、0、1、3、5、7、0、1、1、1;样本重心的角度在 15 次相邻记录之间有 14 次是逆时针变化,7500 步里累计转了 774°(约 2.2 圈)。

步数10002000300040005000600070008000
样本最多的模式13503711
样本重心的角度30°122°247°2°126°302°29°49°

(模式 0 在 0°,逆时针每 45° 一个。脚本把真实数据和第 1000、2000、3000 步的样本并排画成了字符图:每张图里只有一团点,位置在绕圈。)

为什么会”追着跑”:判别器发现假样本都挤在模式 A 附近,就把那里判成”假”;生成器为了骗它,整体挪到判别器还认为”真”的邻近模式 B;判别器随后又追过去……交替地各走一小步,不等于在解极小极大问题——双方可能永远在转圈,而不是收敛到 pg=pdatap_g = p_{\text{data}}。

学习率 1e-3:结果完全不同,四个随机种子最终覆盖 3、3、2、8 个模式。同一个算法、同一份数据,只是换了种子,有的近乎完美、有的只画两个模式。而且漏掉的模式往往再也回不来:生成器没有任何”我漏掉了什么”的信号——判别器只在生成器画了的地方给出反馈。

这就是 slides 说的 GAN “训练不稳定”:对超参数和随机种子极其敏感,没有一个”越来越小”的损失可以盯着看。

3.7 对照:最大似然宁可糊,GAN 宁可漏

02 的第 4 部分用最大似然(EM)拟合二维高斯混合:

模型平均对数似然覆盖的模式数高质量样本比例
真实分布+1.0748—
EM,K = 8 个分量+1.07780.99
EM,K = 3 个分量−3.3200.03

分量数够时,EM 找到了全部八个模式(前提是初始化得当:第一版完全随机地选初始中心,卡在只覆盖 4 个模式的局部最优,还有一个分量缩成了标准差 0.00 的”奇点”;改用 k-means++ 式初始化和标准差下限后 5 次都找到了全局最优)。分量数不够时,最大似然不会丢掉模式,而是让每个分量变得很宽、横跨好几个模式:所有真实数据附近都有概率,但大量样本落在模式之间的空地上。

这正是前置讲 P2 §3.5 的”前向 KL 覆盖、反向 KL 寻模”:

  • 最大似然 = 最小化 KL(pdata ∥ pθ)\mathrm{KL}(p_{\text{data}} \,\|\, p_\theta)。漏掉任何一块真实数据(那里 pθ≈0p_\theta \approx 0),log⁡pθ→−∞\log p_\theta \to -\infty,代价无穷大,所以宁可糊。
  • GAN 的目标更接近 JS 散度 / 反向 KL:画到没有数据的地方会被判别器抓住,漏掉一块数据却没有直接的惩罚,所以宁可漏。

这也解释了一个经验现象:GAN 的样本往往很清晰(不在空地上放概率),但多样性不足;基于似然的模型(VAE)的样本往往模糊,但覆盖全面。第 7–9 讲的扩散模型和 VAE 都回到了(变分形式的)最大似然。


4. 形状世界上的 DCGAN · A DCGAN on the shapes world

03 在 8192 张形状图上训练 §2.3 的生成器和 §2.4 的判别器,3000 步,每步 64 张真图 + 64 张假图,Adam(学习率 2e-4、β₁ = 0.5,DCGAN 论文的建议),非饱和损失。单线程 CPU 约 70 秒。

4.1 训练过程

步数判别器损失D(真图)D(假图)FD↓裁判眼中的四类比例(圆/方/三角/十)
5001.1130.5600.47292.70.11/0.33/0.45/0.11
10001.3140.4850.48459.80.29/0.43/0.26/0.01
15001.4200.4980.50539.30.13/0.45/0.35/0.07
20001.4110.5060.50644.90.14/0.46/0.35/0.04
25001.3910.5050.49957.20.13/0.37/0.42/0.08
30001.3840.5110.50333.80.14/0.38/0.39/0.09
  • 判别器损失很快接近 2ln⁡2=1.3862\ln 2 = 1.386,DD 对真图假图都给 0.5 左右:两个网络”势均力敌”。但这并不意味着生成器已经画得很好——只说明这个判别器已经分不清了。
  • FD 不是单调下降的(92.7 → 59.8 → 39.3 → 44.9 → 57.2 → 33.8)。GAN 的训练没有一个可以盯着看的损失曲线,实践中要定期评估、保存多个检查点。

4.2 画得怎么样

来源四类比例·裁判(圆/方/三角/十)四类比例·拟合两者一致FD↓拟合残差↓像形状的比例边缘宽度像素噪声位置标准差 x/y半径最近邻距离
真实新图(满分)0.26/0.23/0.28/0.240.26/0.24/0.26/0.240.990.480.00151.000.610.0304.0/4.16.2±1.10.074
DCGAN0.14/0.38/0.39/0.090.35/0.27/0.35/0.030.3133.850.01340.030.880.0323.9/3.76.0±1.90.128

(“像形状”= 最佳拟合的每像素均方误差 < 0.005;“两者一致”= 裁判和形状拟合判成同一类的比例;“边缘宽度”= 拟合形状时最合适的边缘模糊程度,“像素噪声”= 远离边缘的平坦区域里的噪声——这两列是第 8、9 讲比较”平滑 / 模糊”时加的,见 shape_metrics.edge_and_noise。裁判的平均确信度是 0.887,真图 0.967。)

  • 远看像,近看不准:裁判的平均确信度 0.887,但只有 3% 的图能被一个完美形状拟合到残差 0.005 以内,残差中位数是真图的 9 倍——边缘歪歪扭扭、角不够尖(字符画见脚本输出)。
  • “画的是哪一类”本身就说不清:裁判和形状拟合只有 31% 的时候判成同一类(真图 99%)。按裁判,圆(0.14)和十字(0.09)偏少;按形状拟合,圆反而不少(0.35),只有十字偏少(0.03)。两把尺子都同意的只有”十字偏少”——这是比较可信的部分模式崩塌(生成器不会被直接告知”你少画了十字”,这是图像上的 §3.6)。我一开始只看裁判,写的是”圆和十字都偏少”;加了形状拟合的对照后才发现,“圆偏少”只是裁判对”不够圆的圆”的看法。
  • 2% 的图几乎是空白的(最亮的像素不到 0.5)。裁判照样会把它们判成某个形状,而且很有把握——分类器只在它见过的分布上可靠。这里我们踩了一个坑:形状拟合的第一版不限制半径,一张空白图会被”半径 0.3 像素的形状”拟合得非常好(残差很小),被算成”像形状”;限制半径 ≥ 3 后,又发现”最像形状”的生成图全是半径 3 左右的小点(面积小,均方误差自然小)。最后把下限定为 4 像素(真实形状最小 4.5)。每一把尺子都会被某种东西骗过,所以要几把一起用。
  • 边缘比真图宽(0.88 vs 0.61),但平坦区域的像素噪声和真图相当(0.032 vs 0.030):GAN 连噪声的纹理也学着画了出来——第 9 讲 §9 会看到,这是它和 VAE 的一个明显区别。
  • 位置分布接近真实,半径更分散(6.0±1.9 vs 6.2±1.1)。

我们试过很多办法让它画得更准——更大的生成器和判别器、更大的学习率、训练 4000 步、对生成器权重做滑动平均(EMA)、去掉训练图里的像素噪声——最终的 FD 都在 24–67 之间(本讲的配置是 33.8),没有一种明显更好(见代码 README)。这本身就是一个结论:在这么小的算力预算下,GAN 很难把几何形状画准。第 8 讲会在同一个数据集上训练扩散模型,用同一套尺子比较。

4.3 隐空间插值

slides:“学好 GAN 之后,可以在隐空间 zz 里插值。“03 的第 2 部分从 64 个样本里挑出最像完美形状的两个(大小正常、形状不同:一个圆和一个三角形),在它们的 zz 之间走一条直线:

α00.170.330.50.670.831
裁判判为方方圆三角三角三角三角
最佳拟合圆圆圆圆方三角三角
拟合中心 x12.712.913.213.714.615.917.0

图像连续地变化:位置平滑移动,形状逐渐”变形”。生成器是连续函数,相近的 zz 给出相近的图。但中途经过的是”两种形状的混合体”,裁判和拟合常常意见不一致(连起点都有分歧:GAN 画的圆本来就不够圆)。隐空间里的直线并不保证每一步都落在”真实图像”上。

4.4 在背训练集吗?

生成图到训练集最近一张的距离(每像素均方根)中位数 0.128,比真实新图到训练集的距离(0.074)还大。生成器没有在背训练集——判别器从来不把训练图原样交给生成器,生成器只能通过判别器的梯度间接地”看到”它们。(真实新图到训练集的距离也不是 0:8192 张图远不足以覆盖”位置 × 大小 × 角度 × 形状”的所有组合。)

记忆是生成模型的一个真实风险:大规模的扩散模型被证明会原样复现一部分训练图(Carlini et al., 2023),这和版权、隐私直接相关(§5.4、第 22 讲)。


5. 条件 GAN 与规模化 · Conditional GANs and scaling up

5.1 条件 GAN

slides:“把一个标签嵌入接到生成器和判别器的输入上,GAN 就能生成指定类别的图像。“(Mirza & Osindero, 2014)生成器的输入变成 [z;e(y)][z; e(y)];判别器看到的是 (x,y)(x, y) 这一对,它要判断的不只是”真不真”,还有”和标签配不配”。

05 的实现:生成器把 8 维的类别嵌入接在 zz 后面;判别器把类别的 one-hot 展开成 4 张常数”平面”,和图像拼在通道维上。其他和 03 完全一样。结果却不太理想:

要求的类别裁判判对的比例裁判眼中的四类比例
圆0.030.03/0.54/0.34/0.08
正方形0.360.06/0.36/0.43/0.15
三角形0.490.06/0.02/0.49/0.43
十字0.570.00/0.04/0.39/0.57

整体只有 36.2% 判对(随机猜是 25%);按形状拟合是 33.4%。而且两把尺子连”哪一类最难”都不同意:裁判说是圆(0.03),形状拟合说是十字(0.12),圆反而有 0.55——和 §4.2 一样,画得不标准的图,归到哪一类本来就是模糊的。诊断:同一个 zz 换不同的类别,图像变化(均方差 0.037)只有换一个 zz(0.122)的 30%;同一个 zz 配 4 个类别,平均只被判成 2.4 种不同的形状。生成器主要靠 zz 决定画什么,类别只是微调。判别器只有约一万个参数,主要在分辨真假,没有被迫去检查”图和标签配不配”。我们还试过更大的判别器(0.40)、投影判别器(Miyato & Koyama, 2018;0.31)、更大的学习率(0.36)、去掉训练图的噪声(0.32),都在 0.3–0.4 之间。AC-GAN(Odena et al., 2017,让判别器同时预测类别)这类方法会更直接地强迫生成器服从类别。

条件生成的思路本身是一切”可控生成”的基础:第 12 讲的文生图把条件从 4 个类别换成了一整句文字,条件信息同样要同时交给生成模型的每个部分。

5.2 把模型做大

  • GAN 无处不在:slides 展示了”GAN 动物园”(the-gan-zoo 仓库,收录了数百种 GAN 变体)和 Henry Chai 的计算机视觉时间线:LeNet(1998)→ ImageNet(2009)→ AlexNet(2012)→ VAE(2013)→ GAN(2014)→ 扩散模型(2015)、ResNet(2015)→ Transformer(2017)→ DDPM(2020)→ ViT、DALL·E、CLIP(2021)→ DALL·E 2、Imagen、Stable Diffusion(2022)→ SDXL、SDXL Turbo(2023)。
  • GAN vs 扩散:slides 并排放了 GAN 生成的图、训练图和扩散模型生成的图。2021 年前后,扩散模型在多样性和可控性上全面超过了 GAN(Dhariwal & Nichol, 2021, Diffusion Models Beat GANs on Image Synthesis),大规模图像生成的主角换了人。GAN 的优势是一步生成,速度快;SDXL Turbo 这类模型又把对抗损失用回到扩散模型上来实现一步生成(第 14 讲)。
  • 规模的力量:slides 用 Parti(Google 的自回归文生图模型)展示同一个提示词在 3.5 亿、7.5 亿、30 亿、200 亿参数下的结果——模型越大,越能正确地画出”袋鼠穿着橙色连帽衫、戴蓝色墨镜、站在悉尼歌剧院前、胸前举着写有 Welcome Friends! 的牌子”。小模型连文字都写不对。规模化的规律第 15 讲再讲。

5.3 水印与溯源

  • 水印(watermarking):在生成的图里嵌入一个数字水印,事后能识别”这是模型生成的”。大多数图像生成方法(GAN、VAE、Stable Diffusion)都可以加上水印。
  • 假图检测(fake-image detection):没有水印也要识别假图。
  • 模型溯源(model attribution):识别一张图是哪个模型生成的(比如 DALL·E 2 还是 SDXL)。slides 说这一项非常成功——每个模型都留下了”天然的水印”。
  • 图像溯源(image attribution):找出是哪些训练图导致了这张生成图。极其困难。

5.4 社会影响

slides 列出的利与弊:

  • 利:给艺术家的新工具;更快地制作表情包。
  • 弊:侵犯版权、艺术家失去工作;社会整体创造力下降;可能生成贬低人格的内容;假新闻、虚假现实、事实核查更难;生成的内容”不扎根于现实”。

这些问题第 22 讲(“会出什么错”)会系统地讨论。


6. 概率图模型 · Probabilistic graphical models

为什么 GAN 这一讲要讲图模型?因为接下来的扩散模型和 VAE 都是隐变量模型,而描述”哪些变量依赖哪些变量”、“能不能高效采样 / 推断”最清楚的语言就是图。slides 介绍三种图:有向图、无向图、因子图。

6.1 有向图模型(贝叶斯网络)

定义(slides):有向图模型(directed graphical model,又叫贝叶斯网络 Bayesian network)是一个有向无环图,表示一组变量 X1,…,XTX_1, \ldots, X_T 之间的条件独立关系。每个节点是一个变量,每条边表示一对变量之间的”方向性影响”。它把联合分布分解成条件概率的乘积:

P(X1,…,XT)=∏t=1TP(Xt∣parents(Xt)).P(X_1, \ldots, X_T) = \prod_{t=1}^{T} P(X_t \mid \text{parents}(X_t)).

slides 的例子:X1→X2X_1 \to X_2;X2,X3→X4X_2, X_3 \to X_4;X3→X5X_3 \to X_5。所以

p(x1,…,x5)=p(x5∣x3) p(x4∣x2,x3) p(x3) p(x2∣x1) p(x1).p(x_1, \ldots, x_5) = p(x_5 \mid x_3)\, p(x_4 \mid x_2, x_3)\, p(x_3)\, p(x_2 \mid x_1)\, p(x_1).

一个有向图模型由两部分描述:

  • 定性描述(图本身):可以根据领域知识里的因果关系来定,可以从数据里学,也可以因为它有好的计算性质而选它。
  • 定量描述(条件概率):形式取决于变量的类型,通常从数据里学。离散变量用条件概率表(CPT);slides 给了每个变量取”红 / 蓝”时的全部数字,比如 p(x1=红)=0.4p(x_1 = \text{红}) = 0.4,p(x4=红∣x2=红,x3=蓝)=0.8p(x_4 = \text{红} \mid x_2 = \text{红}, x_3 = \text{蓝}) = 0.8。

06 的第 1 部分照抄了这些表:

  • 32 种组合的概率之和恰好是 1——每张表各自归一,乘起来自动归一。
  • 参数个数:完整的联合分布表要 25−1=312^5 - 1 = 31 个自由参数;按图分解只要 10 个(1 + 2 + 1 + 4 + 2)。nn 个二值变量、每个最多 kk 个父节点时,是 n⋅2kn \cdot 2^k 对 2n−12^n - 1:差别是指数级的。

6.2 祖先采样、观测变量与推断

祖先采样(ancestral sampling):按”父节点先于子节点”的顺序逐个采样,每一步只看父节点、查表、掷骰子。因为每一步都在从正确的条件分布里采,乘起来就是联合分布,所以采样是精确的。06 采 20 万次,32 种组合的经验频率和精确概率最大相差 0.0008。自回归语言模型的采样(第 3 讲)就是祖先采样。

观测变量:slides 用阴影表示”取值已知”的节点。看到了 X4=X_4 = 蓝,X1X_1 是什么?这需要推断(inference):对其他变量求和,再用贝叶斯公式。06:先验 p(x1=蓝)=0.600p(x_1 = \text{蓝}) = 0.600,精确推断得 p(x1=蓝∣x4=蓝)=0.6153p(x_1 = \text{蓝} \mid x_4 = \text{蓝}) = 0.6153;拒绝采样(祖先采样后只留下 x4=x_4 = 蓝的样本)得 0.6159。正向采样很容易,反过来推就要求和或者丢掉大量样本——变量一多,这就是指数级的问题。

图表示条件独立。X1X_1 和 X5X_5 之间唯一的路径是 X1→X2→X4←X3→X5X_1 \to X_2 \to X_4 \leftarrow X_3 \to X_5:

条件概率值
p(x5=红∣x1=红)p(x_5 = \text{红} \mid x_1 = \text{红})0.5800
p(x5=红∣x1=蓝)p(x_5 = \text{红} \mid x_1 = \text{蓝})0.5800
p(x5=红∣x1=红,x4=蓝)p(x_5 = \text{红} \mid x_1 = \text{红}, x_4 = \text{蓝})0.6005
p(x5=红∣x1=蓝,x4=蓝)p(x_5 = \text{红} \mid x_1 = \text{蓝}, x_4 = \text{蓝})0.5800
p(x5=红∣x1,x3=红)p(x_5 = \text{红} \mid x_1, x_3 = \text{红})0.7000(两种 x1x_1 相同)
  • 不观测 X4X_4 时,x1x_1 不影响 x5x_5:路径在对撞点 X4X_4(两个箭头都指向它)被阻断。
  • 观测了 X4X_4,x1x_1 就影响 x5x_5 了:知道了结果 X4X_4 和其中一个原因(经由 X2X_2),会改变对另一个原因 X3X_3 的判断,进而影响 X5X_5。这叫解释消除(explaining away)。(x1=x_1 = 蓝那一行恰好也是 0.5800,是 slides 数字的巧合:此时 p(x4=蓝∣x3)p(x_4 = \text{蓝} \mid x_3) 对 x3x_3 的两个取值都是 0.45,x4x_4 不带关于 x3x_3 的信息。图只告诉你”可能”相关。)
  • 再观测 X3X_3(X5X_5 唯一的父节点),x1x_1 又不影响 x5x_5 了:给定父节点,一个变量和它的非后代条件独立。

6.3 高斯有向图

变量连续时,可以用高斯条件分布。slides 的例子:

x1∼N(μ1,σ12), x2∼N(x1,σ22), x3∼N(μ3,σ32), x4∼N(x2+x3,σ42), x5∼N(x3,σ52).x_1 \sim \mathcal N(\mu_1, \sigma_1^2),\ x_2 \sim \mathcal N(x_1, \sigma_2^2),\ x_3 \sim \mathcal N(\mu_3, \sigma_3^2),\ x_4 \sim \mathcal N(x_2 + x_3, \sigma_4^2),\ x_5 \sim \mathcal N(x_3, \sigma_5^2).

每个变量是父节点的线性函数加高斯噪声,写成 x=Ax+c+Sεx = Ax + c + S\varepsilon,于是 x=(I−A)−1(c+Sε)x = (I - A)^{-1}(c + S\varepsilon)——一个线性变换作用在高斯噪声上,联合分布是高斯,协方差 (I−A)−1 diag(σ2) (I−A)−⊤(I-A)^{-1}\,\mathrm{diag}(\sigma^2)\,(I-A)^{-\top}。06 取 μ1=1\mu_1 = 1、μ3=−1\mu_3 = -1、σ=(1,0.5,1,0.5,0.5)\sigma = (1, 0.5, 1, 0.5, 0.5)(slides 没给数值),精确协方差和 20 万次祖先采样的协方差最大相差 0.0096。Cov(x1,x5)=0\mathrm{Cov}(x_1, x_5) = 0(没有连通路径),Cov(x1,x4)=σ12=1\mathrm{Cov}(x_1, x_4) = \sigma_1^2 = 1(x1x_1 的波动全部经过 x2x_2 传到 x4x_4)。

如果把 x5x_5 改成 N(x32,0.52)\mathcal N(x_3^2, 0.5^2)(父节点的非线性函数),它的超额峰度是 +6.4,不再是高斯(x4x_4 是 +0.013)。这正是第 7 讲 slides “高斯小结”的第 3、4 条:线性高斯一层层传下去仍是高斯,非线性就不是了。扩散模型的前向过程只用线性高斯,所以有闭式解;反向过程用神经网络,所以要学。

6.4 马尔可夫模型;把 RNN-LM 画成有向图

一阶马尔可夫假设:p(xt∣x1,…,xt−1)=p(xt∣xt−1)p(x_t \mid x_1, \ldots, x_{t-1}) = p(x_t \mid x_{t-1}),给定前一个变量,和更早的变量条件独立。一阶马尔可夫模型:p(x1,…,xT)=p(x1)∏t=2Tp(xt∣xt−1)p(x_1, \ldots, x_T) = p(x_1) \prod_{t=2}^T p(x_t \mid x_{t-1}),画成有向图就是一条链 x1→x2→⋯→xTx_1 \to x_2 \to \cdots \to x_T。第 1 讲的 bigram 就是它。

课堂练习:RNN-LM 的有向图是什么样的? RNN 语言模型在预测 xtx_t 时看了 x1,…,xt−1x_1, \ldots, x_{t-1} 全部(通过隐藏状态),所以每个 xtx_t 的父节点是它之前的所有词——一个完全图,没有任何条件独立假设。06 的第 3 部分算了参数(农场语言 V=56V = 56,长度 5):

模型参数个数条件独立假设
完整的联合分布表550,731,775无
一阶马尔可夫(bigram)3,135给定前一个词,和更早的词条件独立
完全图的条件概率表550,731,775无(就是链式法则)
RNN 语言模型(第 1 讲)11,640无;但所有位置共享同一组参数

完全图的条件概率表和完整联合分布表一样大——链式法则不省任何东西。马尔可夫假设省了参数,代价是能力(第 1 讲:bigram 困惑度 3.83,RNN-LM 2.540,真实下界 2.491)。RNN 走了第三条路:图还是完全图,但每个条件分布用同一个神经网络来参数化,而不是查表。这正是这门课所有深度生成模型的套路——图结构告诉你”谁依赖谁”,神经网络负责”怎样依赖”。

6.5 无向图

无向图模型(又叫马尔可夫随机场)用无向边表示变量之间的”相互影响”,没有方向。slides 只给了几个术语:团(clique,两两相连的节点集合)、极大团(再加任何一个节点就不再是团)、分隔(去掉一组节点后,两组节点之间没有路径)。slides 的原话是:”……这些很复杂,我们这里不太需要它们。”

6.6 因子图

因子图(factor graph)同时可以表示有向图和无向图。它是一个二部图:变量(圆)和因子(方块)。每个变量取一个值,所有变量的取值合起来叫一个赋值(assignment)。每个因子对它相邻的变量的取值有一个”局部的看法”,用势函数表(potential table)表示。

slides 的例子:两个变量 y1,y2y_1, y_2,取值是食物。一元因子 ψ1\psi_1 对 y1y_1 的偏好、ψ2\psi_2 对 y2y_2 的偏好、二元因子 ψ12\psi_{12} 对”配在一起”的偏好:

P~(tuna,ice cream)=ψ1(tuna)⋅ψ2(ice cream)⋅ψ12(tuna,ice cream)=6×7×0.1=4.2.\tilde P(\text{tuna}, \text{ice cream}) = \psi_1(\text{tuna}) \cdot \psi_2(\text{ice cream}) \cdot \psi_{12}(\text{tuna}, \text{ice cream}) = 6 \times 7 \times 0.1 = 4.2 .

“糟了!所有赋值的分数加起来是 Z>1Z > 1。那就都除以 ZZ。” 06 用 slides 显示出来的四种食物算出 Z=399.43Z = 399.43,所以 P(tuna,ice cream)=4.2/399.43=0.0105P(\text{tuna}, \text{ice cream}) = 4.2 / 399.43 = 0.0105;最可能的组合是(peanut butter, ice cream),概率 0.263。

ZZ 叫配分函数(partition function)。因子必须是非负的(这样除以 ZZ 之后才是合法的分布),所以也叫势函数。因子就是张量:一元因子是向量,二元因子是矩阵,三元因子是三阶张量……slides 用”time flies like an arrow”的词性标注展示了这一点:每个词一个一元因子(对 v/n/p/d 四种词性的偏好),相邻两个词之间一个二元的转移因子。

6.7 局部归一化 vs 全局归一化

  • 有向图是局部归一化的:每个因子都是归一化的条件概率,乘起来自动是分布,Z=1Z = 1,祖先采样很容易。
  • 因子图 / 无向图是全局归一化的:势函数只是”局部偏好”,要整体除以 ZZ。

ZZ 要把所有赋值加起来:nn 个变量、每个 kk 种取值就是 knk^n 项。28×28 的二值图像有 2784≈102362^{784} \approx 10^{236} 种。

6.8 推断的三个任务

slides 列出了图模型上的三个推断任务和它们在一般图上的难度:

  1. 边缘推断(marginal inference):算变量或团的边缘分布 p(xi)p(x_i)、p(xC)p(x_C)。#P 难。
  2. 配分函数:算 Z(θ)=∑x∏CψC(xC)Z(\theta) = \sum_x \prod_C \psi_C(x_C)。#P 难。
  3. MAP 推断:找概率最大的赋值 x^=arg⁡max⁡xp(x∣θ)\hat x = \arg\max_x p(x \mid \theta)。NP 难。

但图有好的结构时可以分解。06 在”time flies like an arrow”这条链上(转移势和”time”的一元势抄自 slides,其余四个词的一元势是自己编的)对比了暴力枚举(45=10244^5 = 1024 种标注)和动态规划:前向算法只用 n⋅k2n \cdot k^2 次运算就得到和暴力枚举完全相同的 ZZ(8,681,152.06),Viterbi 得到相同的 MAP 标注(v n v d n)。HMM 和 CRF 都是这样做的。

对生成模型的启示:能不能精确算出(或绕开)ZZ 和后验,决定了训练目标。自回归模型局部归一化,可以直接最大似然;GAN 干脆不要密度;VAE 和扩散模型用变分下界绕开难算的后验。这就是 §7 的内容。


7. 无监督学习与隐变量 · Unsupervised learning and latent variables

7.1 设定

slides 把这门课的”生成建模”统一成一个无监督学习问题:

  1. 数据来自某个分布 p∗(x0)p^*(x_0);
  2. 我们选一个分布 pθ(x0)p_\theta(x_0),从它采样是容易的;
  3. 目标:学 θ\theta 使得 pθ(x0)≈p∗(x0)p_\theta(x_0) \approx p^*(x_0)。

7.2 三种模型,三种回答

模型p∗p^* 是什么pθp_\theta 是什么怎样学
自回归语言模型人类在网上写文字的过程自回归 LM:p(xt∣x1,…,xt−1)p(x_t \mid x_1, \ldots, x_{t-1}),祖先采样精确高效θ≈arg⁡max⁡log⁡pθ(x0)\theta \approx \arg\max \log p_\theta(x_0),用 ∇θlog⁡pθ(x0)\nabla_\theta \log p_\theta(x_0) 做梯度更新
GAN发到 Flickr 上的照片的分布噪声喂进倒过来的 CNN:z∼N(0,I)z \sim \mathcal N(0, I),x0=fθ(z)x_0 = f_\theta(z),采样容易最大似然?**不行!**连 log⁡pθ(x0)\log p_\theta(x_0) 和它的梯度都算不了——改为优化极小极大损失
VAE / 扩散模型同上一个表达力强的模型,采样也容易最大似然?算是吧!梯度算不了,改为优化一个变分下界

为什么 GAN 连 log⁡pθ(x0)\log p_\theta(x_0) 都算不了? slides 的解释:“就连一层的神经网络也不行:在条件分布里,一张图 x0x_0 只对应噪声 zz 里的一个点,这让边缘分布 p(x0)p(x_0) 几乎处处为 0,而且很难求导。” 01 的第 4 部分把这句话变成了数字:生成器 x=wz+bx = wz + b(zz 一维、xx 二维)的样本全部落在一条直线上;为了能写出密度,给输出加一点噪声 σ\sigma,对八高斯圆环的 2000 个真实点算最优直线下的平均对数似然:

噪声 σ10.30.10.030.010.001
平均 log⁡p(x)\log p(x)−3.68−12.50−99.56−1,101−9,915−991,696
离直线不到 3σ 的点100%33.7%0000

σ\sigma 每缩小 10 倍,对数似然大约低 100 倍(离直线距离 dd 贡献 −d2/(2σ2)-d^2/(2\sigma^2)),σ→0\sigma \to 0 时趋于 −∞-\infty。真正的 GAN 生成器(没有输出噪声,而且 zz 的维数通常远小于图像的维数)正是 σ=0\sigma = 0 的情形。要算 p(x)p(x),只有在 zz 和 xx 维数相同、GG 可逆时才能用变量替换公式——那是另一类模型(normalizing flows)。GAN 选择了另一条路:不算 p(x)p(x),只要求能采样,用判别器比较两个分布。

7.3 隐变量模型

slides:“对 GAN 和 VAE,我们假设有一些(未知的)隐变量产生了我们的观测。向量 zz 就是这些隐变量。学好 GAN 或 VAE 之后,可以在隐空间里插值。”(§4.3)

用图模型的语言:隐变量模型就是一个两层的有向图 z→xz \to x,zz 不被观测。生成(祖先采样)是容易的:先采 zz,再采 x∣zx \mid z。难的是反过来——给定 xx,它的 zz 是什么(后验 p(z∣x)p(z \mid x))?以及边缘似然 p(x)=∫p(x∣z)p(z) dzp(x) = \int p(x \mid z) p(z)\, dz。§6.2 的”正向容易、反向要推断”在这里变成了”连续、高维、有神经网络”的版本,这就是变分推断要解决的问题(第 9 讲)。

7.4 预告:扩散模型和 VAE

slides 的预告:“虽然 VAE 出现得更早,我们先深入扩散模型,因为它会得到更多关注。“定义这两类模型的步骤大致是:

  1. 定义一个包含高斯噪声的概率分布;
  2. 用一个变分下界作为目标函数;
  3. 通过优化目标函数来学习分布的参数。

“那么,什么是变分下界?“扩散模型的标准讲法需要变分推断(第 9 讲才讲);slides 说第 7 讲会给一个不用变分推断的另一种讲法。


8. 小结 · Summary

  1. GAN 由两个确定性网络组成:生成器把噪声变成样本,判别器区分真假。训练是交替的小步 SGD,不是精确地解极小极大问题。
  2. 固定生成器,最优判别器 D∗=pdata/(pdata+pg)D^* = p_{\text{data}}/(p_{\text{data}} + p_g),目标变成 −log⁡4+2 JS-\log 4 + 2\,\mathrm{JS}。判别器是一个密度比估计器,生成器得到的信号是”哪里真图比假图多”。
  3. slides 的生成器目标在判别器很强时饱和;非饱和损失 −log⁡D(G(z))-\log D(G(z)) 是便宜的保险。JS 散度在分布不重叠时恒为 ln⁡2\ln 2,给不出方向(WGAN、加噪声是两条出路)。
  4. GAN 训练不稳定:模式崩塌、“追着跑”、对超参数和种子极其敏感。它的目标”宁可漏、不肯糊”,最大似然”宁可糊、不肯漏”。
  5. 生成模型的评估本身是难题。FID 式的 Fréchet 距离是标准做法,但每把尺子都会被某种东西骗过;在画得不标准的图上,两个”分类”尺子只有三成的时候意见一致。我们的 DCGAN 远看像形状、近看不准,十字明显偏少。
  6. 有向图模型把联合分布分解成局部条件概率,参数少、祖先采样精确;反向推断要求和。因子图要除以配分函数 ZZ,一般是 #P 难的;结构好的图可以用动态规划。
  7. 三类深度生成模型对”能不能做最大似然”给出了三种回答:自回归(能)、GAN(不能,改用博弈)、VAE / 扩散(用变分下界)。

9. 常见误区 · Common pitfalls

  • “判别器损失到 1.386 了,生成器就训练好了。” 它只说明这个判别器分不清了。03 的判别器损失在 1500 步后就在 1.386 附近,FD 却还在 34–57 之间跳。
  • “转置卷积就是反卷积。” 它是卷积矩阵的转置,不是逆。slides 特意强调”not deconvolution”。
  • “z 是随机的,所以 GAN 需要重参数化技巧。” 不需要:zz 的分布不依赖任何参数,它对 θ\theta 来说就是普通的输入。需要重参数化的是第 9 讲的 VAE。
  • “slides 的 log⁡(1−D(G(z)))\log(1 - D(G(z))) 一定会饱和。” 要看判别器有多强。02、03 里没有饱和,04 让判别器强很多才出现。但一旦出现就是恶性循环,所以默认用非饱和损失。
  • “模式崩塌是因为生成器容量不够。” 主要是优化的动力学问题。02 里同一个生成器,换学习率或种子,就从”只画 1 个”变成”8 个都画”。
  • “FD 越低,每张图越好。” FD 同时混合了质量和多样性,而且依赖特征网络。裁判对空白图也很自信;不加约束的形状拟合会把空白图当成”小形状”。要多把尺子一起用。
  • “用一个分类器数一数各类的比例,就知道缺了哪类。” 分类器在生成的(不标准的)图上并不可靠:我们的裁判和形状拟合只有三成的时候意见一致,“圆偏少”只是裁判一家之言。
  • “有向图的箭头就是因果。” 箭头表示分解方式和条件独立;它可以按因果关系画,也可以只为了计算方便。解释消除说明:不相关的两个变量,在观测了共同的结果之后会变得相关。
  • “势函数就是概率。” 势函数只要非负,要除以 ZZ 才是概率;slides 的例子 Z=399Z = 399。

10. 练习 · Exercises

练习 1(最优判别器)。 对固定的 a,b>0a, b > 0,求 f(y)=alog⁡y+blog⁡(1−y)f(y) = a\log y + b\log(1 - y) 在 (0,1)(0, 1) 上的最大值点,并由此写出 D∗D^*。

参考答案

f′(y)=a/y−b/(1−y)=0⇒y=a/(a+b)f'(y) = a/y - b/(1-y) = 0 \Rightarrow y = a/(a+b);f′′(y)=−a/y2−b/(1−y)2<0f''(y) = -a/y^2 - b/(1-y)^2 < 0,是最大值。逐点地取 a=pdata(x)a = p_{\text{data}}(x)、b=pg(x)b = p_g(x),得 D∗(x)=pdata(x)/(pdata(x)+pg(x))D^*(x) = p_{\text{data}}(x)/(p_{\text{data}}(x) + p_g(x))。在 pdata(x)=pg(x)=0p_{\text{data}}(x) = p_g(x) = 0 的地方,DD 取什么都不影响 VV。

练习 2(JS 散度)。 (a) 证明 V(D∗,G)=−log⁡4+2 JS(pdata∥pg)V(D^*, G) = -\log 4 + 2\,\mathrm{JS}(p_{\text{data}} \| p_g)。(b) 证明两个分布支撑集不相交时 JS=ln⁡2\mathrm{JS} = \ln 2。

参考答案

(a) 见 §3.2:log⁡D∗=log⁡pdata2m\log D^* = \log\frac{p_{\text{data}}}{2m},log⁡(1−D∗)=log⁡pg2m\log(1 - D^*) = \log\frac{p_g}{2m},拆出 −log⁡2-\log 2 两次得 −log⁡4-\log 4,剩下的是 KL(pdata∥m)+KL(pg∥m)=2 JS\mathrm{KL}(p_{\text{data}} \| m) + \mathrm{KL}(p_g \| m) = 2\,\mathrm{JS}。 (b) 在 pp 的支撑上 q=0q = 0,m=p/2m = p/2,KL(p∥m)=Ep[log⁡2]=ln⁡2\mathrm{KL}(p \| m) = \mathbb E_p[\log 2] = \ln 2;同理 KL(q∥m)=ln⁡2\mathrm{KL}(q \| m) = \ln 2;JS=12(ln⁡2+ln⁡2)=ln⁡2\mathrm{JS} = \tfrac12(\ln 2 + \ln 2) = \ln 2。和两个分布离多远无关(01 第 3 部分:μ≥1\mu \ge 1 时都是 0.6931)。

练习 3(饱和)。 判别器对一个假样本的输出 D(G(z))=0.01D(G(z)) = 0.01。分别求两种生成器损失对判别器 logit 的梯度。如果要把极小极大版本的梯度大小提高到非饱和版本的水平,D(G(z))D(G(z)) 至少要是多少?

参考答案

极小极大:−D=−0.01-D = -0.01;非饱和:−(1−D)=−0.99-(1-D) = -0.99,相差 99 倍。两者大小相等当且仅当 D=1−DD = 1 - D,即 D(G(z))=0.5D(G(z)) = 0.5;D>0.5D > 0.5 之后反而是极小极大版本的梯度更大(表中 D=0.9D = 0.9 那一行)。

练习 4(转置卷积的尺寸)。 (a) ConvTranspose2d(核 4, 步长 2, 填充 1) 作用在 14×14 上,输出多大?(b) 核 3、步长 2、填充 1 的转置卷积作用在 7×7 上,输出 13×13;想得到 14×14,PyTorch 的 output_padding 应该取多少?

参考答案

(a) (14−1)×2−2+4=28(14 - 1)\times 2 - 2 + 4 = 28,正是生成器的最后一层。(b) (7−1)×2−2+3=13(7-1)\times 2 - 2 + 3 = 13;output_padding = 1 在一侧多补一行一列,得 14。(步长大于 1 的普通卷积会把 13 和 14 都映射到 7,所以”反过来”时需要这个参数来消除歧义。)

练习 5(有向图的参数)。 (a) 对 slides 的五变量图,验证按图分解需要 10 个自由参数。(b) nn 个二值变量、每个最多 kk 个父节点,按图分解最多要多少个参数?n=30n = 30、k=3k = 3 时和完整联合表比一比。

参考答案

(a) p(x1)p(x_1):1;p(x2∣x1)p(x_2 \mid x_1):2(父节点每种取值 1 个);p(x3)p(x_3):1;p(x4∣x2,x3)p(x_4 \mid x_2, x_3):4;p(x5∣x3)p(x_5 \mid x_3):2。合计 10。 (b) 每个变量最多 2k2^k 个,共 n⋅2kn \cdot 2^k。n=30n = 30、k=3k = 3:240 个,而完整联合表要 230−1≈10.72^{30} - 1 \approx 10.7 亿个。

练习 6(祖先采样的顺序)。 slides 的五变量图有多少种合法的祖先采样顺序(拓扑序)?

参考答案

约束:X1X_1 在 X2X_2 前,X2X_2、X3X_3 在 X4X_4 前,X3X_3 在 X5X_5 前。若 X5X_5 在 X4X_4 之后:前三个是 {X1,X2,X3}\{X_1, X_2, X_3\} 且 X1X_1 在 X2X_2 前,3 种,接着 X4X_4、X5X_5。若 X5X_5 在 X4X_4 之前:前四个是两条链 X1→X2X_1 \to X_2 和 X3→X5X_3 \to X_5 的交错,(42)=6\binom{4}{2} = 6 种,最后 X4X_4。共 9 种(用代码枚举 120 个排列验证过)。任何一种都给出精确的样本。

练习 7(因子图)。 用 §6.6 的数字:(a) 不算 ZZ,P(tuna,ice cream)P(\text{tuna}, \text{ice cream}) 和 P(tuna,tuna)P(\text{tuna}, \text{tuna}) 哪个大?大多少倍?(b) 为什么有向图模型不需要算 ZZ?

参考答案

(a) P~(tuna,tuna)=ψ1(tuna) ψ2(tuna) ψ12(tuna,tuna)=6×3×2=36\tilde P(\text{tuna}, \text{tuna}) = \psi_1(\text{tuna})\,\psi_2(\text{tuna})\,\psi_{12}(\text{tuna}, \text{tuna}) = 6 \times 3 \times 2 = 36,是 P~(tuna,ice cream)=4.2\tilde P(\text{tuna}, \text{ice cream}) = 4.2 的约 8.6 倍。比较两个赋值的相对大小不需要 ZZ(它在比值里约掉了)——MAP 推断也不需要 ZZ,但要比较所有赋值。 (b) 有向图的每个因子都是归一化的条件分布 ∑xtp(xt∣parents)=1\sum_{x_t} p(x_t \mid \text{parents}) = 1,从叶子往根逐个求和,每一步都得 1,所以 Z=1Z = 1。

练习 8(一维的 Fréchet 距离)。 证明一维时 FD(N(μ1,σ12),N(μ2,σ22))=(μ1−μ2)2+(σ1−σ2)2\mathrm{FD}(\mathcal N(\mu_1, \sigma_1^2), \mathcal N(\mu_2, \sigma_2^2)) = (\mu_1 - \mu_2)^2 + (\sigma_1 - \sigma_2)^2。一个模型只会画”平均的那张图”(σ2=0\sigma_2 = 0,μ2=μ1\mu_2 = \mu_1),FD 是多少?

参考答案

一维时矩阵平方根就是数的平方根:Tr(…)=σ12+σ22−2σ1σ22σ1=σ12+σ22−2σ1σ2=(σ1−σ2)2\mathrm{Tr}(\ldots) = \sigma_1^2 + \sigma_2^2 - 2\sqrt{\sigma_1\sigma_2^2\sigma_1} = \sigma_1^2 + \sigma_2^2 - 2\sigma_1\sigma_2 = (\sigma_1 - \sigma_2)^2。只画平均图:FD=σ12\mathrm{FD} = \sigma_1^2,即真实特征的方差——均值完全对,多样性完全没有,FD 仍然很大。这就是为什么 FD 能惩罚模式崩塌(shape_metrics 测试里”只画正中间的圆”FD 454)。

练习 9(宁可漏还是宁可糊)。 真实分布是 ½N(−2, 0.5²) + ½N(2, 0.5²),模型只能是一个高斯。(a) 最大似然会选什么?(b) 一个”理想的”GAN(假设它最小化反向 KL)倾向于选什么?前置讲 P2 的 03 号脚本算过这两个数。

参考答案

(a) 最大似然 = 最小化前向 KL = 矩匹配:均值 0,标准差 4+0.25≈2.06\sqrt{4 + 0.25} \approx 2.06——横跨两个峰,在山谷里放了大量概率。(b) 反向 KL 寻模:均值 ±2、标准差 0.5,只盯住一个峰(KL = ln 2)。GAN 的 JS 目标介于两者之间,但实践中的表现更接近 (b):样本清晰、漏掉模式。

练习 10(为什么 GAN 不能做最大似然)。 生成器 G:R32→R784G: \mathbb R^{32} \to \mathbb R^{784}(我们的 DCGAN)。说明 pgp_g 在 R784\mathbb R^{784} 上没有密度。如果非要给 GAN 算一个似然,01 第 4 部分的做法是什么?它有什么问题?

参考答案

GG 的像是 R784\mathbb R^{784} 里一个至多 32 维的”曲面”,勒贝格测度为 0,概率全部集中在上面,所以没有(对勒贝格测度的)密度;任何不在曲面上的真实图像似然都是 0。01 的做法是给输出加高斯噪声 σ\sigma,得到一个处处有密度的模型。问题是结果完全由人为选的 σ\sigma 决定:σ\sigma 越小似然越低,趋于 −∞-\infty;σ\sigma 大了又等于在评价一个”糊掉的”模型。原始 GAN 论文用的 Parzen 窗估计(在样本上放小高斯)有同样的问题。

11. 延伸阅读 · Further reading

  • GAN 原文与教程:Goodfellow et al. (2014), Generative Adversarial Nets;Goodfellow (2016), NIPS 2016 Tutorial: Generative Adversarial Networks(饱和、模式崩塌、各种技巧的权威讲解)。
  • 架构:Radford, Metz & Chintala (2016), DCGAN;Isola et al. (2017), pix2pix(PatchGAN);Karras et al. (2019), StyleGAN;Brock, Donahue & Simonyan (2019), BigGAN;Kang et al. (2023), GigaGAN。
  • 训练的稳定性:Arjovsky & Bottou (2017), Towards Principled Methods for Training GANs;Arjovsky, Chintala & Bottou (2017), Wasserstein GAN;Gulrajani et al. (2017), WGAN-GP;Miyato et al. (2018), Spectral Normalization;Metz et al. (2017), Unrolled GANs(八高斯圆环实验的出处)。
  • 条件生成:Mirza & Osindero (2014), Conditional GAN;Odena, Olah & Shlens (2017), AC-GAN;Miyato & Koyama (2018), cGANs with Projection Discriminator。
  • 评估:Heusel et al. (2017)(FID);Theis, van den Oord & Bethge (2016), A note on the evaluation of generative models;Carlini et al. (2023), Extracting Training Data from Diffusion Models(记忆)。
  • 理论视角:Nowozin, Cseke & Tomioka (2016), f-GAN;Mohamed & Lakshminarayanan (2016), Learning in Implicit Generative Models(判别器 = 密度比估计)。
  • 概率图模型:Koller & Friedman, Probabilistic Graphical Models;Bishop, Pattern Recognition and Machine Learning 第 8 章;Murphy, Probabilistic Machine Learning: Advanced Topics 第 4 章。

12. 下一讲预告 · Next lecture

GAN 绕开了似然,代价是训练不稳定、会漏模式。第 7 讲换一条路:扩散模型。

  • 前向过程:一步步往图像上加一点高斯噪声,直到变成纯噪声——全是线性高斯(§6.3),任意一步都有闭式解;
  • 反向过程:学一个神经网络,一步步把噪声去掉;每一步只是一个小小的高斯,合起来却能表示复杂的分布;
  • 训练目标简单得出奇:预测加进去的噪声。

我们会先在二维的”瑞士卷”和八高斯圆环上从零训练扩散模型,看它是否也会模式崩塌(§3.6),再介绍去噪网络 U-Net。

← 返回课程目录