上一讲第 13 讲:生成模型(一) 下一讲第 15 讲:3D 视觉

第 14 讲:生成模型(二)

Generative Adversarial Networks 与 Diffusion Models —— 先把 GAN 的极小极大博弈逐项拆开:生成器与判别器如何互相博弈、为什么 \(V\) 不是损失函数、训练初期的梯度消失与非饱和损失技巧、最优判别器的理论保证及其两大警告;再看取代 GAN 的扩散模型:渐进加噪与迭代去噪的直觉、整流流(rectified flow)的几何图像与几行代码、无分类器引导(CFG)、潜在扩散"VAE + GAN + Diffusion 全都要"的现代管线、DiT 架构、文生图与文生视频的真实数字,以及蒸馏与三大数学形式主义

本讲概览:

上一讲走完了生成模型家族树的显式密度那一半(自回归模型与变分自编码器),本讲进入隐式密度的另一半:模型不再输出密度值 \(p(x)\),但可以从学到的分布中采样。前半场是生成对抗网络(GAN)——两个网络对抗博弈,判别器学会分辨真假,生成器学会欺骗判别器,理论上均衡点恰是生成分布等于数据分布;代价是训练出了名的不稳定、没有可读的损失曲线。后半场是把它请下王座的扩散模型(diffusion models)——老师刻意绕开论文里"五页数学"的黑洞,用纯几何直觉讲透当今最主流的整流流(rectified flow):训练就是让网络预测"从数据指向噪声"的速度向量,采样就是从纯噪声出发沿预测速度小步回撤 50 步。最后把所有零件拼成真实的现代管线:潜在扩散(VAE 编码器 + GAN 判别器 + 扩散主干 + 冻结的文本编码器),并用 FLUX.1、Sora、Veo 3 的数字收尾。老师的总结是:GAN、VAE、自回归、扩散一个都没白讲,因为它们全都活在现代生成管线的某个角落里

一、开场:生成模型家族树的另一半

上讲从判别模型与生成模型的对比开始:二者都是概率模型的不同变体,区别在于预测什么、条件于什么、以及对什么做归一化。判别模型预测条件分布 \(p(y \mid x)\);生成模型学习数据分布 \(p(x)\);条件生成模型学习 \(p(x \mid y)\)。老师特别强调:概率分布天然带有归一化约束——各种可能的输出必须"竞争"概率质量,这是理解各类生成模型差异的关键线索。

随后是生成模型的家谱:显式密度模型(explicit density models)直接(或近似)输出 \(p(x)\)——其中可精确计算密度的一支是自回归模型:把图像拉成一串像素(甚至子像素)序列,每个像素当作 0~255 的 8 位整数,用 RNN 或 Transformer 这样的离散序列模型逐个预测;近似密度的一支是变分自编码器(VAE):联合训练编码器(\(x \to z\) 的分布)与解码器(\(z \to x\)),最大化似然的变分下界。而贯穿一切的核心洞见是最大似然:生成模型的训练目标几乎总是最大化观测数据在模型分布下的似然。

今天转向家谱的另一半——隐式密度模型(implicit density models):我们不再能得到任何密度值 \(p(x)\),模型只是"隐式地"拟合概率分布;虽然算不出 \(x\) 的密度,但可以从学到的分布中采样。第一个代表就是 GAN。

二、GAN:让两个网络互相对抗

2.1 基本设定:从已知先验到数据分布

与自回归/VAE 对照:自回归是似然方法,写下参数化的 \(p(x)\) 然后最大化;VAE 写下 \(p(x)\) 的近似(下界)再最大化。GAN 则干脆放弃直接建模 \(p(x)\)——不输出密度值,但给出从所拟合分布采样的办法。设定如下:手头有有限样本 \(x_i\),假设来自真实数据分布 \(p_{\text{data}}\)。\(p_{\text{data}}\) 是"宇宙用来给你生成数据的分布"——它涉及物理、历史、也许还有社会政治约束,极其复杂。我们想拟合一个近似模型去逼近它,从而能采出新样本。

做法是引入潜变量 \(z\):它类似 VAE 里的 \(z\),服从一个我们自己写下、完全可控的已知先验分布 \(p(z)\)——通常是标准高斯(有时均匀分布),总之必须简单、可解析采样。想象一个数据生成过程:从 \(p(z)\) 采一个 \(z\),送入生成器网络 \(G(z)\),输出 \(x\) 即为来自生成器分布 \(p_G\) 的样本。改变生成器的参数、架构或训练方式,就会诱导出不同的 \(p_G\)。GAN 训练的全部目标,就是迫使 \(p_G\) 尽可能接近 \(p_{\text{data}}\)——匹配之后,采 \(z\)、过生成器,就等价于从数据分布采样。

2.2 判别器与博弈直觉

但怎么"迫使"\(p_G\) 匹配 \(p_{\text{data}}\)?VAE 和自回归模型都是亲手写下某个目标函数来最小化;GAN 的trick 是把这件事外包给另一个神经网络——判别器 \(D\)。判别器输入图像(有时真、有时假),输出它是真图还是假图的判断。两个网络于是打起来:训练生成器去骗判别器,训练判别器作为分类器去正确区分真假。直觉是:对抗之下判别器会越来越擅长从假样本中识别真数据的特征;而生成器为了让假样本被判为真,必须产出越来越像真实数据的样本。

