上一章的自编码器压缩得挺好,但你想让它造一张猫时——它做不到。
问题不在解码器,在
普通
于是
互动 · 点一下潜空间的任意位置,看解码出来是什么
那是训练数据里从来没有过的位置。普通
VAE 的全部工作就是:把这片海域填满,让整个潜空间变成一张连续的地图。
| 对比项 | 普通自编码器 | VAE |
|---|---|---|
| 一个点 z | 一个分布:均值 μ 和标准差 σ | |
| 采样方式 | 直接用 z | z = μ + σ ⊙ ε,其中 ε ∼ N(0, I) ⊙ 是逐个数相乘;ε 的每一维各自独立地从「平均 0、方差 1」的钟形分布(N(0, I))里抽 |
| 损失函数 | 只有重建误差 | 重建误差 + KL 散度 |
| 潜空间 | 散落的孤岛 | 连续、平滑、覆盖完整的地图 |
| 能生成吗 | 不能 | 能——从 N(0,I) 采样一个 z 直接解码 |
这行读作:KL 量两片分布差多远,0 就是一模一样;q(z|x) 是编码器给出的那片分布; ‖ 读作「相对于」;β 是 KL 的权重——第 4 节那个滑块拖的就是它。
重建误差:逼
KL 散度:逼每个数据点的编码分布贴近标准正态分布。
为什么这能填满海域?每片分布都是 N(0,I) 附近的一小团,
天然会彼此重叠、覆盖整个空间——空洞会少得多。
VAE 有个看起来要命的问题:采样是一个随机操作,随机操作没有梯度。 「从分布里抽一个数」输出和 μ、σ 之间没有能求导的公式——反向传播走到 z = 采样(μ, σ) 就断了。 重参数化把随机性挪到 ε 身上——ε 照样是随机抽的,但它和 μ、σ 无关,抽好之后在这一次计算里就是个定数:z = μ + σ·ε 成了普通乘加,就能求导了。
互动 · 重参数化前后
重参数化做的事,就是“把随机性从计算图里挪到输入端”:
z 是 ε 的确定性函数,ε 是外部喂进来的噪声——函数可导,随机采样那一步就没了。
这个技巧本身比 VAE 更有普适性:扩散模型(从噪声里一步步雕出图片,后面有专章)用它加噪声,
强化学习里的连续动作采样用它保梯度,Gumbel-Softmax(让「从一堆里选一个」也能求导的近似办法)也用它。
两项损失在互相拉扯。KL 项盯着一件事:每片的编码分布要和标准正态 N(0, I)(先验)对齐; 编码器吐出的后验分布 q(z|x),就是被它按着的那片。理解这场拉锯,就理解了 VAE 的一切。
互动 · 拖动 β,看潜空间怎么变形(点云是按 β 画的示意,不是训练出来的)
示意:八个颜色代表八类数字,点云按 β 的规律画出来,不是训练结果;两个读数也按同一套点云算。
| β | 会发生什么 | 结果 |
|---|---|---|
| ≈ 0 | 退化成普通 |
潜空间是散点,不能采样 |
| 0.5 ~ 2 | 两项平衡 | 潜空间连续,重建也还行。常规选择 |
| 很大时 | β 远大于 1、解码器又很强时,正则项压倒重建, |
后验坍塌:所有输入都被编码成同一个 N(0,I), |
界限在这里:β 稍大于 1(β-VAE 常用 4 左右)能让各维更分开;β 大到 KL 压倒一切、 尤其解码器又很强时,编码器才放弃编码信息——同一个旋钮,适度是好事,过头就坍塌。
坍塌是怎么发生的:KL 权重一大,
症状:重建图像全都变成一个模糊的平均样子。
解法:KL 退火(训练前期把 β 从 0 慢慢升上去)、
β-VAE(显式控制权衡)、或者用 自由比特技巧(给每个潜变量维度留一点 KL 免罚额度)。
这也是为什么 VQ-VAE(潜空间换成离散字典,见第 6 节)会绕开这个 KL 项。
潜空间连续之后,会得到一些漂亮的性质。
一张图看懂 · 两个点之间插值
| 能力 | 做法 | 典型效果 |
|---|---|---|
| 插值 | 在 z₁ 和 z₂ 之间线性走 | 平滑的过渡。如果是人脸,会看到连续的表情变化 |
| 潜空间算术 | z(微笑) − z(中性) + z(男生) 这种向量运算 | 类似词向量,可以编辑属性 |
| 随机生成 | 从 N(0,I) 采样 z,解码 | 得到从未存在过的、但看起来合理的样本 |
| 异常检测 | 算一下重建误差(误差大 = 解码器还原不出来) | 误差明显大的判为异常 |
前面五节讲直觉,这一节把式子摊开。整章只有两个式子:
① 怎么从一片分布里拿出一个点?——就是第 3 节那个
② 怎么保证这片分布不跑偏、还能拼成一张连续地图?——就是第 4 节那个
下面两张图都是真算的:拖一下,数字和图形一起变。
互动 · μ 定位置、σ 定宽度,ε 是这里唯一的随机数
互动 · 每个符号管图上的哪一块
回到第 4 节把 β 从 0 拖到 2:左图那片散点会慢慢收拢、重叠。
再回到上面这张图拖 σ —— 是同一个动作。
注意那张图里那条虚线(一个标准的
这一章的 VAE 只是最早的一版。后面的人想让它多做一件事,就只动一个地方——每处改动长出一个新名字。
一张图看懂:五处改动,各改了哪一块
| 变体 | 改了哪一点 | 想换来什么 |
|---|---|---|
| VAE(这一章) | 编码器吐一片分布(μ、σ);损失 = 重建 + KL | 潜空间连续,能采样、能插值 |
| β-VAE | 损失 = 重建 + β · KL(多出来的 β 就是权重) | 想让每一维各管一种属性(解耦,也叫解缠)时,适度加大 β(β-VAE 常用 4 左右)逼它分开;过头会坍塌,见第 4 节 |
| CVAE(条件 VAE) | 编码器和解码器都多喂一个条件,比如类别标签 | 按条件生成:说「生成一个 5」,就生成 5 |
| VQ-VAE | 潜空间换成一本离散字典,去查表,不再从高斯里采样 | 绕开后验坍塌;给图像换来离散的「视觉 token」 |
| 潜空间扩散里的 VAE(Stable Diffusion 的 AutoencoderKL) | 只当压缩器:图片先压进潜空间,扩散全程在里面跑,最后再解压 | 省算力——512×512×3 压成 64×64×4,要处理的数少了 48 倍 |
最容易和 VAE 混的是 VQ-VAE:它的潜空间不是连续分布,而是一本离散字典—— 编码器给出的是「第几号词」,不是 μ 和 σ。图像模型说的「视觉 token」就从它开始。
先说两个对手:GAN 是「造假者与鉴定师」的对抗游戏(下一章讲), 扩散模型把噪声一步步雕回图片(后面有专章)。每一条同时也是一份「什么时候别用 VAE」的清单。
一张图看懂:为什么「取平均」看起来就是糊的
| 问题 | 根源 | 什么时候真的会痛 → 换什么 |
|---|---|---|
| 图像永远是模糊的 | 重建损失(MSE)的最优解是条件均值——上面那张图: 同一个编码的几种可能细节,取平均就是糊的。 (平方误差下,猜它们的平均数时总误差最小——几个可能的答案,押中间最不吃亏。) 这是数学上的必然,不是训练不够。 | 要给人看的高清图 → GAN(判别器直接挑「像不像真的」)或扩散(一次只去一点噪声) |
| 潜变量各维度常常混在一起 | KL 把每片编码都按向 N(0,I),但各维之间没有「各管一摊」的约束。 解耦指的就是每一维只管一种属性(比如一维管粗细、一维管倾斜)。 有意思的是:β-VAE 加大 KL 权重,反而能让这些维度更分开 | 想单独调某个属性 → β-VAE |
| 训练目标有偏 | 第 2 节那行「重建误差 + KL」,在论文里叫 ELBO(证据下界): 它比真正想要的「数据出现的概率」(似然)略小一点,但好算,所以拿它当损失。 下界离真值差多远依赖假设,实际会低估 | 要精确的概率值 → 换能直接算似然的模型 |
| 指标好 ≠ 看起来好 | VAE 有可报的似然分数;GAN 连似然都没有,两者本来就不好直接比。 但人眼看上去,VAE 的图更糊。 这提醒我们:别拿一个和人的感受无关的数字下结论。 | 评价生成模型 → 似然和感知质量分开看 |
为什么 GAN 和扩散不糊?GAN 让判别器直接挑「像不像真的」,不受「均值最糊」约束;
扩散每次只去一点噪声,不用一步猜出全部细节。
而 VAE 留下的两样东西今天仍在用:重参数化(扩散模型也靠它)和潜空间——
Stable Diffusion 系、FLUX、Sora 都在潜空间里工作。这个思路直接来自 VAE。
这一章只有一个想法,而且它跟大多数人的直觉正好相反: 不是「让模型学得更准」,而是故意让它学得没那么准。
一张图看完这一章
回到第 4 节,把「β(KL 项的权重)」滑块从最左边 ≈0 往右拖到 2—— 左边那张潜空间图会从一堆散落的孤岛,慢慢收拢、重叠; 同时右边那行「类别之间的可分离程度」读数会一路往下掉——类别不再分得那么开。
那个瞬间就是「表达力换泛化」:滑块往右,模型松开「每个点都要重建准」的执念, 换来「任意位置都有东西可解码」。
重建逼模型记住细节,KL 逼潜空间连续,β 在中间调天平——第 4 节那个滑块拖的就是它。 采样那一步 z = μ + σ ⊙ ε 里没有可以省的东西:随机性全在 ε 身上(§M 那张卡)。
| 暗线 | 这一章的回答 |
|---|---|
| A 信息流动 | 形状一路在变窄再变宽:MNIST(手写数字图,拉直就是一串 784 个数)
→ d 维的 μ 和 σ(d 常常只有 2~20)
→ 采样出 z → 784 维。
真正的瓶颈是中间那个 d。VAE 比普通 |
| B 什么被牺牲了 | 牺牲了逐点精确重建的自由:普通 VAE 把这份清晰度换成了潜空间连续 + 可采样 + 可插值, 而「清晰度」就输给了 GAN 和扩散模型(第 7 节) |
| C 参数账本 | 给几个能对照的真实数字: ・一个 MNIST 的 MLP-VAE(784→400→20)大约 65 万个 ・真正在用的是 Stable Diffusion 的 KL-f8 VAE:把 512×512×3 = 786432 个数
压成 64×64×4 = 16384 个数,压缩约 48 倍——
扩散全程在这个潜空间里跑,省下来的算力就在这里 |
| D 跑在什么上 | 带宽受限的那一类。解码器主要是卷积 + 逐元素运算(中间也夹着注意力层),
算术强度(每搬一次数据能做多少次运算)很低,GPU 大部分时间在等 最贵的动作是解码:把 64×64×4 的潜码放大回 512×512×3,
第一层就变成 64×64×512(约 128 倍)——这正是「为什么要在潜空间做扩散」的硬件答案。
算力 / 带宽账见 《硬件与算力账本》 |
| E 它假设了什么 | 假设「整张潜空间都能被一个标准正态先验覆盖」—— 真实数据在高维里聚成的那个曲面,可以被一个各向同性的高斯(各个方向都一样)完全罩住。 这个假设在简单数据(MNIST 数字)上成立,在复杂图像上就不成立, 会进一步加剧模糊(糊的主因是 MSE 的条件均值,见第 7 节) |
| F 违背了哪个直觉 | 「注入噪声」通常是坏事,这里却是好事。z = μ + σ·ε 里的 ε 是真随机噪声,
它看上去只是在干扰训练——但正是它让 第二个反直觉:「重建误差更小」不等于「模型更好」(第 7 节那张表) |
它接住了上一章的什么:普通
它给下一章留了什么:这一章用 MSE 逼像,糊就是代价——下一章 《GAN 生成对抗网络》不比像素,只要骗过对手;更后面的 《扩散模型 DDPM》再把它和「逐步去噪」结合。
VAE = 给
它的图像生成质量输给了 GAN 和扩散模型——因为 MSE 的最优解就是模糊的。
但它留下的重参数化和潜空间两个思想,是今天主流生成模型的地基。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。