上一讲第 12 讲:自监督学习 下一讲第 14 讲:生成模型(二)

第 13 讲:生成模型(一):自回归模型与变分自编码器

Generative Models I —— 先补完上一讲遗留的对比学习方法(SimCLR 的大 batch 困境、MoCo 的动量编码器与负样本队列、DINO 与规模化到 1.42 亿图像的 DINOv2);随后正式进入生成模型:用"概率质量竞争"的视角厘清监督/无监督与判别/生成两条正交的轴,理解 \(p(y|x)\)、\(p(x)\)、\(p(x|y)\) 三类模型及联系它们的贝叶斯公式;学习生成模型分类树(显式/隐式密度 × 直接/间接采样)与贯穿始终的最大似然估计(MLE);最后按"自回归模型 → 自编码器 → 变分自编码器"的顺序走完显式密度分支,其中 VAE 的证据下界(ELBO)推导、重参数化技巧与"两个损失的博弈"是本讲的重头戏。生成对抗网络与扩散模型留给下一讲

本讲概览:

本讲分两大块。第一块是上一讲的收尾:老师先快速回顾自监督学习"代理任务 + 编码器 + 下游迁移"的框架与对比学习"拉近正样本、推远负样本"的思想,然后补讲三个因上一讲时间不够而没讲完的方法——SimCLR(需要超大 batch 才能收敛,因为任务对网络来说太简单)、MoCo(用历史批次组成的负样本队列 + 不做反向传播、按指数滑动平均更新的动量编码器,把负样本数量与 batch 大小解耦)和 DINO / DINOv2(同样使用动量编码器,但损失换成 KL 散度;DINOv2 把训练数据从 ImageNet 的 100 万张扩到约 1.42 亿张,成为当今常用的自监督特征模型)。第二块是本讲正题"生成模型":老师强调这是十年间"从完全不能用变成真的能用"的领域,但数学基础十年未变,变的是算力、稳定训练配方、数据规模与分布式训练。接着从"概率分布是归一化的、所有取值在竞争固定的概率质量"这一核心观察出发,讲清判别模型 \(p(y|x)\)、(无条件)生成模型 \(p(x)\)、条件生成模型 \(p(x|y)\) 三者的本质区别(判别模型无法拒绝离谱输入;生成模型要回答"三条腿的狗和三只胳膊的猴子谁更可能"这种深刻问题),并用贝叶斯公式说明三者可以互相换算。随后给出"显式密度(精确:自回归;近似:VAE)vs 隐式密度(直接:GAN;间接:扩散)"的对称分类树,讲最大似然估计与对数技巧,把自回归模型套到"图像 = 三百万个 0–255 整数的一维序列"上并分析其代价,回顾自编码器的瓶颈思想及其"采样难题被踢皮球"的困境,最后用大篇幅推导 VAE:边际化积分不可解、后验不可解 → 引入编码器 \(q(z|x)\) 近似后验 → 网络输出对角高斯的参数(固定方差时最大似然等价于 L2)→ 逐步推出 ELBO = 重建项 − \(\mathrm{KL}(q(z|x) \,\|\, p(z))\) → 重参数化技巧让采样可回传 → 重建项与先验项"打架"达成平衡 → 训练后从先验采样解码生成,且潜空间各维近似独立、可插值(MNIST 数字平滑变形)

一、开场补讲:上一讲自监督学习的收尾

老师开场说:欢迎回到 CS231N 第 13 讲,今天的主题是生成模型(Generative Models)。但在此之前,要先花几分钟补完上一讲因时间不足没讲完的几个自监督学习方法。

快速回顾:自监督学习(Self-Supervised Learning)的典型设定是手里有一大堆没有标签的图像,把它们喂给一个编码器(encoder)提取特征表示,再经过某个解码器(decoder)从特征预测一些东西;全部技巧在于设计一个代理任务(pretext task),让整套系统无需任何人工标注就能训练。上讲举过的例子——旋转预测(把图旋转、让模型猜转了多少度)、重排/拼图(把图像切块打乱、预测原始相对排列)、重建/补全(删掉一部分像素、让模型补回来)——本质上都是对输入像素做几何扰动,再要求模型从扰动中恢复。

训练流程通常是两阶段:先在能找到的所有数据(百万、上亿甚至十亿样本)上用代理任务训练编码器-解码器;然后扔掉解码器,在编码器后面接一个新的(可能很小的)全连接网络,在小规模有标注任务上端到端微调、或只训练这个头部。理想场景:在十亿张互联网无标注图像上预训练,迁移到我们愿意人工标注几十、几百、几千张的具体任务上。

1.1 对比学习回顾与 SimCLR 的大 batch 困境