有同学问:生成器能从判别器那里得到反馈吗?能,而且这正是整个机制成立的关键——反馈就是梯度。生成器与判别器都只是普通神经网络,梯度可以从判别器出发、穿过生成出来的那张图像、一路反传回生成器。也就是说必须端到端训练:除了经由判别器的梯度,没有任何辅助损失项告诉生成器该做什么。

三、极小极大目标:逐项推导与训练循环

把直觉写成数学,就是联合训练 \(G\) 与 \(D\) 的极小极大博弈(minimax game)(课件用蓝色标生成器、红色标判别器):

$$\min_G \max_D V(D, G) = \mathbb{E}_{x \sim p_{\text{data}}}[\log D(x)] + \mathbb{E}_{z \sim p(z)}[\log(1 - D(G(z)))]$$

先明确 \(D\) 的输出语义:\(D(x) = 1\) 表示判为真,\(D(x) = 0\) 表示判为假,实际输出是介于两者之间的软概率。

3.1 判别器视角:一个标准的二分类

固定 \(G\),从判别器视角看这个目标的两项。第一项:期望号下从真实 \(p_{\text{data}}\) 采 \(x\)、过判别器、取 log(处理概率几乎总在 \(\log\) 空间进行,且 \(\log\) 单调,最大化 \(\log x\) 等价于最大化 \(x\))——最大化 \(\log D(x)\) 等价于要求对真数据 \(D(x) = 1\)。第二项:从先验 \(p(z)\) 采 \(z\)、过生成器得假样本、再过判别器;判别器希望把它们判为假,即 \(D(G(z)) = 0\),于是最大化 \(\log(1 - D(G(z)))\)。两项合起来:判别器就是一个在"真样本 vs 生成样本"上的普通分类器,要做对两个方向。

3.2 生成器视角:只关心第二项

再固定 \(D\),从生成器视角看:第一项与生成器完全无关(它只涉及真样本的判别),所以生成器只关心第二项。生成器想骗过判别器,即希望对假数据 \(D(x) = 1\)——同一个式子,判别器想最大化它,生成器想最小化它。把整套数学抽象成一个标量价值函数 \(V(G, D)\):判别器最大化 \(V\),生成器最小化 \(V\),二者如此对抗。

3.3 交替训练循环

优化就是交替的梯度上升/下降

注意方向相反的两步作用在同一个量 \(V\) 的不同参数集上——这正是不稳定性的根源之一。\(V\) 是博弈的"价值",不是损失函数

四、V 不是损失函数:GAN 为什么难训练

4.1 没有任何数值可以监控

这一点老师反复强调:\(V\) 的绝对值不反映生成器/判别器解决问题的好坏,更不反映我们真正关心的东西——\(p_G\) 与 \(p_{\text{data}}\) 的匹配程度。原因很简单:\(V\) 的取值依赖于判别器有多强。判别器很烂时,生成器轻易骗过它拿到漂亮的数字;判别器很强时,生成器必须真的很强。不同的 \((D, G)\) 组合可以给出完全相同的 \(V\)。于是 GAN 既难训练,也难判断训练得好不好:普通网络训练时看损失下降就行,而 GAN 有"生成器损失"和"判别器损失"两条曲线,可以画出来——但它们基本没有意义。

4.2 不稳定的三个来源

有同学问"会不会陷入局部极小?能不能训一阵再踢出来?"——老师的回答:成百上千篇论文、无数启发式技巧,没有什么真正流行开。另一个相关问题是"分别画两条曲线(判别器多好、生成器多好)行不行?"——尽管去画,看起来依然毫无用处。关于"怎么改 GAN 目标、不用 log、换成 Wasserstein 什么什么的"——同样有几百篇论文、五年来无数人的时间投入,老师认为没人拿出过真正的好方案,多数人最后还是用这个原始(vanilla)公式。

4.3 训练初期动态与非饱和损失技巧

想象训练一开始:\(G\) 与 \(D\) 都随机初始化。生成器输出纯随机噪声,与真实图像天差地别——判别器的任务极其容易,几个迭代内就能以很高置信度分辨真假。于是从生成器视角,它要优化的 \(\log(1 - D(G(z)))\) 出现在 \(D(G(z)) \approx 0\) 的区域——把 \(\log(1 - x)\) 画出来:在 \(x \to 0\) 处曲线极其平坦。平坦意味着梯度接近零:朴素目标下,生成器在训练初期几乎学不动。

深入

非饱和损失(non-saturating loss)。补丁是一个"小 hack":生成器不再最大化 \(\log(1 - D(G(z)))\),而是最小化 \(-\log D(G(z))\)(即最大化 \(\log D(G(z))\))。可以课后自行验证两者大体等价(最优解一致),但关键差别在梯度形状:\(\log x\) 在 \(x \to 0\) 处陡峭,恰好落在训练初期 \(D(G(z)) \approx 0\) 的位置——生成器在开局就能拿到大梯度。老师强调:从零训练 GAN 时这个改写在实践中极其重要。它的直接后果是:生成器与判别器实际计算的不再是同一个 \(V\)——各自维护各自的目标,只是"大体等价"。

顺带一提训练中的不变量:\(p_{\text{data}}\) 在整个训练过程中固定不变;变的是生成器诱导的 \(p_G\)(这正是判别器面临非平稳分布的原因)。

