上一章《文本生成与采样》讲的是「学到的东西怎么取出来」;这一章反过来问:那份「什么重要」本身,能不能让网络自己学出来?
前面所有模型都在做「输入 → 输出」。
输入是一张 28×28 的手写数字灰度图(MNIST 数据集),拉平成 784 个数——每个像素一个数。 网络要做的事:把这 784 个数压成一小段,再原样还原回 784 个数。
| 部件 | 干什么 | 常见结构 |
|---|---|---|
| 把输入压成一小段"编码" | 784 → 256 → 64 → 16 | |
| 瓶颈 Bottleneck | 整个设计的核心——必须比输入小得多 | 16 维(原来 784 维) |
| 从编码还原出输入 | 16 → 64 → 256 → 784 | |
| 输入和还原有多像(像素级) | MSE 或 BCE |
瓶颈里那几个数叫编码,也记作 z;所有可能的 z 组成的空间,就叫潜空间。 后面说的「编码 z」「潜空间里的一个点」,指的都是它。 为什么是 16?它是人定的超参:小了糊、大了不压缩——具体丢多少,数学那节会把它摊开算。 损失函数一栏的两个选择也用得上:MSE 直接量两张图差多少;BCE 把每个像素当成「有多亮」的概率来算,只在像素值归一化到 0~1 时用。
如果瓶颈和输入一样宽,网络会直接学成恒等映射(输出和输入一模一样),什么也学不到。
正是因为它做不到完美还原,才被迫丢弃冗余、保留本质。
这和人有损压缩的记忆其实是一回事——你记不住一个房间的所有细节,但能记住"那是个什么样的房间"。
真算 · 瓶颈里只准留 k 个数,这张图会长什么样
如果
互动 · 亲手转动这条投影线
把鼠标移到下面公式里的 θ 上——上面那个「投影线角度」滑块会亮起来。
然后把它从 0° 一路拖到 180°,盯着那行「重建误差 MSE」看它在哪个角度最低——
那个角度,就是这一节要找的答案。
点「让网络自己找」——它会用真实的梯度下降去优化这个角度,
从你当前的位置一路爬到最优解。爬到的地方,就是 PCA 的主成分方向。
这意味着:一个神经网络学出来的东西,有时候能被一个一百多年前的统计学方法解释清楚。
只要在
对比 · 数据长在一张弯曲的流形上时会怎样
线性
非线性
线性
非线性自编码器拿到了软尺,可以贴着绳子的形状量。同样是把绳子压成"一个数",
后者能保留的信息多得多。
这个类比管到「沿着哪条弯线」为止:软尺的意思是沿着弯的数据走,用「走到第几厘米」一个数就能说清一个点在哪。
同一道沙漏,六种「加约束」的方式
| 变体 | 加了什么约束 | 学到了什么 | 用在哪 |
|---|---|---|---|
| 欠完备 | 瓶颈比输入窄 | 压缩表示——可以看成 PCA 的弯曲版:找的不再是直线,而是一条弯的曲线 / 曲面 | 降维、特征提取 |
| 去噪 | 输入加噪声,但要求还原干净的原图 | 更鲁棒的特征——它必须学会"噪声不是信号"(异常检测就靠这条:正常数据重建得好,没见过的数据重建误差大,按误差设阈值) | |
| 稀疏 | 要求瓶颈里大部分维度是 0 | 可解释的特征。今天被大量用于机械 | 特征解耦、SAE |
| 收缩 | 惩罚 |
在输入附近更平滑的表示 | 理论分析 |
| VAE | 瓶颈加概率分布约束 | 连续的潜空间,可以采样生成新数据 | 生成模型(下一章) |
| 掩码 | 遮住 75% 的输入,只还原被遮的部分 | 大规模视觉自监督 | 视觉 |
整章只有一件事在起作用:中间那道窄口留了几个数。 留几个,就等于只允许数据在几个方向上展开——没留的那几个方向,全部算进误差。
换一团更规整的点云来看(两个方向的方差分别是 1 + ρ 和 1 − ρ,ρ 由下面的滑块控制):最长的那根轴是第一个方向,和它垂直的那根是第二个; 每个方向上数据散开的程度,就是它的方差 λ(读作「lambda」)。 「瓶颈留 k 个数」的意思是:只记录每个点在前 k 根轴上的位置,剩下那些轴上的散开,全部算成误差。
数学节 · 留几个方向、丢多少误差(左边是几何,右边是账本)
互动 · 每个符号管图上的哪一块(卡片下面那张 = 为什么 MSE 的最优解是「平均」)
拖「相关系数 ρ」:数据越像一根斜着的长条,两个 λ 差得越远,一个方向就够用了。 把 ρ 拖到 0(数据变成一个圆),λ₁ 和 λ₂ 几乎相等——这时留 1 个方向,误差正好是总误差的一半。
| 硬伤 | 为什么 | 后果 |
|---|---|---|
| ① |
普通 |
无法采样生成。随机取一个编码 z,解码出来往往是垃圾——下一章 VAE 的全部工作就是修这个 |
| ② 像素损失 ≠ 感知质量 | MSE 会让模型倾向于输出"模糊的平均值"—— 当它不确定这一笔该粗一点还是细一点时,输出一个中间值能让 MSE 更小 | 重建图像总是糊的。这是所有像素级损失的共同问题 |
| ③ 会"抄近路" | 如果瓶颈不够窄,或者训练太久,模型可能学会把输入几乎原样编码 (比如把每张图的一个像素值直接存进瓶颈) | 看起来损失很低,但实际上没学到任何有用的表示 |
示意 · 潜空间是「散点」不是「地图」
解析解 · 瓶颈一宽到装得下输入,误差就掉到 0
用 MSE 训练的重建模型,输出天生偏模糊。原因很数学:
MSE 的最优解是条件均值 E[x|z]——已知编码是 z 时,所有可能原图的平均。
当模型不确定时,输出均值是最优策略——而均值看起来就是模糊的。
所以 GAN(生成对抗网络:用另一个网络当裁判挑刺,后面章节会讲)会换掉像素损失,改用对抗损失(让另一个网络来当裁判)或感知损失(比的是人眼看到的结构像不像)。
回到第 2 节那张画布。先拖那个「投影线角度」滑块,慢慢转一整圈——
盯住下面跳动的 重建误差 MSE:它会有一个最低点。
然后点一次 「🚀 让网络自己找」,看它用真实的梯度下降一路爬到你刚才亲手摸到的那个角度。
那个「只准转一个角度、误差由你定」的受限状态,就是「表达力」的本体。
线性
再切到第 3 节那两幅对比图:同样把 2 维压成 1 维,
右边那条能弯的曲线,就是把「一个角度」换成了「一张曲面」——
于是左边整片丢掉的波峰波谷,它全保住了。
那个瞬间你看到的就是「瓶颈宽度 + 非线性 = 表达力」。
如果你刚才只是觉得「这条线转起来挺顺手的」,那这一节对你就是没用的
——回到第 2 节那张画布重新转一次,这次盯着数字。
这一章在「参数账本」和「它假设了什么」两条上,答案比大多数章都具体。
| 暗线 | 这一章的回答 |
|---|---|
| A 信息流动 | 一条「先瘦后胖、回到原地」的流:784 → 256 → 64 → 16 → 64 → 256 → 784别的章里形状一路在变形(序列→向量、图→向量), 这一章输入和输出的形状完全一样,只有中间那个 16 是窄口。 所有信息都必须从这 16 个数的洞里挤过去——整章的机制只有这一条。 挤过去一次,就是一个具体的压缩比: 16 × 4 byte = 64 byte,
而一张 28×28 灰度图是 784 byte——
12 倍。(两种字节别混:图片存的是 0~255 的整数,一个像素 1 字节;模型算的是带小数的数,float32 一个数 4 字节。) |
| B 什么被牺牲了 | 用「重建细节」换来了「一套 去掉的信息不是随机的:它优先丢的是高频细节、保留的是低频结构—— 高频指图里变化很快的细节(笔画边缘),低频指变化很慢的大轮廓。 (这正是 MSE 的偏好,也是第 5 节硬伤②「重建图发糊」的同一个原因)。 更要紧的是第二笔代价:它牺牲了潜空间的连续性。 一个普通的 |
| C 参数账本 | 就用页首那张 MNIST 沙漏图上的数字算一遍(偏置都算进去): · · 两个对比数字:ResNet-50 是 2,560 万参数,是它的 58 倍; 而一张 MNIST 图只有 784 个数 ≈ 0.8 KB(像素是 0~255 的整数,每像素 1 字节)。 结论有点难堪:这个模型的参数,比它要还原的一张图多出 500 多倍。 训练集里有几万张图,模型不是只记一张;但参数多、瓶颈又不够窄的时候, 它就有条件把训练样本直接搬过去,而不是学共性——第 5 节硬伤③「抄近路」,在账本上就是这句话。 |
| D 跑在什么上 | 两个都不是——这一章既不算力受限,也不带宽受限,它只是小得过分。 · 一次前向约 2 × 43.7 万 ≈ 87 万 次乘加,
在消费级显卡上一秒能跑好几万张图,训练停在几十秒量级;· 最贵的动作是 784×256 矩阵乘,
它一个人就占了全模型参数的 约 46%(200,960 / 436,896);
瓶颈那一层 64×16 小到可以忽略。所以这章的结论要反过来读: |
| E 它假设了什么 | 两条假设,第二条几乎没人提。 · 流形假设:它假设「数据虽住在 784 维空间里,真实自由度远小于 784」—— 手写数字的笔迹变化,来来回回就那么些种。 这条假设一旦不成立(数据真的均匀铺满 784 维), · 「没学到的东西 = 噪声」假设:用 MSE 时它默认 凡是还原不出来的部分都是随机噪声,所以最优策略是输出条件均值, 于是画面发糊。这条假设也是错的——丢掉的往往是高频细节而非噪声。 |
| F 违背了哪个直觉 | 「输出等于输入,那它什么也没学。」 这是每个第一次看到 第二个反直觉:「压得越狠,学到的东西越多」。 常识是压得越狠信息丢得越多;这里恰恰相反, 瓶颈一旦宽到装得下输入,它就退化成一次复制,学到的东西反而归零。 有损,才是它有效的原因。 第三个更反直觉:「一百多年前的 PCA 就正好是它的最优解。」 线性自编码器无论怎么训,最终都只能落回 PCA 那张老地图上—— 神经网络在这件事上并没有比统计学高明,它只是能加非线性。 |
上面 A、C 两行里的账,写成正经的数学:
图 · 同一道窄口,两本账(数个数 vs 数字节)
图 · 参数都花在哪
线性版本就是 PCA。
它的真正价值不在压缩,而在"无监督地学到好特征"(去噪、稀疏、掩码自编码器都是这个思路)。
但它有一个致命局限:潜空间是一堆散点,不是一张地图,所以不能生成。
——这正是下一章 VAE 要修的;它接住了上一章《文本生成与采样》的「怎么取出来」。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。