上一讲讲过另一类自监督方法——对比学习(contrastive learning):构造相似对与不相似对,把相似对在特征空间拉近、不相似对推远。具体做法:对每张无标签输入图像施加两次随机变换(课上的例子:猫的一张裁剪在猫脸附近、另一张裁剪在猫身子后段;猴子的一张裁在脸部、另一张还转成了黑白),把所有增强版本喂给同一个特征提取器(ViT、CNN 均可),然后计算一个巨大的相似度矩阵——n 张图、每张两个增强,共 2n 个样本,因此矩阵是 \(2n \times 2n\)(共 \(4n^2\) 个标量相似度)。训练目标:来自同一张原始图的两个增强互相拉近,来自不同原始图的增强对互相推远。把这一切整合起来的代表作就是 SimCLR

但 SimCLR 有个问题:它需要相当大的 batch size 才能良好收敛。原因是对网络来说这个任务"太容易"了——如果负样本不够多,从一堆图里挑出那两张相似的猫图轻而易举,学习信号不足。要让任务足够难、给网络足够强的梯度信号,就需要巨大的 batch,于是又要把前几讲讲过的大规模分布式训练那一套全部搬出来。这固然可行、也确实有效,但自然会问:有没有办法不用超大 batch?

1.2 MoCo:负样本队列 + 动量编码器

MoCo(Momentum Contrast,动量对比)的设定与 SimCLR 几乎一样:数据、增强对、特征编码器、拉近相似/推远不相似。区别在于它想让每次迭代不必背负超大 batch。做法是维护一个来自以往训练迭代的样本队列(queue):当前迭代里,新批次作为查询(query)\(x\) 走正常的编码器网络,与 SimCLR 完全相同地计算对比损失;而队列里那些历史批次(\(x_0, x_1, x_2, \ldots\),称为键 key)则走另一个不同的网络——动量编码器(momentum encoder)——同样得到特征、同样参与相似度计算。

机制

动量编码器为什么不回传、怎么更新?队列里累积的样本量太大,无法在 GPU 显存里对它们做反向传播,所以动量编码器根本不通过梯度下降更新。它有自己独立的一套权重,更新规则是普通编码器权重的指数滑动平均(exponential moving average):普通编码器一切照旧——前向、反向、梯度更新;每步更新完之后,把动量编码器的当前权重衰减 0.99,再混入 1% 的普通编码器权重

$$ \theta_{\mathrm{momentum}} \leftarrow 0.99 \cdot \theta_{\mathrm{momentum}} + 0.01 \cdot \theta_{\mathrm{encoder}} $$

也就是说,动量编码器是一个"滞后跟随"的编码器。老师坦诚地说:他自己也没有很好的直觉能解释这为什么恰好有效,但经验证据非常强——它确实有效。带来的好处很实际:每次迭代不再需要巨量负样本,照样能学好自监督表示。这条路线后续还有一批跟进论文。

1.3 DINO 与 DINOv2:换掉损失,然后规模化

另一个应当知道的方法是 DINO。整体思路与 MoCo 很像:同样是"一个用梯度下降训练的普通编码器 + 一个动量更新的编码器"的双网络结构,但损失不同——不用 softmax 式的对比损失,而是某种 KL 散度(KL divergence)损失。老师在这里提到 DINO 的目的,是让大家知道 DINOv2 的存在:DINOv2 把 DINO v1 的配方(结构上类似 MoCo、吸收了 SimCLR 的不少想法、也有自己独有的细节)中训练数据的规模大幅扩大——以前多数自监督方法在 ImageNet(约 100 万张图)上训练,DINOv2 成功扩到约 1.42 亿张图像,得到了非常强的自监督特征。用老师的话说:深度学习喜欢更大的网络、更大的数据、更多的 GPU、更多的 flops——DINOv2 就是找到了一个能成功规模化的自监督配方。如今想拿现成特征做微调或下游任务时,DINOv2 是实践中用得很多的选择。老师不要求掌握细节,只要求知道它存在、做项目时能用上。

补讲到此结束,进入本讲正题。

二、生成模型导论:十年之间,从"模糊垃圾"到真的能用

老师形容生成模型是深度学习里变化最戏剧性的领域之一:十年前完全不能工作——他读研时看这些模型的采样结果,只能眯着眼睛从"低分辨率的、完全模糊的垃圾"里勉强看出一点希望——而最近几年真的能用了:语言模型(本身就可以看作生成模型)、图像生成模型、视频生成模型。他很庆幸当时有人坚持穿过"模糊垃圾"阶段把这条路做了下去。这门课第一次开课时这个领域还完全不行,现在却成了最热门的方向。

但老师同时强调:生成建模的很多基本数学思想十年间其实没有变——如何思考数据、有哪些建模途径,这些数学基础基本未动;真正变化的是更多算力、更稳定的训练配方、更大的数据集、分布式训练,以及把它们规模化到有用任务上的能力。算法层面当然也有改进,尤其是下一讲的扩散模型——但本讲先打地基。

三、监督学习 vs 无监督学习:任务世界的第一条轴

在讲生成建模之前,老师退一步梳理术语,因为深度学习的任务可以沿几条正交的轴(orthogonal axes)切分。