五、理论保证:最优判别器与全局最优

为什么这个目标可能是"好的"?老师说他以前的课件有逐步证明,今天只给 TL;DR。这是一个嵌套优化问题:内层对 \(D\) 最大化,外层对 \(G\) 最小化。做一点数学,可以把内层最大化解析解出来,写下给定 \(G\) 时的最优判别器

$$D^{*}(x) = \frac{p_{\text{data}}(x)}{p_{\text{data}}(x) + p_{G}(x)}$$
深入

一页纸的推导。固定 \(G\),对每个 \(x\) 独立最大化 \(p_{\text{data}}(x) \cdot \log D(x) + p_{G}(x) \cdot \log(1 - D(x))\)。对 \(D\) 求导置零:

$$\frac{p_{\text{data}}(x)}{D(x)} - \frac{p_{G}(x)}{1 - D(x)} = 0 \;\;\Rightarrow\;\; D^{*}(x) = \frac{p_{\text{data}}(x)}{p_{\text{data}}(x) + p_{G}(x)}$$

直觉非常自然:某点真数据密度高则判真、生成密度高则判假,五五开则输出 0.5——判别器再也分不清的地方,恰是两个分布重合的地方。把 \(D^{*}\) 回代后可以证明:外层目标当且仅当 \(p_{G}(x) = p_{\text{data}}(x)\) 时取得最小值。理论上,判别器与生成器的均衡点唯一出现在两分布相等处——这给了 GAN 理论上的合法性。

但老师马上给出两条重要警告。其一:\(D^{*}\) 虽然写得出来,却永远算不出来——它依赖 \(p_{\text{data}}\) 的密度,而若能计算 \(p_{\text{data}}\) 的密度,生成建模早就做完了;它只能作为幻灯片上的公式存在。其二:该结果假设 \(G\) 与 \(D\) 都有无限的表示容量(能表示任意函数)——固定大小的神经网络当然做不到;更重要的是,它对能否经梯度上升/下降收敛到那个最优点只字未提,尤其考虑到现实中只有有限个数据样本。所以这是一个"聊以安慰"的理论结果,实践中既不严格成立、也不提供强保证。

六、架构与代表作:DCGAN、StyleGAN 与潜空间插值

实践里 \(G\) 与 \(D\) 都用神经网络参数化——以前是 CNN(GAN 在 ViT 流行之前就失宠了,但老师相信用 ViT 也能做)。第一个真正给出非平凡结果的 GAN 是 DCGAN:一个五层卷积网络架构,在当时产出了相当令人兴奋的样本。老师特意讲了第一作者 Alec Radford 的故事:对绝大多数人来说 DCGAN 足以是一生的高光,但对 Radford 远远不够——他的下一个项目是 GPT(GPT-1、GPT-2 以及 OpenAI 的其他重要工作)。老师觉得这是个很酷的连结:一批做图像生成的人跳去做了离散文本的生成建模,在那里做出了奠基性的工作。

另一个老师点名的是 StyleGAN:不展开细节,但它是想了解 GAN 最佳实践的必读论文——架构复杂得多,实践效果很好。GAN 还有一个真的很可爱的性质:潜空间往往学得很平滑。取两个潜向量 \(z_0\)、\(z_1\)(各从高斯采出),在两者之间做插值,对曲线上每一点都生成一张图——通常会得到平滑的渐变序列(课件展示 StyleGAN3 论文的例子:动物在潜空间的连续移动中平滑地彼此变形)。这说明模型自己发掘出了某种有用的结构并塞进了潜空间

拓展

StyleGAN 系列与"平滑"的另一面。StyleGAN(2019)的核心创新包括:把 \(z\) 先经过一个映射网络得到中间样式向量 \(w\)、以自适应实例归一化(AdaIN)逐层注入样式、用双线性上采样替代反卷积以消除"棋盘伪影",从而实现粗到细的层级属性控制(StyleGAN2 修正了 AdaIN 的液体伪影;StyleGAN3 提出 alias-free,解决纹理"粘"在像素格上不随物体移动的问题——课件里的插值示例正来自它)。但平滑并非免费午餐:如老师在问答中指出的,生成器完全可以走"记忆少量训练样本"的捷径(见下节),StyleGAN 系列大量工程正是为了让潜空间保持可插值、多样本覆盖。

七、GAN 课堂问答、优劣与历史地位

7.1 平滑的潜空间并非理所当然:记忆与 Dirac delta

有同学问:平滑潜空间难道不是理所应当出现的吗?老师:不一定。生成器可能直接记忆训练集中固定数量的样本:比如完全无视 \(z\),无论如何都输出记忆的 10 张图之一。由于输出与真样本可能逐位相同,判别器照样被骗——这甚至是博弈的合法解。此时生成器在 \(p_G\) 里只在有限几个样本附近堆了 Dirac delta 密度,其余处处没有概率质量,潜空间自然毫无平滑可言。这就是 GAN 各种"坍塌到反直觉解"的一个典型例子(老师在总结 GAN 缺点时也点了名:mode collapse,模式坍塌——训练随时可能崩掉:突然出现 NaN、inf,判别器发疯,生成器输出纯垃圾,而你没有任何损失曲线可供诊断)。

