Generative Adversarial Networks 与 Diffusion Models —— 先把 GAN 的极小极大博弈逐项拆开:生成器与判别器如何互相博弈、为什么 \(V\) 不是损失函数、训练初期的梯度消失与非饱和损失技巧、最优判别器的理论保证及其两大警告;再看取代 GAN 的扩散模型:渐进加噪与迭代去噪的直觉、整流流(rectified flow)的几何图像与几行代码、无分类器引导(CFG)、潜在扩散"VAE + GAN + Diffusion 全都要"的现代管线、DiT 架构、文生图与文生视频的真实数字,以及蒸馏与三大数学形式主义
上讲从判别模型与生成模型的对比开始:二者都是概率模型的不同变体,区别在于预测什么、条件于什么、以及对什么做归一化。判别模型预测条件分布 \(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。
与自回归/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\)、过生成器,就等价于从数据分布采样。
但怎么"迫使"\(p_G\) 匹配 \(p_{\text{data}}\)?VAE 和自回归模型都是亲手写下某个目标函数来最小化;GAN 的trick 是把这件事外包给另一个神经网络——判别器 \(D\)。判别器输入图像(有时真、有时假),输出它是真图还是假图的判断。两个网络于是打起来:训练生成器去骗判别器,训练判别器作为分类器去正确区分真假。直觉是:对抗之下判别器会越来越擅长从假样本中识别真数据的特征;而生成器为了让假样本被判为真,必须产出越来越像真实数据的样本。
有同学问:生成器能从判别器那里得到反馈吗?能,而且这正是整个机制成立的关键——反馈就是梯度。生成器与判别器都只是普通神经网络,梯度可以从判别器出发、穿过生成出来的那张图像、一路反传回生成器。也就是说必须端到端训练:除了经由判别器的梯度,没有任何辅助损失项告诉生成器该做什么。
把直觉写成数学,就是联合训练 \(G\) 与 \(D\) 的极小极大博弈(minimax game)(课件用蓝色标生成器、红色标判别器):
先明确 \(D\) 的输出语义:\(D(x) = 1\) 表示判为真,\(D(x) = 0\) 表示判为假,实际输出是介于两者之间的软概率。
固定 \(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 生成样本"上的普通分类器,要做对两个方向。
再固定 \(D\),从生成器视角看:第一项与生成器完全无关(它只涉及真样本的判别),所以生成器只关心第二项。生成器想骗过判别器,即希望对假数据 \(D(x) = 1\)——同一个式子,判别器想最大化它,生成器想最小化它。把整套数学抽象成一个标量价值函数 \(V(G, D)\):判别器最大化 \(V\),生成器最小化 \(V\),二者如此对抗。
优化就是交替的梯度上升/下降:
这一点老师反复强调:\(V\) 的绝对值不反映生成器/判别器解决问题的好坏,更不反映我们真正关心的东西——\(p_G\) 与 \(p_{\text{data}}\) 的匹配程度。原因很简单:\(V\) 的取值依赖于判别器有多强。判别器很烂时,生成器轻易骗过它拿到漂亮的数字;判别器很强时,生成器必须真的很强。不同的 \((D, G)\) 组合可以给出完全相同的 \(V\)。于是 GAN 既难训练,也难判断训练得好不好:普通网络训练时看损失下降就行,而 GAN 有"生成器损失"和"判别器损失"两条曲线,可以画出来——但它们基本没有意义。
有同学问"会不会陷入局部极小?能不能训一阵再踢出来?"——老师的回答:成百上千篇论文、无数启发式技巧,没有什么真正流行开。另一个相关问题是"分别画两条曲线(判别器多好、生成器多好)行不行?"——尽管去画,看起来依然毫无用处。关于"怎么改 GAN 目标、不用 log、换成 Wasserstein 什么什么的"——同样有几百篇论文、五年来无数人的时间投入,老师认为没人拿出过真正的好方案,多数人最后还是用这个原始(vanilla)公式。
想象训练一开始:\(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\) 时的最优判别器:
一页纸的推导。固定 \(G\),对每个 \(x\) 独立最大化 \(p_{\text{data}}(x) \cdot \log D(x) + p_{G}(x) \cdot \log(1 - D(x))\)。对 \(D\) 求导置零:
直觉非常自然:某点真数据密度高则判真、生成密度高则判假,五五开则输出 0.5——判别器再也分不清的地方,恰是两个分布重合的地方。把 \(D^{*}\) 回代后可以证明:外层目标当且仅当 \(p_{G}(x) = p_{\text{data}}(x)\) 时取得最小值。理论上,判别器与生成器的均衡点唯一出现在两分布相等处——这给了 GAN 理论上的合法性。
但老师马上给出两条重要警告。其一:\(D^{*}\) 虽然写得出来,却永远算不出来——它依赖 \(p_{\text{data}}\) 的密度,而若能计算 \(p_{\text{data}}\) 的密度,生成建模早就做完了;它只能作为幻灯片上的公式存在。其二:该结果假设 \(G\) 与 \(D\) 都有无限的表示容量(能表示任意函数)——固定大小的神经网络当然做不到;更重要的是,它对能否经梯度上升/下降收敛到那个最优点只字未提,尤其考虑到现实中只有有限个数据样本。所以这是一个"聊以安慰"的理论结果,实践中既不严格成立、也不提供强保证。
实践里 \(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 系列大量工程正是为了让潜空间保持可插值、多样本覆盖。
有同学问:平滑潜空间难道不是理所应当出现的吗?老师:不一定。生成器可能直接记忆训练集中固定数量的样本:比如完全无视 \(z\),无论如何都输出记忆的 10 张图之一。由于输出与真样本可能逐位相同,判别器照样被骗——这甚至是博弈的合法解。此时生成器在 \(p_G\) 里只在有限几个样本附近堆了 Dirac delta 密度,其余处处没有概率质量,潜空间自然毫无平滑可言。这就是 GAN 各种"坍塌到反直觉解"的一个典型例子(老师在总结 GAN 缺点时也点了名:mode collapse,模式坍塌——训练随时可能崩掉:突然出现 NaN、inf,判别器发疯,生成器输出纯垃圾,而你没有任何损失曲线可供诊断)。
问题:训练数据与潜变量之间是什么关系?这是关于 GAN 非常本质的一问。生成器给出从潜空间到数据空间的单向映射 \(z \to x\);但 GAN 没有从 \(x\) 反推 \(z\) 的通道——这与 VAE 形成鲜明对比(VAE 显式学出 \(x \to z\) 的编码器)。可以用梯度下降数值求逆(确实有论文这么做),但 \(x\) 与 \(z\) 之间没有显式约束的关系;判别器只是在做分布层面的对齐——让生成器输出的整体分布对齐数据样本的整体分布,中间没有任何逐样本的监督。也有学双向映射的 GAN 变体论文,但从未真正流行。
回顾得失:从自回归到 VAE,我们得到了潜向量、放弃了密度;从 VAE 到 GAN,看似又放弃了可控的潜向量——换来的是好得多的样本。VAE 的样本一贯地模糊,单靠它自己永远出不了干净锐利的图;GAN 则能产出非常干净、清晰、高分辨率的样本。"你失去的是调参时的理智(sanity)。"另一个对比在推理端:GAN 推理极其高效——训完直接扔掉判别器,采一个 \(z\) 过一遍生成器就出图。
有同学问怎么构造数据集:"如果世界上不存在独角兽,怎么生成独角兽的照片?"回答:\(p_{\text{data}}\) 由你选择——你装配的训练集就是在选择要建模的 \(p_{\text{data}}\)。想生成与见过的所有东西都不像的样本?没戏。所有生成模型(所有神经网络)都只能做一点泛化:你可能从没见过"戴圣诞帽的写实风格独角兽",但你见过写实的马、写实的圣诞帽、独角兽的绘画、马的绘画——只要凑齐足够多"足够接近"的成分,模型就有望组合泛化出新东西,这永远只是"希望"。反过来看判别器:那张独角兽照片纹理、光照、阴影全都完美,样本本身毫无破绽;判别器得"聪明到知道独角兽不存在"才能判假——那是个相当难的语义问题,实践中的判别器通常没那么聪明。
优点:公式简单;调对了(如 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)——的几何直觉。这个领域足以讲很多讲课,但我们只有三分之二讲的时间。
与 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)一丝丝数据的结构";之后每轮输入都稍微干净一点,如此往复,若一切设置得当,最终把噪声全部去掉,得到一个生成样本。"这是个很怪异的设定,但这就是扩散模型的直觉。"有同学问步数是不是固定超参数——看情况:这页幻灯片刻意留了模糊(噪声是什么?"腐蚀"是什么意思?"去掉一点"是多少?迭代怎么迭代?),不同形式体系对每个词有不同的具体化方式。
从一般扩散进入具体的整流流。老师先声明立场:有人会说整流流不算扩散、是另一回事——"我不在乎,对我来说整流流就是扩散模型的一种,不服来辩。"接着用几何讲(二维画图,但注意真实对象是超高维的图像与高斯——低维直觉在高维完全失效,"很遗憾我们生活在这么低维的宇宙里")。
设定:\(p_{\text{noise}}\)(友好可控)与 \(p_{\text{data}}\)(宇宙生成图像的方式,疯狂复杂)。每个训练迭代做四件事:
上一页含糊的"带噪数据",在整流流里就是数据与噪声的线性插值。训练目标简单到过分:训练网络 \(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 到这几行代码——"这一点在太多讲演里不被讲清楚,快把我逼疯了。"
训练整流流(乃至任何扩散模型)时,有一个可以盯着的损失:损失下降,模型大体在变好。老师动情地回忆:对经历过"GAN 疯狂五年"的人,第一次训练扩散模型、看到有条真实的损失可看时——"天哪,这是多美妙的事。我们在 GAN 那两根曲线上耗了多少个小时,全像在读茶叶;而扩散模型给你一条漂亮、平滑的指数下降损失曲线,让人由衷快乐。"
GAN 推理简单(\(z\) 过一遍生成器完事);扩散模型的模型输出本身是"无用"的——拿到了 \(x_t\) 和预测的 \(v\),然后呢?所以推理比 GAN 复杂一步。流程:
# 整流流采样(完整)
x = randn(shape) # 纯噪声起步
for t in linspace(1, 0, steps): # 例如 50 步,从 1 走回 0
v = model(x, t) # 预测"数据→噪声"的速度
x = x - v / steps # 沿 -v 恰似做一步梯度下降
小结这笔交易: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\) 配成对。如果既知道怎么配对、又会从先验采样,问题直接做完。所有这些生成建模的形式,本质上都是"绕过这个圆的 square the circle"的不同姿势:在没有配对监督的条件下,学出一个 \(z \to x\) 的关联并能从 \(z\) 采样。
上讲说过:无条件生成没什么用,我们几乎总关心条件生成。整流流里这非常容易容纳。想象数据分布有子部分(课件举例是类别性的:数据由"方块"和"三角"两个子分布组成,各有 \(p(x \mid y=\text{方块})\)、\(p(x \mid y=\text{三角})\),合起来是整体 \(p_{\text{data}}\))——这就是条件生成该有的心理图像。具体做法:数据集变成成对的 \((x, y)\);模型把 \(y\) 作为附加输入一并吃进(训练与采样同理)。\(y\) 应当是用户可控的条件信号——文本提示、输入图像、任何推理时预期的用户输入——这让模型在实践中真正可控、可用。
有趣的后续问题:有没有旋钮能控制模型对条件信号的服从程度?实践发现,naive 训练出的条件模型常常不如期望的那样跟随条件。这就引出一个几乎无处不在的技巧:无分类器引导(classifier-free guidance, CFG),它对扩散训练循环只做一点点修改。
仍然训练输入 \((x_t, y)\) 的条件扩散模型,但每个训练迭代抛一次硬币:正面朝上,就把条件信息删掉——置为某个 0/null 值,彻底毁掉条件。毁掉的比例是个超参数,但 50% 是实践中大家都用的好默认值。于是模型被强迫学出两种速度向量:输入 null 条件时,等价于无条件生成器,预测速度 \(v_{\text{null}}\) 指向整个数据分布 \(p_{\text{data}}\) 的主体;输入真实条件 \(y\) 时,预测条件速度 \(v_y\) 指向该条件下的子分布。
"笨办法"是取两者的线性组合,把速度推得比条件方向更条件:\(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 \sim \mathrm{Uniform}(0, 1)\),等于给所有噪声水平同等重视——但这与任务的难度结构不匹配:
所以实践里常改用别的 \(t\) 采样分布。最流行的是 logit-normal 采样:形状近似高斯钟形,在 0 和 1 两端权重很小、中间权重很大,与难度结构对齐。另一类是偏移噪声调度(shifted noise schedules):不对称、整体向某一端偏移——在扩展到高分辨率数据时很重要。直觉:高分辨率图像相邻像素间相关性很强,低分辨率图像则弱得多;数据相关性越强,"恰到好处地摧毁信息"所需的噪声量就不同,这些调度不能朴素地跨分辨率复用——这是扩散模型一个大麻烦:形式很美,但 naive 地搬到高分辨率数据上并不好使。
老师说"扩散模型是最流行的生成模型"其实撒了个小谎:真正遍地开花的是潜在扩散模型(latent diffusion models)——一个多阶段流程:
这是当今最常见的扩散模型形态。那编码器-解码器怎么训?"我们见过编码器-解码器吗?——变分自编码器怎么样?"实践里它确实基本是个 VAE。但马上撞上刚说过的大问题:VAE 输出模糊——如果解码器重建出来的是模糊丑陋的图,重建质量就会卡死下游扩散模型生成质量的上限,这可不行。怎么办?"在解码器后面加个东西清理样本质量——我们可以把它做成一个 GAN。"于是训练四件套:编码器(图→潜空间)、解码器(潜空间→图)、判别器(分辨真假图像)、扩散模型(在潜空间生成)。
幸好底层架构这几年收敛出了些理智:相对朴素的 Transformer 直接用在扩散模型上就工作得非常好,即扩散 Transformer(Diffusion Transformers, DiT)——基本就是标准 Transformer 块,"没什么特别的秘方"。架构上真正要回答的问题是条件信息怎么注入:扩散模型现在要吃三个输入——带噪图像、时间步 \(t\)、条件信号(比如文本)。两条主要机制:
任务:输入文本提示,输出符合描述的图像。老师展示自己前一天写的提示词(真实生成样例):
"一张专业的纪录片风格照片:一只猴子与一只老虎在埃菲尔铁塔前握手。猴子戴着一顶香蕉做的帽子。老虎用两条腿站立、穿着西装。"——"这些东西现在居然能用了,很疯狂。"
管线:文本提示 → 预训练文本编码器(通常是 T5、CLIP 之类,一般冻结)得到文本嵌入。老师坦白"我又撒谎了——要训的模型还不止这些:除了编码器、解码器、VAE、判别器,你还得偷偷训练一个语言模型才能让整套东西工作"。文本嵌入与带噪潜变量(及扩散时间步)一起送入扩散 Transformer,迭代输出干净潜变量,最后过 VAE 解码器得到图像。
把数字说清楚:FLUX.1 [dev]。老师拿当前颇为强大的开源模型 FLUX.1 dev 举例:文本端用 T5 + CLIP 双编码器;VAE 编码器做 8× 空间下采样;扩散主干是 120 亿参数的 Transformer;而且它在 VAE 之上还额外叠了一层下采样("有点乱")——最终主干工作在1,024 个图像 token 的序列长度上。这组数字是理解下一节视频模型开销的基准。
管线几乎相同:文本过预训练编码器;唯一本质区别是潜变量多了一个时间维度——除两个空间维度 \(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 损失(通常):
各种"扩散变体",本质上就是往这四个槽位里塞不同的函数超参数。整流流取最简单的形式:\(a(t) = 1 - t\)、\(b(t) = t\),且 \(c\)、\(d\) 是常数(目标就是 \(v = z - x\))。方差保持(variance preserving, VP)把两系数坍缩成一个标量噪声调度 \(\sigma(t)\):
这样选的原因:若 \(x\) 与 \(z\) 独立且单位方差,输出保证也单位方差。方差爆炸(variance exploding, VE)则取 \(a(t) = 1\)、\(b(t) = \sigma(t)\),即 \(x_t = x + \sigma(t)\,z\)。监督目标同样多样:让网络预测干净数据、预测加进去的噪声、或两者的线性组合——整流流预测的是速度。老师的吐槽:选超参已经够糟了,现在要选的是 \(t\) 的函数——"这很疯狂,凭直觉永远设不出来,只能靠数学指导。"而数学指导有三套完全不同的体系:
延伸阅读推荐: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 年生成建模的主线剧情。