监督学习(supervised learning)是本学期大部分时间在做的事:有数据对 \((x, y)\) 的集合,目标是学一个从输入 \(x\) 到目标/标签 \(y\) 的映射。例子都见过:图像分类(\(x\) 是图像,\(y\) 是类别标签)、图像描述/看图说话(\(y\) 是描述图像的一段文字)、目标检测(\(y\) 是框 + 类别标签的集合)、语义分割(给每个像素一个标签)。它们都是监督问题,因为你要预测的东西恰好就是数据集里有的,只需在训练集上模仿这个 \(x \to y\) 映射、再泛化到训练集之外的新样本。

无监督学习(unsupervised learning)则"更玄、更神秘、更难描述":没有任何标签,只有样本 \(x\)(只有图像),想从数据中学出某种结构。它不一定针对某个具体任务,往往任务本身就是模糊的——目的常是为了以后迁移到下游任务。经典例子:

这些都是要从数据本身中发掘的隐藏/潜在结构。老师提醒:可以把"监督 ↔ 无监督"看作一条谱(spectrum),系统在其中各占一点;无监督方法不一定是概率化或生成式的(聚类和 PCA 虽常有概率解释,但不必那样理解)。而另一条独立的谱,才是本讲的主角。

四、判别模型 vs 生成模型:概率质量的竞争

第二条谱是判别模型(discriminative model)vs 生成模型(generative model)。这一对概念天然是概率性的:谈它们时,我们总是在想象数据背后有某种概率结构要学。区别仅在于:变量之间的概率关系到底是哪一种

约定:\(x\) 通常是高维的大东西(对课程而言是图像),\(y\) 是标签、描述或辅助信息(类别标签、一段文字说明等)。

4.1 核心事实:概率分布是归一化的

要真正理解概率层面发生了什么,必须记住概率分布(密度函数 \(p(x)\))最重要的性质——归一化(normalization):\(p(x)\) 给每个可能的输入 \(x\) 赋一个非负数值,且对全空间积分恒等于 1:

$$ \int p(x)\, dx = 1 $$

这个约束正是概率模型的威力来源:总概率质量(probability mass)只有固定的一个单位,选定一个分布就等于把这份固定的质量摊分到所有可能的 \(x\) 上。所有 \(x\) 在互相竞争:想让某个 \(x\) 的概率升高,必然要有别的 \(x\) 的概率降低。因此,不同建模框架真正的区别是——哪些变量在竞争概率质量。哪怕纸面上的符号长得几乎一样,"谁和谁竞争"不同,模型要学的结构就完全不同。

4.2 判别模型 p(y|x):标签在竞争,图像不竞争

判别模型学的是条件分布 \(p(y|x)\):对每一个 \(x\),输出一个在全部可能标签上的分布。若标签是离散类别(猫/狗),那就是对每个输入图像都有一个 0 到 1 之间、猫 + 狗 = 1 的分布。关键观察:图像之间没有竞争——每张图像各自诱导出自己的标签分布,彼此互不抢夺质量;竞争只发生在同一张图内部的各个标签之间

判别模型还有一个有趣的局限:无法拒绝离谱的输入。一旦标签空间固定为"猫/狗",喂进来一只猴子、或者一幅抽象画,系统毫无灵活性,被迫在预先固定的词表上输出一个分布——它没有说"这不合理"的通道。这不一定是缺点,但理解判别建模时必须知道底层发生了什么。

4.3 生成模型 p(x):宇宙中所有图像在竞争

生成模型学的则是分布 \(p(x)\) 本身:所有可能存在的图像统统在互相竞争概率质量。这件事一下子变得非常深刻,逼你回答一些近乎哲学的问题。老师的例子:一张"三条腿的狗"的图像,和一张"三只胳膊的猴子"的图像,谁该分到更多概率质量?大概前者——狗丢一条腿是现实中会发生的事,而猴子长第三只胳膊就罕见得多了(除非你专门建模科幻图像)。一旦进入"所有图像互相竞争"的世界,模型就必须认真思考数据中可能存在的结构,问题难度骤增。

反过来,生成模型获得了判别模型没有的能力:拒绝不合理的输入——它可以把很低甚至零的概率质量分给某张图。比如一个"动物园动物"生成模型,喂进一幅抽象画,其概率应为 0:这就有了判定"此类图像不在我们关心范围内"的机制。

4.4 条件生成模型 p(x|y):每个标签下都有一场全体图像的竞争

条件生成模型(conditional generative model)学 \(p(x|y)\):在给定标签/信号 \(y\) 下图像的条件分布。此时对每一个可能的 \(y\),都单独进行一场"全体图像"的概率质量竞争。\(y\) = "猫"时:猫图的概率最高,猴子和狗图作为哺乳动物也许略高一点,抽象画几乎为 0;\(y\) = "狗"时又是另一套分布。更有趣的是,\(y\) 完全可以比单个类别标签丰富得多——一段文字描述、一整段话、甚至"另一张图 + 一段文字"。要在如此丰富的输出空间 \(x\) 与条件空间 \(y\) 之间建模,实际上是在要求模型对涉及的对象做非常深层的推理,去解决一个复杂且相当"定义不清"的问题。