7.2 数据集与潜变量的关系:单向映射

问题:训练数据与潜变量之间是什么关系?这是关于 GAN 非常本质的一问。生成器给出从潜空间到数据空间的单向映射 \(z \to x\);但 GAN 没有从 \(x\) 反推 \(z\) 的通道——这与 VAE 形成鲜明对比(VAE 显式学出 \(x \to z\) 的编码器)。可以用梯度下降数值求逆(确实有论文这么做),但 \(x\) 与 \(z\) 之间没有显式约束的关系;判别器只是在做分布层面的对齐——让生成器输出的整体分布对齐数据样本的整体分布,中间没有任何逐样本的监督。也有学双向映射的 GAN 变体论文,但从未真正流行。

7.3 "我们到底得到了什么":与 VAE 对比

回顾得失:从自回归到 VAE,我们得到了潜向量、放弃了密度;从 VAE 到 GAN,看似又放弃了可控的潜向量——换来的是好得多的样本。VAE 的样本一贯地模糊,单靠它自己永远出不了干净锐利的图;GAN 则能产出非常干净、清晰、高分辨率的样本。"你失去的是调参时的理智(sanity)。"另一个对比在推理端:GAN 推理极其高效——训完直接扔掉判别器,采一个 \(z\) 过一遍生成器就出图。

7.4 独角兽问题:生成模型如何泛化

有同学问怎么构造数据集:"如果世界上不存在独角兽,怎么生成独角兽的照片?"回答:\(p_{\text{data}}\) 由你选择——你装配的训练集就是在选择要建模的 \(p_{\text{data}}\)。想生成与见过的所有东西都不像的样本?没戏。所有生成模型(所有神经网络)都只能做一点泛化:你可能从没见过"戴圣诞帽的写实风格独角兽",但你见过写实的马、写实的圣诞帽、独角兽的绘画、马的绘画——只要凑齐足够多"足够接近"的成分,模型就有望组合泛化出新东西,这永远只是"希望"。反过来看判别器:那张独角兽照片纹理、光照、阴影全都完美,样本本身毫无破绽;判别器得"聪明到知道独角兽不存在"才能判假——那是个相当难的语义问题,实践中的判别器通常没那么聪明。

7.5 历史地位

优点:公式简单;调对了(如 StyleGAN3)能出非常漂亮、高分辨率的图。缺点:训练不稳定、无损失曲线可看、动辄崩溃(模式坍塌、NaN),需要极其小心地控制归一化、采样等一切细节,且很难扩展到超大模型、超大数据。尽管如此,约 2016 到 2020/2021 年,GAN 就是生成建模的默认选择,五年间涌现了成千上万篇论文——各种新公式、新损失、新数学形式,以及把 GAN 应用到一切能想到的生成任务上。那么,是什么取代了它?

拓展

被跳过的评价问题:GAN 好不好,怎么量化?课上老师顺口提到了"Wasserstein 某某"——指的正是 WGAN(2017):用 Earth-Mover(推土机)距离替代 JS 散度,以获得更平滑的损失信号,配合权重裁剪/梯度惩罚(WGAN-GP)或谱归一化(SNGAN)稳定训练;后续还有 BigGAN 等大规模化工作。另一个课上来不及展开的主题是评价:GAN 没有似然可算,业界转而使用 Inception Score(IS)与 FID(Fréchet Inception Distance)——把真样本与生成样本各自送入在 ImageNet 上预训练的 Inception 网络,在其特征空间中用高斯近似两个分布并计算 Fréchet 距离,距离越小越好。FID 至今仍是图像生成论文的标配指标(对扩散模型同样适用)。

八、扩散模型:从直觉到整流流

取代 GAN 的是扩散模型(diffusion models)。老师先打预防针:扩散文献非常疯狂——论文常常先铺五页数学才告诉你它在干什么;有三种截然不同的数学形式体系都能导出扩散模型,各论文的记号与术语互不兼容。所以他不会覆盖所有变体的严格数学,而是给一个直观总览,加上对当今最常见形式——整流流(rectified flow)——的几何直觉。这个领域足以讲很多讲课,但我们只有三分之二讲的时间。

8.1 高层直觉:渐进加噪,迭代去噪

与 GAN 相同的宏愿:把来自噪声分布的样本 \(z\) 变成数据分布的样本 \(x\);但做法完全不同——GAN 学一个把 \(z\) 直接映成 \(x\) 的确定性映射,扩散则更隐式、更间接。第一条硬约束:噪声与数据同形状——图像是 \(H \times W \times 3\),噪声就必须也是 \(H \times W \times 3\)。核心构造是考虑数据的不同噪声腐蚀版本:设噪声水平 \(t \in [0, 1]\)——\(t=0\) 是完全干净的数据;\(t=0.3\) 时把一部分噪声 \(z\) 混入数据 \(x\);\(t=1\) 时是彻底的噪声,即噪声分布本身的样本。\(t\) 这个参数在数据分布与噪声分布之间平滑插值(噪声分布几乎总是高斯——简单、可采样)。

然后训练一个网络做增量去噪:输入一个带中等噪声的样本,学会擦掉一点点噪声。推理时:先从噪声分布直接采一个纯噪声样本,再迭代地调用网络一点一点去噪。第一次调用最魔幻——网络面对纯噪声,被迫"在噪声里幻觉出(hallucinate)一丝丝数据的结构";之后每轮输入都稍微干净一点,如此往复,若一切设置得当,最终把噪声全部去掉,得到一个生成样本。"这是个很怪异的设定,但这就是扩散模型的直觉。"有同学问步数是不是固定超参数——看情况:这页幻灯片刻意留了模糊(噪声是什么?"腐蚀"是什么意思?"去掉一点"是多少?迭代怎么迭代?),不同形式体系对每个词有不同的具体化方式。

8.2 整流流:几何图像与训练代码

从一般扩散进入具体的整流流。老师先声明立场:有人会说整流流不算扩散、是另一回事——"我不在乎,对我来说整流流就是扩散模型的一种,不服来辩。"接着用几何讲(二维画图,但注意真实对象是超高维的图像与高斯——低维直觉在高维完全失效,"很遗憾我们生活在这么低维的宇宙里")。

设定:\(p_{\text{noise}}\)(友好可控)与 \(p_{\text{data}}\)(宇宙生成图像的方式,疯狂复杂)。每个训练迭代做四件事:

  1. 从先验采一个 \(z\)(\(p_z\) 简单,可解析采样);
  2. 从数据分布采一个 \(x\)——具体就是从有限训练集里挑一张;
  3. 选噪声水平 \(t \sim \mathrm{Uniform}(0, 1)\);
  4. 画一条从数据 \(x\) 指向噪声 \(z\) 的向量 \(v\)(称为流场的速度),并取这条线段上的插值点 \(x_t\)。
$$x_t = (1 - t)\,x + t\,z, \qquad v = z - x$$

上一页含糊的"带噪数据",在整流流里就是数据与噪声的线性插值。训练目标简单到过分:训练网络 \(f_\theta(x_t, t)\)(输入带噪样本与噪声水平)去预测速度向量 \(v\)。训练循环:

# 整流流训练循环(完整)
for x in dataloader:
    z = randn_like(x)               # 与 x 同形状的标准高斯
    t = uniform(0, 1)               # 噪声水平
    v_gt = z - x                    # 目标速度:从数据指向噪声
    x_t = (1 - t) * x + t * z       # 线性插值
    loss = mse(model(x_t, t), v_gt) # 就是 MSE

老师感叹:读论文时你会震惊于这里裹了多少晦涩的包装,而它最终 boil down 到这几行代码——"这一点在太多讲演里不被讲清楚,快把我逼疯了。"

8.3 与 GAN 的第一处对比:终于有损失曲线了

训练整流流(乃至任何扩散模型)时,有一个可以盯着的损失:损失下降,模型大体在变好。老师动情地回忆:对经历过"GAN 疯狂五年"的人,第一次训练扩散模型、看到有条真实的损失可看时——"天哪,这是多美妙的事。我们在 GAN 那两根曲线上耗了多少个小时,全像在读茶叶;而扩散模型给你一条漂亮、平滑的指数下降损失曲线,让人由衷快乐。"

8.4 推理:沿速度场小步回撤

GAN 推理简单(\(z\) 过一遍生成器完事);扩散模型的模型输出本身是"无用"的——拿到了 \(x_t\) 和预测的 \(v\),然后呢?所以推理比 GAN 复杂一步。流程:

  1. 预先选定步数(固定常数)——整流流50 步是好的起点,有时 30 步也还行;
  2. 从噪声分布直接采一个纯噪声 \(x\);
  3. 让 \(t\) 从 1 线性倒着走到 0(此简化版中等间距回撤);每一步:把当前 \(x\) 与 \(t\) 喂给模型得预测速度 \(\hat{v}_t\),沿该方向迈一小步,得到噪声略少一点的新样本,循环。
# 整流流采样(完整)
x = randn(shape)                    # 纯噪声起步
for t in linspace(1, 0, steps):     # 例如 50 步,从 1 走回 0
    v = model(x, t)                 # 预测"数据→噪声"的速度
    x = x - v / steps               # 沿 -v 恰似做一步梯度下降
为什么只走小步?因为预测的 \(v\) 并不会一路指向最终干净样本,它只是把你"送上"一条通往干净样本的轨迹——每走一小步就重新问一次模型方向(形式上看就像对预测速度做梯度下降式更新)。走完 50 步得到的 \(x_0\) 即为生成样本。"扩散模型其实没那么吓人"——训练加采样的完整实现能塞进一页幻灯片的几行代码里;老师保证:把这份代码接上一个合理的网络架构,它真的能跑出东西

小结这笔交易:GAN 训练难、推理易;扩散/整流流推理更繁琐,但换回了理智——训练有真损失、样本质量更好、并且对大数据与大模型扩展得非常好

拓展

扩散模型的当代统治地位与名词源流。"rectified flow"出自 Liu et al. 2022(Flow Straight and Fast),与之几乎同期的 Lipman et al. 2022 提出 flow matching,二者是同一思想的两个名字:直接回归概率路径之间的速度场。Stable Diffusion 3 与本讲的 FLUX.1 均已采用整流流目标;DDPM(2020)、score-based SDE(Song & Ermon,2021)则是另外两大形式体系的源头。产品层面,DALL-E 3、Midjourney、Imagen、Stable Diffusion 系列让"文生图"在 2022–2023 年成为大众技术,而 Sora/Veo 把战线推进到视频——正是这些系统让 GAN 时代的 StyleGAN 系从"最前沿"变成了"高质量的遗产"。