老师对生成模型为何有趣的原话大意:看起来简单——"我们只是把 \(x\) 和 \(y\) 对调了一下,能有多难?"——结果突然之间,模型必须认真思考视觉世界的运行规律。实践中真正大量训练和使用的几乎总是条件生成模型:写下一句"我想要一张'猫穿着热狗味 T 恤在月球上'的图",生成模型就能据此造出一张全新的 \(x\)。文献里"生成模型"这个词常把无条件与条件混为一谈,甚至为了公式整洁干脆把条件 \(y\) 省略不写——读论文时请始终在脑内补上"以 \(y\) 为条件"(老师特意在本讲分类树幻灯片上故意省略 \(y\),就等同学发问,以此训练大家的警惕性)。

4.5 贝叶斯公式:三类模型的互相换算

判别、生成、条件生成看似三种东西,其实由贝叶斯公式(Bayes' rule)——"概率论中最美妙的关系之一"——串在一起:

$$ p(x|y) \cdot p(y) = p(y|x) \cdot p(x) $$

只要拿到任意两个(例如判别模型 \(p(y|x)\) + 无条件生成模型 \(p(x)\) + 标签先验 \(p(y)\)),就能组合出第三个(条件生成模型 \(p(x|y)\))。理论上完全行得通;但实践中人们一般从头单独训练条件生成模型,不做这种组合。不过——老师预告——在扩散模型里,有时确实会因为某些原因把条件模型和无条件模型放在一起联合学习(这是给下一讲埋的伏笔,即后来的无分类器引导思想)。

4.6 三类模型各自的用处

五、为什么要生成模型:凡是输出有歧义的地方

什么时候需要生成模型?当任务输出存在歧义(ambiguity)时。\(p(x|y)\) 的美妙之处在于它是概率性的:在给定输入 \(y\) 的条件下,合法的输出 \(x\) 有一整个空间。有些任务是确定性映射——"数数图里有几只猫"只有一个答案;但更多任务是微妙的多解问题——"画一只戴热狗帽子的狗"有无数种合理的画法,输出带有不确定性。生成模型要建模的正是给定输入下整个输出分布。老师给了三个近年的例子:

老师还提醒:生成建模是深度学习中数学味最重的子领域之一——要想清楚"有哪些办法对概率分布建模""怎样写出能让正确事情发生的损失函数",所以读论文时会遇到大量公式,有时确实需要逐行推敲。

六、生成模型分类树:显式密度 vs 隐式密度

接下来是本讲的组织地图——生成模型的分类树(taxonomy),老师对它的对称性颇为自豪:两个分支、四个叶子,本讲盖一半、下一讲盖另一半。

为什么有人愿意放弃密度值?因为很多时候你只关心采样及其多样性,根本不需要知道某个具体输入的密度是多少;反之显式方法的采样有时反而更麻烦(不绝对)。

答疑

问 1:能否把间接采样当黑盒,从而把"间接"方法当"直接"方法用?原则上可以,实践上不行——得到的样本是近似的,具体近似程度取决于方法。以扩散模型为例,要抽出严格意义上的真样本需要无穷多步迭代,实际只能用有限步逼近;早年 MCMC/马尔可夫链方法同理(严格样本需无穷步收敛)。间接方法的"直接化"永远伴随有限步近似。

问 2:近似密度与隐式采样有什么区别?近似密度方法仍然能算出一个数——那是对真 \(p(x)\) 的近似或下界;而隐式(间接)方法里到处都找不到密度值,完全无法计算,只能迭代地采样。

七、最大似然估计:贯穿生成模型的通用原则

在进入第一个具体模型之前,老师先讲一个所有生成建模背后最通用的思想——最大似然估计(Maximum Likelihood Estimation, MLE):给定有限样本,如何拟合概率模型。

思路:既然有的方法要显式建模密度,那就用神经网络来做——写一个网络,输入数据 \(x\) 与权重 \(W\),输出一个数作为密度值 \(p(x; W)\)。给定数据集 \(x^1, x^2, \ldots, x^N\)(注意:上标表示不同的独立样本,后文自回归里的下标将表示同一样本的不同部分,老师特意提醒别混淆),训练目标是:找一组权重,使这个数据集出现的概率最大——权重变了,网络建模的密度就变了,我们要挑那个让数据"最像从它里面采出来"的密度:

$$ W^* = \operatorname*{arg\,max}_{W} \prod_{i=1}^{N} p(x^i; W) \qquad \Longrightarrow \qquad W^* = \operatorname*{arg\,max}_{W} \sum_{i=1}^{N} \log p(x^i; W) $$

推导中两步标准操作:其一,假设数据独立同分布(IID)——每个 \(x\) 都是从那个真实分布采出来的,于是联合概率分解为各样本概率的乘积;其二,对数技巧(log trick)——log 是单调函数,最大化似然等价于最大化对数似然,而 log 恰好把乘积变成求和,求和更好处理(实践里为了数值稳定几乎总在 log 空间计算,网络直接输出 log 概率)。把网络代进去,就得到了一个可以直接训练的损失函数。

似然(likelihood)与概率(probability)的区别在于"谁在变"。谈概率时:分布固定,滑动 \(x\),看不同 \(x\) 在同一分布下的概率;谈似然时:样本 \(x\) 固定,变动分布本身,看这批固定样本的密度如何随分布变化。MLE 做的正是后者:固定训练样本,在神经网络能表达的分布族里挑使样本似然最大的那个。这背后还有一个隐含假设:宇宙存在一个我们永远无法直接访问的真实数据分布 \(p_{\text{data}}\),它生成了我们看到的一切样本;学习就是从有限样本中把这个未知分布"挖"出来。

不过 MLE 本身太一般化——不依赖数据的任何结构,要取得实际进展,还需要给数据加结构假设。第一个这样的假设,引出下一节。

八、自回归模型:链式法则 + 把数据拆成序列

8.1 概率链式法则:无假设的精确分解

自回归模型(autoregressive model)的假设是:数据 \(x\) 存在某种规范的拆法,能切成子部分的序列 \(x_1, x_2, \ldots, x_T\)(下标 = 同一个样本内部的部件)。在此假设下,对联合分布使用概率链式法则(chain rule of probability)——它对任何联合分布恒成立、不需要任何额外假设:

$$ p(x) = p(x_1) \cdot p(x_2 \mid x_1) \cdot p(x_3 \mid x_1, x_2) \cdots p(x_T \mid x_1, \ldots, x_{T-1}) = \prod_{t=1}^{T} p(x_t \mid x_1, \ldots, x_{t-1}) $$

于是训练目标变为:训练一个网络,输入序列的前缀,输出下一部分的概率分布。老师问全班"这像什么"——RNN:隐状态沿时间传递,天然只依赖序列前缀,从每个隐状态预测下一元素的条件分布,正是以前讲过的 RNN 语言模型;还有掩码 Transformer(masked transformer):把注意力矩阵按上三角遮住,使每个输出只依赖于前缀——如今自回归建模最常用的就是它。

8.2 为什么必须分解?——\(V^T\) 的爆炸

有同学问"为什么要把数据拆成序列"?老师的回答:分解让问题变小。以语言建模为例,词表大小为 \(V\):直接建模两个词的联合分布需要 \(V^2\) 个表项,三个词 \(V^3\),\(T\) 个词 \(V^T\)——随序列长度指数增长,长序列下完全不可处理。链式法则把它化整为零:每次只在给定前缀的条件下预测一个元素,规模可控。

8.3 语言天然适配,图像要"硬凑"

这套范式与文本是天作之合:文本天然是一维序列,而且天然离散——对离散取值建模概率是我们整学期的拿手好戏(softmax + 交叉熵,网络给每个类别打分、归一化、训练)。中间虽有个分词器(tokenizer)的模糊地带,但"一维 + 离散"两点让语言与自回归模型严丝合缝。

图像则两头都不沾:既不天然一维,也不天然离散(我们通常把图像看作连续实值对象)。但老师引用了一句俗话:"手里有锤子,见钉子就敲。"几年前人们确实朴素地把自回归模型直接套到图像上:把图像当作像素序列。关键观察是:每个像素就是三个数,而常用存储格式(JPEG、PNG)里每通道 8 比特——所以一个像素就是三个 0 到 255 的整数!把图像按光栅顺序拉成一维序列、序列每个元素是一个子像素值,图像就变成了"一维 + 离散"序列,可以像语言模型一样用 RNN 或 Transformer 做自回归建模。

算账

代价有多惨?一张不算特别高分辨率的 1024 × 1024 图像,就对应三百万个元素的序列(1024 × 1024 × 3)。如今模型确实能处理百万级序列,但极其昂贵、难以扩展到高分辨率——所以那几篇直接在像素上做自回归的论文并不算成功。老师剧透:这一思路最近两年复活了,诀窍在于不再把单个像素值当序列元素,而是先用别的流程/模型(神经网络)把图像切成一系列一维 token 再做自回归——细节留到下一讲。

问:能从自回归模型里恢复出精确密度吗?能。Transformer 在序列每个位置都输出"下一个 token 的条件分布";把真实下一个 token 的预测概率沿整个序列连乘(实践中是对 log 概率求和),就得到这张图/这段文本的精确似然值。RNN 版同理。这就是分类树里"精确显式密度"一叶的含义。

拓展

像素自回归的家谱:PixelRNN / PixelCNN 与"图像 token 化"的新生。字幕里"把图像当像素序列"的做法对应 2016 年 DeepMind 的 PixelRNNPixelCNN:按光栅顺序逐像素预测,分别用 LSTM 或带掩码的卷积保证"只看过去",在当时把 ImageNet 上的对数似然推到了新高度,但序列太长、采样慢,正与老师"难以扩展到高分辨率"的判断一致。老师预告的"把图像切成一维 token"的复兴路线包括:VQ-VAE / VQGAN(先用码本把图像编码为离散 token 序列,再在 token 空间自回归)、ImageGPT(Transformer 直接吃下采样像素序列)、Google 的 Parti 与更近的 VAR(多尺度"下一尺度预测"自回归),以及 Chameleon 等统一多模态模型——文本与图像共用一套自回归 Transformer。"自回归之于图像"在过去十年经历了从直译到 token 化的完整轮回。

九、自编码器:最笨的损失,最巧的瓶颈

分类树的下一站是变分自编码器(Variational Autoencoder, VAE)。老师故意先去掉"V",讲几页普通自编码器(autoencoder)——因为本课程此前还没正式讲过它。

自编码器是一种无监督学习特征的方法:在没有标签的条件下,从输入 \(x\) 中学出特征 \(z\)——这与上一讲的自监督一脉相承。我们希望特征 \(z\) 包含关于数据的有用信息:图中物体的身份、数量、颜色等等。编码器可以是任意架构(MLP、Transformer、CNN 都行),输入数据 \(x\),输出向量 \(z\)。没有标签,怎么训练?最简单的一个答案:重建输入——再接一个解码器(decoder),输入 \(z\)、输出 \(\hat{x}\),训练使输出尽量等于输入。老师戏称这是"某种意义上最笨的损失函数":我们在训练网络模仿恒等函数。可恒等函数我们本来就会,为什么要花一堆算力在巨量数据上学它?

答案:瓶颈(bottleneck)。如果模型容量无限——比如中间的 \(z\) 非常宽、学习毫无约束——网络当然能完美解决这个任务,但那毫无意义。我们真正想要的是让网络在约束下学恒等函数:把中间表示 \(z\) 压得远小于输入 \(x\)。课上数字:一张 1024 × 1024 的图像约 300 万个浮点数,而 \(z\) 可能只是一个128 维的潜码(latent code)。模型被迫把数据"挤"过这个极窄的通道,我们的期望是:这一挤压迫使网络学到数据的非平凡结构。训练完之后照例可以扔掉解码器,把编码器当作下游任务的初始化/特征提取器——完全是自监督的老故事。

但如果目标是生成呢?那我们想做的恰恰相反:扔掉编码器,想办法采样出与"模型学到的那些 \(z\)"分布相符的 \(z\),再喂给解码器造出新样本——这就成了一个隐式方法(全程没有密度值)。问题是我们把难题踢皮球了(老师原话:"we've just kicked the can down the road"):本来想生成 \(x\),于是训了个自编码器;现在拿到一数据集的 \(z\),要在 \(z\) 空间采样——这并不比原来容易分毫。卡住了。破局思路:如果能在训练时强行规定 \(z\) 服从某个已知分布(比如高斯)呢?那训练结束后直接从已知分布抽 \(z\)、过解码器,样本就到手了。给潜空间强加概率结构,正是"变分"自编码器要做的事。至于为什么叫"变分(variational)"——说来话长,术语有很长的文献历史;简单说,VAE 就是给传统自编码器加了一层概率化的包装

十、变分自编码器:本讲的重头戏

10.1 生成式假设:看不见的潜变量

VAE 的世界观:假设每个训练样本 \(x^i\)(上标 = 不同样本)背后都由一个潜在向量 \(z^i\) 生成——宇宙生成数据的流程是先采 \(z\),再由 \(z\) 生成 \(x\);生成那张图像所需的一切信息都装在 \(z\) 里。但我们永远观察不到 \(z\),也没有 \(z\) 的数据集。直觉:\(x\) 是图像,\(z\) 是"关于这张图你需要知道的一切"的潜特征表示——只可意会、不可观测。再外加一条硬约束:\(z\) 服从某个已知先验分布 \(p(z)\),压倒性的常见选择是标准正态分布(单位高斯)。训练成功后,生成只需两步:从先验抽 \(z\) → 过解码器 → 得到新样本。

10.2 训练的两条死路:积分不可解,后验不可解

怎么训练?看似不可能——要为每个 \(x\) 找到 \(z\),而 \(z\) 又永远看不见。老办法:回到最大似然。假如我们真有 \((x, z)\) 成对的数据集,直接套用第七节的 MLE(最大化对数似然)就能训练条件生成模型 \(p(x|z)\)——但我们没有 \(z\)。先假装有,往下走:

尝试一:边际化(marginalization)。联合分布 \(p(x, z)\) 必然存在(虽然看不见),用链式法则拆成 \(p(x|z) \cdot p(z)\),再对 \(z\) 积分:

$$ p(x) = \int p(x|z) \cdot p(z)\, dz $$

逐项检查:\(p(x|z)\) 没问题——它就是解码器,我们正要训练的神经网络;\(p(z)\) 没问题——已假设为单位高斯,解析可算;但这个积分要了命:对一个神经网络输出的复杂函数做全空间积分,既无解析解也无精确数值解。勉强用有限采样近似?\(z\) 是超高维空间,在训练内循环里嵌套数值积分是个坏主意。此路不通。

尝试二:贝叶斯公式。概率里另一件万能工具:

$$ p(x) = \frac{p(x|z) \cdot p(z)}{p(z|x)} $$

逐项检查:分子两项都好——\(p(x|z)\) 是解码器,\(p(z)\) 是高斯先验,而且这次没有积分了。但分母的后验 \(p(z|x)\)又把卡住了:要算它同样需要对 \(z\) 的积分。两条路都撞在同一堵墙上。

10.3 破局:再上一个神经网络

VAE 的招数非常"深度学习":算不出的项,就用网络去近似它。引入第二个神经网络 \(q(z|x)\)(权重记作 \(\phi\),与解码器权重 \(\theta\) 相互独立),让它去学那个算不出的后验——期望 \(q(z|x) \approx p(z|x)\)。严格逼近无法强制,但先把网络放上去,看看能推出什么。于是 VAE 的完整阵容是联合训练两个网络

10.4 神经网络怎么"输出一个分布"?——对角高斯

有同学问:网络怎么能输出概率分布?技巧是:规定所有分布都是正态分布,让网络只输出高斯的参数

细节

为什么解码器用固定方差?原则上解码器也可以逐像素输出各自的方差,但那毫无用处:在不建模像素间协方差的前提下,"每个像素各自允许抖一点、抖多少因像素而异"意味着从这个分布采样 = 取均值 + 加与逐像素方差成比例的独立噪声——不是 sensible 的做法。所以解码器这里"耍了个小赖":名义上输出分布,实际上永远只取均值、从不采样。固定方差还有个漂亮副产品——对固定对角方差的高斯做最大似然,等价于 L2 损失:常数 \(\sigma^2\) 从对数似然里提到前面变成常数系数,剩下的正是均值与 \(x\) 之间的平方距离:

$$ \log \mathcal{N}(x;\, \mu, \sigma^2 I) = -\frac{\lVert x - \mu \rVert^2}{2\sigma^2} + \mathrm{const} \qquad \Longrightarrow \qquad \text{最大似然} \equiv \text{最小化 L2} $$

另有同学问"逐像素平移的不变性呢"?老师答:那是架构性质——可以把平移不变/等变性设计进输出这些参数的网络结构里;但在损失函数层面确实没有考虑。

10.5 ELBO 推导:本讲唯一的一页数学(逐步)

万事俱备,现在推导 VAE 的训练目标。指导思想依然是最大似然:最大化 \(\log p(x)\)。老师预告"这是本讲唯一一页数学",但每一步都不难。

推导

第 1 步(出发点):最大化对数似然 \(\log p(x)\)。

第 2 步(代入贝叶斯):用 10.2 的贝叶斯公式改写,这是精确等价

$$ \log p(x) = \log \frac{p(x|z) \cdot p(z)}{p(z|x)} $$

第 3 步("犯傻"的一步):分子分母同乘 \(q(z|x)\)——那个我们凭空引入的第二个网络:

$$ \log p(x) = \log \frac{p(x|z) \cdot p(z) \cdot q(z|x)}{q(z|x) \cdot p(z|x)} $$

第 4 步(对数拆项):用"log 乘积 = log 之和"把上式拆成三项之和(老师按某种"有先见之明"的顺序重排并做了颜色标注,方便追踪每项去向)。

第 5 步(关键的观察):注意 \(\log p(x)\) 本身不依赖 \(z\)——表面上式子里有 \(z\),实际会完全消掉。而对任何不依赖 \(z\) 的量,都可以任意套一层对 \(z\) 的期望(期望分布随你挑,结果不变):把第 4 步的三项整体包进 \(\mathbb{E}_{z \sim q(z|x)}\)。再由期望的线性性,把期望分别施加到三项上——到此为止每一步都仍是精确恒等式

第 6 步(识别 KL 散度):得到三个看似神秘的期望项,若对概率公式足够熟,能认出后两项恰是 KL 散度(KL divergence,度量两个分布差异的非对称量,定义 \(D_{\mathrm{KL}}(q \,\|\, p) = \mathbb{E}_{z \sim q}[\log q(z) - \log p(z)] \ge 0\))。于是:

$$ \log p(x) = \mathbb{E}_{z \sim q(z|x)}[\log p(x|z)] \;-\; D_{\mathrm{KL}}\bigl(q(z|x) \,\|\, p(z)\bigr) \;+\; D_{\mathrm{KL}}\bigl(q(z|x) \,\|\, p(z|x)\bigr) $$

三项各自的含义

第 7 步(扔掉第三项):妙在不需要算也知道它非负——KL 散度恒 \(\ge 0\)。于是直接丢弃,得到下界

$$ \log p(x) \;\ge\; \mathbb{E}_{z \sim q(z|x)}[\log p(x|z)] \;-\; D_{\mathrm{KL}}\bigl(q(z|x) \,\|\, p(z)\bigr) \;\equiv\; \mathrm{ELBO} $$

这个量就是大名鼎鼎的证据下界(Evidence Lower Bound, ELBO),也叫变分下界。训练 VAE = 联合最大化 ELBO:它是真实对数似然的下界,最大化下界,希望真实似然也随之上行——虽不精确,但可算、可优化。

10.6 训练流程与重参数化技巧

把 ELBO 落成实际的训练步骤:

  1. 输入 \(x\),编码器输出分布 \(q(z|x)\)(即均值与方差两个向量);
  2. 对它施加先验 KL 项:把预测分布往单位高斯上拉——鼓励预测均值趋 0、预测方差趋 1;
  3. 从预测分布中采样一个 z——这里必须用重参数化技巧(reparameterization trick)才能让梯度穿过"采样"这一步:不直接从 \(\mathcal{N}(\mu(x), \sigma^2(x))\) 采样,而是先采 \(\epsilon \sim \mathcal{N}(0, I)\),再算
$$ z = \mu(x) + \sigma(x) \odot \epsilon $$

这样随机性被隔离在 \(\epsilon\) 里,\(z\) 对网络参数(\(\mu\)、\(\sigma\))可微,反向传播畅通;

  1. 把 \(z\) 送入解码器,得到解码器预测的高斯(实际只取均值);
  2. 施加重建项损失(固定方差下就是 L2)。

老师总结:看似吓人的一大页数学,最终落地的训练目标其实并不疯狂。

10.7 两个损失的博弈:VAE 最有趣的地方

老师认为 VAE 最耐人寻味之处在于:两个损失项对潜空间的要求针锋相对,训练就是让它们"打架"找平衡。模型被强制经由潜空间瓶颈,而两项各说各话:

两者拉锯的平衡点,就是"既能较好重建数据、潜空间又贴着先验"的那个折中状态——这正是 VAE 潜空间规整、连续、可采样的根源。

10.8 生成与潜空间结构:MNIST 的平滑变形

训练完成后,生成流程即终极目标:从先验 \(\mathcal{N}(0, I)\) 采一个 \(z\),过解码器,得到一张新图。另外有个漂亮的副产品:因为潜空间被约束为对角高斯,\(z\) 的各维之间带有统计独立的意味,可以分开单独调整;而这些独立维度往往各自编码了数据中某种有用、可解释甚至正交的因素。课上演示:在手写数字数据集(MNIST)上训练一个 VAE,固定其余维度、只变动潜空间的两个维度,解码出的数字会从一个类别平滑地变形为另一个类别——这是 VAE 相当普遍的性质,也是"潜空间结构良好"最直观的证据。

拓展

VAE 的现代遗产:Stable Diffusion 的"潜空间"与 ELBO 的延续。VAE 本身在图像生成上常被认为"偏模糊"(对角高斯的逐像素重建天然倾向输出均值),但它最持久的遗产是潜空间压缩:Stable Diffusion(即 Latent Diffusion Model)先用一个 VAE 把 512×512 图像压到约 64×64 的潜空间,再在该潜空间里训练扩散模型,训练与推理成本骤降一个数量级——其中"压缩端"正是本讲的 VAE,"生成端"是下一讲的扩散。概念上,扩散模型的训练目标同样可以写成一种层级式的 ELBO(每一步去噪对应 ELBO 的一项),本讲的推导直接通向下一讲;"为省算力而在低维潜空间里生成"的思想,后来也延续到视频生成模型中。

拓展

分类树之外的第五片叶子:可逆流模型与 Flow Matching。老师的分类树有四个叶子,其实还有一族方法可放在"显式 + 精确密度"下与自回归并列:流模型(Normalizing Flows)——用一串可逆神经网络把简单高斯变换为数据分布,借助概率的变量替换公式精确算出 \(p(x)\)(代表有 RealNVP、Glow),代价是可逆结构限制网络设计。更新一代的 Flow Matching(2022)则放弃了采样时的迭代 ODE 求解器:直接回归把噪声"搬运"到数据的速度场,训练更稳、更简单,已成为 Stable Diffusion 3、Flux 以及许多视频生成模型的主力训练目标。它与扩散模型(下一讲)共享"从噪声逐步走到数据"的图景——可以看作把"迭代间接采样"与"可学习的连续变换"结合的路线,读完下一讲再回看会非常清晰。

十一、总结与下一讲预告

老师收尾回顾:本讲讲了监督 vs 无监督两条轴,讲了判别、(无条件)生成、条件生成三种概率模型及其联系,然后走完了生成模型分类树的一半——显式密度分支:精确的自回归模型(链式法则 + 序列化数据 + 像素级建模的代价)与近似的变分自编码器(ELBO、重参数化、重建与先验的博弈、潜空间插值)。下一讲回到家族树的另一半——隐式密度分支:生成对抗网络(GAN)与扩散模型(Diffusion Models)

十二、本讲要点回顾

上一讲第 12 讲:自监督学习 下一讲第 14 讲:生成模型(二)