九、核心问题:如何把 z 和 x 配对起来

有同学的提问引出了老师"最近几天备课一直在想"的总结:生成建模的核心问题是——手里有一个会采样的先验(\(z\)),有一个想要生成的数据分布(\(x\)),核心在于如何建立 \(z\) 与 \(x\) 的关联。各类生成模型给出了不同答案:

关键在于:我们事先没有任何办法把先验样本 \(z\) 与数据样本 \(x\) 配成对。如果既知道怎么配对、又会从先验采样,问题直接做完。所有这些生成建模的形式,本质上都是"绕过这个圆的 square the circle"的不同姿势:在没有配对监督的条件下,学出一个 \(z \to x\) 的关联并能从 \(z\) 采样。

十、条件生成与无分类器引导(CFG)

上讲说过:无条件生成没什么用,我们几乎总关心条件生成。整流流里这非常容易容纳。想象数据分布有子部分(课件举例是类别性的:数据由"方块"和"三角"两个子分布组成,各有 \(p(x \mid y=\text{方块})\)、\(p(x \mid y=\text{三角})\),合起来是整体 \(p_{\text{data}}\))——这就是条件生成该有的心理图像。具体做法:数据集变成成对的 \((x, y)\);模型把 \(y\) 作为附加输入一并吃进(训练与采样同理)。\(y\) 应当是用户可控的条件信号——文本提示、输入图像、任何推理时预期的用户输入——这让模型在实践中真正可控、可用

10.1 问题:模型常常"不听话"

有趣的后续问题:有没有旋钮能控制模型对条件信号的服从程度?实践发现,naive 训练出的条件模型常常不如期望的那样跟随条件。这就引出一个几乎无处不在的技巧:无分类器引导(classifier-free guidance, CFG),它对扩散训练循环只做一点点修改。

10.2 训练:抛硬币毁掉条件

仍然训练输入 \((x_t, y)\) 的条件扩散模型,但每个训练迭代抛一次硬币:正面朝上,就把条件信息删掉——置为某个 0/null 值,彻底毁掉条件。毁掉的比例是个超参数,但 50% 是实践中大家都用的好默认值。于是模型被强迫学出两种速度向量:输入 null 条件时,等价于无条件生成器,预测速度 \(v_{\text{null}}\) 指向整个数据分布 \(p_{\text{data}}\) 的主体;输入真实条件 \(y\) 时,预测条件速度 \(v_y\) 指向该条件下的子分布

10.3 采样:外推向条件方向

$$v_{\text{cfg}} = (1 + w)\,v_y - w\,v_{\text{null}}$$

"笨办法"是取两者的线性组合,把速度推得比条件方向更条件:\(w = 0\) 时恰好还原纯条件模型;\(w\) 越大,对条件信号强调得越过头。采样时就按 \(v_{\text{cfg}}\) 而不是模型原始预测迈步:

# CFG 采样(每个去噪步)
v_y  = model(x_t, t, y)          # 条件速度
v_0  = model(x_t, t, null)       # 无条件速度
v_cfg = (1 + w) * v_y - w * v_0  # 外推,w 越大越听话
x_t = x_t - v_cfg / steps

名字的由来"很蠢":更早有一篇 classifier guidance 的论文(课上不展开),这一篇去掉了分类器,故称 classifier-free——两篇论文只隔了九个月,而后者已过去四年,名字就这么将错就错地留下了。老师强调:CFG 对产出高质量输出极其重要,在扩散模型中无处不在;代价是采样成本翻倍——每个迭代要把模型跑两遍(\(v_y\) 和 \(v_{\text{null}}\) 各一次),这是个问题。(课件上还有一页"最优预测"的内容,因时间关系老师跳过了。)

十一、噪声水平 t 该怎么采:logit-normal 与 shifted 调度

原始整流流里 \(t \sim \mathrm{Uniform}(0, 1)\),等于给所有噪声水平同等重视——但这与任务的难度结构不匹配:

所以实践里常改用别的 \(t\) 采样分布。最流行的是 logit-normal 采样:形状近似高斯钟形,在 0 和 1 两端权重很小、中间权重很大,与难度结构对齐。另一类是偏移噪声调度(shifted noise schedules):不对称、整体向某一端偏移——在扩展到高分辨率数据时很重要。直觉:高分辨率图像相邻像素间相关性很强,低分辨率图像则弱得多;数据相关性越强,"恰到好处地摧毁信息"所需的噪声量就不同,这些调度不能朴素地跨分辨率复用——这是扩散模型一个大麻烦:形式很美,但 naive 地搬到高分辨率数据上并不好使。

十二、潜在扩散:VAE + GAN + Diffusion 全都要

老师说"扩散模型是最流行的生成模型"其实撒了个小谎:真正遍地开花的是潜在扩散模型(latent diffusion models)——一个多阶段流程:

  1. 第一阶段:训练编码器-解码器。编码器把图像映入某个潜空间,理想情况下做空间下采样因子 \(D\)、通道数从 3 升到 \(C\)。常见配置:8×8 空间下采样、16 通道。这类编解码器通常是带注意力的 CNN,近年的论文也探索用 ViT;
  2. 第二阶段:在潜空间(而非原始像素空间)训练扩散模型。采样图像、过冻结的编码器得到潜变量、给潜变量加噪、训练扩散模型去噪。关键:编码器冻结、梯度不回传——它只负责提取潜变量;
  3. 推理:采一个随机潜变量 → 反复过扩散模型去噪 → 得到潜空间里的干净样本 → 过解码器解码成干净图像。

这是当今最常见的扩散模型形态。那编码器-解码器怎么训?"我们见过编码器-解码器吗?——变分自编码器怎么样?"实践里它确实基本是个 VAE。但马上撞上刚说过的大问题:VAE 输出模糊——如果解码器重建出来的是模糊丑陋的图,重建质量就会卡死下游扩散模型生成质量的上限,这可不行。怎么办?"在解码器后面加个东西清理样本质量——我们可以把它做成一个 GAN。"于是训练四件套:编码器(图→潜空间)、解码器(潜空间→图)、判别器(分辨真假图像)、扩散模型(在潜空间生成)。

老师总结全讲最点题的一段话:"为什么要走完所有这些生成模型的形式?就是为了让你看懂现代管线。当前生成建模的最先进水平——它是 VAE 吗?是 GAN 吗?是扩散吗?——全是。现代生成管线要训练一个 VAE、一个 GAN、和一个扩散模型。很抱歉,它就是一团乱麻(It's a mess)。"

十三、DiT:用 Transformer 造扩散模型

幸好底层架构这几年收敛出了些理智:相对朴素的 Transformer 直接用在扩散模型上就工作得非常好,即扩散 Transformer(Diffusion Transformers, DiT)——基本就是标准 Transformer 块,"没什么特别的秘方"。架构上真正要回答的问题是条件信息怎么注入:扩散模型现在要吃三个输入——带噪图像、时间步 \(t\)、条件信号(比如文本)。两条主要机制:

十四、应用管线:文生图与文生视频的真实数字

14.1 文生图(text-to-image)

任务:输入文本提示,输出符合描述的图像。老师展示自己前一天写的提示词(真实生成样例):

"一张专业的纪录片风格照片:一只猴子与一只老虎在埃菲尔铁塔前握手。猴子戴着一顶香蕉做的帽子。老虎用两条腿站立、穿着西装。"——"这些东西现在居然能用了,很疯狂。"

管线:文本提示 → 预训练文本编码器(通常是 T5、CLIP 之类,一般冻结)得到文本嵌入。老师坦白"我又撒谎了——要训的模型还不止这些:除了编码器、解码器、VAE、判别器,你还得偷偷训练一个语言模型才能让整套东西工作"。文本嵌入与带噪潜变量(及扩散时间步)一起送入扩散 Transformer,迭代输出干净潜变量,最后过 VAE 解码器得到图像。

深入

把数字说清楚:FLUX.1 [dev]。老师拿当前颇为强大的开源模型 FLUX.1 dev 举例:文本端用 T5 + CLIP 双编码器;VAE 编码器做 8× 空间下采样;扩散主干是 120 亿参数的 Transformer;而且它在 VAE 之上还额外叠了一层下采样("有点乱")——最终主干工作在1,024 个图像 token 的序列长度上。这组数字是理解下一节视频模型开销的基准。

14.2 文生视频(text-to-video)

管线几乎相同:文本过预训练编码器;唯一本质区别是潜变量多了一个时间维度——除两个空间维度 \(H\)、\(W\) 外再加时间轴;解码器相应变成时空自编码器,同时在空间与时间上下采样,再把潜变量上采样回像素,输出视频。课件播放了 Meta Movie Gen 论文(去年发布)生成的视频样例。核心要点:视频模型训练开销暴涨的元凶是序列长度——要生成高分辨率、高帧率的视频,token 数暴增:文生图是 1,024 个 token,而这个文生视频模型要处理约 76,000 个视频 token,架构几乎没变,账全记在长序列上。

行业节奏:过去一年(甚至 18 个月)基本就是视频扩散模型的时代——几乎每周都有新模型发布,有开源的、有出技术报告的(给你看些架构与训练细节)、也有纯工业闭源的(什么都不告诉你,"但会收你的信用卡号让你出样本")。里程碑是 OpenAI 的 Sora 博文(2024 年 3 月):不是第一个视频扩散模型,但第一个效果真正好的;它采用现代扩散 Transformer + 整流流("Sora 是否真用了整流流我并不确定,他们没说;但他们是第一批把 DiT 真正规模化并做通的")。那是视频扩散的"四分钟一英里时刻"——各大公司随即注意到并迅速跟进复刻。而就在本讲开讲的当天上午 11 点,Google 发布了 Veo 3——"几乎可以肯定是当前最好的视频生成模型,我是来上课的车上读完博文的,看起来很酷";它还联合建模声音,视频帧之外能一并输出音频。

十五、老大难:采样太慢与蒸馏

扩散模型的一大痛点是采样慢:采样是迭代式的,而模型可能高达几百亿参数、序列长度上万甚至更长——即便用整流流,推理也得跑几十次模型。解法是一族叫蒸馏(distillation)的算法(课上没时间展开,给了参考文献):把原本推理需要 30/50/100 步的扩散模型,改造成步数少得多仍能出好样本的模型。代价是牺牲样本质量——蒸馏的全部技巧就在于在减步的同时尽可能保住质量;有的方法能压到单步采样,很酷,但生成质量通常明显受损。这是 2024–2025 年非常活跃的研究方向。

拓展

少步生成的技术谱系。老师课件里列的参考文献大致对应这条线:一致性模型(Consistency Models)与潜在一致性模型(LCM)学习"任意噪声点一步映射回轨迹起点";对抗扩散蒸馏(ADD,即 SDXL-Turbo 背后)用 GAN 损失蒸馏——有趣的是 GAN 以这种方式回到了扩散管线里;分布匹配蒸馏(DMD)则直接匹配分布。另一条并行路线是"更聪明的积分器与更高阶求解器"(DPM-Solver 等),不重训模型、只改采样器,属于第十七节 SDE 视角的直接应用。

十六、扩散的三大数学形式主义(速览)

老师先重述整流流目标,再把它放进一个泛化框架:采 \(x \sim p_{\text{data}}\)、\(z \sim p_{\text{noise}}\)(连续模型里噪声分布几乎总是高斯,一般不动它)、\(t \sim p_t\)(uniform / logit-normal / shifted,可变);带噪样本是 \(x\) 与 \(z\) 的线性组合,组合系数是 \(t\) 的函数;监督目标也是 \(x\) 与 \(z\) 的线性组合;网络输入 \((x_t, t)\) 出预测,配 L2 损失(通常):

$$x_t = a(t)\,x + b(t)\,z, \qquad \text{目标}\; y = c(t)\,x + d(t)\,z, \qquad L = \lVert f_\theta(x_t, t) - y \rVert^2$$

各种"扩散变体",本质上就是往这四个槽位里塞不同的函数超参数。整流流取最简单的形式:\(a(t) = 1 - t\)、\(b(t) = t\),且 \(c\)、\(d\) 是常数(目标就是 \(v = z - x\))。方差保持(variance preserving, VP)把两系数坍缩成一个标量噪声调度 \(\sigma(t)\):

$$x_t = \sqrt{1 - \sigma(t)^2}\,x + \sigma(t)\,z$$

这样选的原因:若 \(x\) 与 \(z\) 独立且单位方差,输出保证也单位方差方差爆炸(variance exploding, VE)则取 \(a(t) = 1\)、\(b(t) = \sigma(t)\),即 \(x_t = x + \sigma(t)\,z\)。监督目标同样多样:让网络预测干净数据、预测加进去的噪声、或两者的线性组合——整流流预测的是速度。老师的吐槽:选超参已经够糟了,现在要选的是 \(t\) 的函数——"这很疯狂,凭直觉永远设不出来,只能靠数学指导。"而数学指导有三套完全不同的体系:

  1. 潜变量模型视角:每个干净样本 \(x_0\) 都对应一串无法观测的加噪版本,它们是潜变量——结构像极了 VAE,可以用与 VAE 相同的数学技巧最大化似然的变分下界,由此导出扩散;
  2. 分数函数(score function)视角:对分布 \(p_{\text{data}}\) 定义分数 \(s(x) = \nabla_x \log p_{\text{data}}(x)\)——它是指向高概率密度区域的向量场;扩散模型学的正是数据分布的分数函数,更准确说,学的是对应不同噪声水平的一族分数函数。完全不同的数学,最后导出的算法却长得几乎一样;
  3. 随机微分方程(SDE)视角(老师自嘲"我自己也没完全搞懂,别问太多"):写一个微分方程,描述把噪声样本搬运到数据样本的无穷小传输;网络相当于学一个数值积分器。在这个视角下,整流流采样里那种朴素的"梯度下降式"小步走,对应的就是前向欧拉积分器——于是自然可以换成更高级的积分器,把分数场走得更准。这又打开了两整类新的采样方法。"这些是深水区。"

延伸阅读推荐:Sander Dieleman 的博文 Perspectives on Diffusion——给出了八种理解扩散模型的视角,"他写的一切都强烈推荐"。

十七、自回归的回归:现代第二配方

最后老师"偷偷塞进一页":自回归模型也杀回来了。同样的编码器-解码器戏码照样能玩——在离散 VAE 得到的离散潜变量上训练自回归模型。这就是为什么本课程把 GAN、VAE、自回归、扩散全部讲了一遍:它们在现代机器学习管线里全都被用上了。扩散之外,这是现代生成建模的另一条主流配方。

拓展

"离散潜变量 + 自回归"一脉的当代进展。这条路线的代表:VQ-VAE / VQGAN 式离散 tokenizer + GPT 式 transformer 是早期经典(DALL-E 1 即此配方);2024 年以来的新进展包括 VAR(Visual Autoregressive Modeling,放弃逐 token 光栅序、改为逐尺度"下一分辨率预测")与 LlamaGen(证明普通自回归 transformer 缩放后能比肩扩散);MAR(掩码自回归 + 扩散头做逐 token 连续生成)干脆把两族方法杂交。更宏观地,GPT-4o 的原生多模态图像生成、Chameleon 等统一 token 模型,都印证了老师这句"全都被用上了"——扩散与自回归两大配方在图像生成上正面竞争,是 2024–2026 年生成建模的主线剧情。

本讲要点回顾

上一讲第 13 讲:生成模型(一) 下一讲第 15 讲:3D 视觉