接着上一章《神经符号与可验证推理》:「想多久」能按题目难度分配,
「走多少层」为什么不能?
标准前馈网络是固定计算量的——不管输入是「这是猫还是狗」还是
「用黎曼猜想推一下这个」,层数、矩阵一模一样。这在工程上简单,在道理上荒唐。
一个 70B 模型回答「1+1 等于几」,消耗的 FLOPs 和回答 「分析这段代码的时间复杂度」是一模一样的。
| 现实情况 | 固定计算量的做法 | 本该怎么做 |
|---|---|---|
| 很多输入其实很简单 | 照样跑满全部层数 | 中间层就有把握了 → 提前收工 |
| 一小部分输入特别难 | 跑到最后也没想清楚,也只能给答案 | 再想想 —— 多花算力反复推敲 |
| MoE 已经做了一半 | 每次只激活一部分专家(参数维度上省) | 但它层数还是固定的——该走的层一层不少 |
动态分配算力有三个地方可动手:网络的深度(中间层够确定就不往下走)、 每层用多少参数(只激活一部分,即 MoE,阶段 5 讲过)、 推几步(难就多想几轮,阶段 5 的 reasoning 那章)。 这一章只讲最直接的那一个——深度,因为它是唯一能在推理时动态改变的。
认知科学里有个很贴切的划分:系统 1(快、直觉、省力)和
系统 2(慢、费力、准确)。
人不会对每个问题都启动深思熟虑模式。「今天几号」用系统 1,
「这个合同有什么法律风险」才切到系统 2。
固定计算量的神经网络,等于对所有问题都强制用系统 2 的全部流程。
这个类比管到「该不该多花力气」为止:人自己判断用哪种思考,网络只认一个阈值和一个概率数。
标准网络只有最后一个出口。早退架构在中间几层各自挂一个小的分类头, 每个出口都能给出预测和置信度。
结构示意
损失函数(L,越小越好)从「最后一个出口的损失」变成「所有出口损失之和」:
L = L出口1 + L出口2 + L出口3
这样逼着中间层也得学好。不然中间出口乱猜,
置信度不可信,早退就成了随机提前收工。
辅助出口要在训练时一起学,所以早退不是给训好的模型加几个头就能用——通常要重训。
真算 · 每个出口各自有多大把握(240 个测试样本)
下面这个网络有 3 个出口。每个置信度都是当前样本一路走到那一层之后, 经过该出口 softmax 得到的输出;阈值 τ 就是「把握到多少才允许退出」。
核心大图 · 逐层置信度决定在第几层退出
点「容易的样本」「随机的样本」「难的样本」,各试几次:
· 容易的样本(离边界很远的点)——第一层出口的置信度就很高,
这时只跑 1 层,省掉约 2/3 的算力(这个演示共 3 层)
· 难的样本(正好落在两个类中间的点)——它一路走到最后,
置信度都不高。这种样本必须跑满,早退对它没有意义
早退的价值不来自「所有输入都更快」,而来自「大部分输入其实很简单」。
真算 · 它说自己有多准,和它实际有多准
要算的账是:把置信度阈值调高调低,能省多少算力、掉多少准确率。 下面是 240 个测试样本的真实统计,准确率算的是它实际退出的那个出口给出的答案。 阈值没有标准答案,按你能接受的准确率在验证集上选。
互动 · 阈值 vs 省下的算力 vs 准确率
这里算的是理论 FLOPs(模型要做的乘法次数)。真实 GPU 上,早退的收益会大打折扣—— 原因见第 6 节。所以看到论文里写「省 60% 算力」, 别直接理解成「快 2.5 倍」(墙钟时间 = 从开始到结束实际花的时间)。
三种省法,动的是哪一刀
| 方法 | 在哪一维省 | 机制 |
|---|---|---|
| Early Exit 2016 起 | 深度 | 每层挂辅助分类头,置信度够高就返回。最直接,也最容易实现 |
| ACT Adaptive Computation Time | 深度 | 让模型自己学「该想几步」——用一个额外的输出预测「还要不要再算」, 用「思考成本」惩罚它多想。理论上优雅,实际用起来要小心调参 |
| PonderNet | 深度 | ACT 的概率化版本。把「停在第几步」变成一个可微的概率分布(能对它求导、 能端到端训练),再给每一步一个固定概率继续往下想(几何分布),训练稳定得多 |
| CALM 2022 | 深度 | 把早退用在大语言模型上:用当前层的隐状态和前一层的隐状态做对比, 够接近就跳过。不需要额外的分类头 |
| MoE 阶段 5 | 参数 | 每层只激活一部分专家。层数不变,但每层只用一部分参数 |
| 测试时计算 阶段 5 | 推理步数 | 让模型「想久一点」——生成更长的思维链、采样多个候选再投票。 和早退方向相反:这个是往多了花 |
| 级联 Cascade | 模型大小 | 先用小模型答,置信度低再升级到大模型。 工业界最实用的自适应计算形式,因为它不需要改模型结构 |
| 投机解码 阶段 6 | 验证成本 | 小模型猜、大模型验。本质也是一种「大部分情况走便宜路径」 |
三者的区别一句话:早退省深度、MoE 省宽度、测试时计算花步数。 前两个省钱,第三个花钱,但目标一致——把算力从不需要的地方挪到需要的地方。
前面说「置信度够高就从这一层返回」。整件事只有一道不等式, 但读起来最容易空——拿哪个数去比?比出来的「第一个」又是什么意思? 第一个达标的出口记作 l*(读作「L 星」),一张图看完整件事。
互动 · 拉高虚线,看出口一个个掉下去
互动 · 每个符号管图上的哪一块
卡片下面那条横条是期望算力:每个出口都能拦住一部分样本, 它贡献的算力 = (用掉的层数 l) × (停在该层的样本比例 P)。全批平均要跑几层 = Σ l·P(停在第 l 层),图里那条横条的三个格子就是这么来的。这里默认每层开销一样,所以算力直接用层数记; 真实网络每层的计算量不同,账要按 FLOPs 各自加权。
把虚线往上拖:出口 1 先掉下去,出口 2 掉下去……最后只剩一个出口够得着。 虚线越高,走的路越长。那个「第一个够得着的出口」,就是公式里的 l*。
| 代价 | 说明 | 什么时候真的会痛 → 换什么 |
|---|---|---|
| 动态控制流 vs GPU 并行 | 这是最根本的矛盾。GPU 快的唯一原因是同一个指令同时作用在成千上万个数据上。
但如果 batch 里第 7 个样本在第 2 层就退出了、第 13 个要跑到第 3 层——
它们没法再放在同一个矩阵乘法里。 结果是:省了 FLOPs,却没省时间。 |
输入难度参差、又要求低延迟 → 别用早退,改用不改结构的级联 / 投机解码 |
| 置信度不等于正确率 | 神经网络普遍偏自信——它会在错误答案上给出 0.95 的概率。 早退正好放大了这个问题的危害:你是在模型最自信的时候相信它。 所以早退必须配置信度校准(拿验证样本拟合一个温度,把概率调到可信) | 模型偏自信、或输入是训练时没见过的分布 → 先校准;校准后仍不可信就别用早退 |
| 辅助出口本身有开销 | 每个出口都是一个小的分类头。虽然参数量不大,但它们要参与训练、 要占显存、而且会干扰主干(网络的主体层)的表示学习—— 网络被迫让中间层也具备分类能力,而不是纯粹地为后续层服务 | 层很窄、显存紧 → 少挂几个出口,或只在中间少数几层挂 |
| 大 batch 下收益被摊薄 | 批量推理时,即使 80% 的样本早退了,剩下的 20% 仍然要跑满。 而 GPU 是按最长的那条路径计时的—— 除非你批内分组(把已退出的样本从 batch 里换出去,空出槽位接新样本)。 这就是连续批处理要解决的问题(阶段 6) | 吞吐优先的在线服务 → 批内分组 / 连续批处理;否则早退只省纸面算力 |
| 训练更麻烦 | 多出口联合训练需要调各出口的损失权重。ACT 这类「自己学该想几步」的方法 尤其难训——它有个退化解:永远只算一步,然后在训练集上碰运气。 必须用正则项专门惩罚这种偷懒 | 想直接拿现成模型改 → 得重训;ACT 类还要加正则,防「永远只算一步」的退化解 |
真算 · 省下来的 FLOPs,为什么换不成墙钟时间
真算 · 辅助出口本身要占多少参数
不是早退。是级联(cascade)和投机解码。
原因很实际:它们不需要改模型结构。
· 级联:训一个小模型和一个大模型,先用小的答,置信度低再升级。
换人时大模型拿到的是原问题、从头算一遍——小模型已经说出口的中间状态不会传过去。
· 投机解码:小模型猜、大模型验,验证通过就一次接受多个 token。
两者都把「自适应」放在了模型外面的调度层,而不是塞进网络内部。
这样 GPU 仍然能高效并行,工程上也容易部署。
这是「算法上更优雅」和「工程上更可行」之间的一次典型妥协。
早退像让每个员工自己决定几点下班——理论上最高效,但你要给他们排班、
统计工时、还得处理协作问题。
级联像设两个岗位:初级客服先接,搞不定转高级——流程固定、好管理,
虽然不如前者精细,但落地成本低得多。
大公司几乎总是选后者。
回到第 3 节那张核心大图。先点「容易的样本」,阈值拖到 0.90—— 第一层出口就过了线,后面两层直接不跑。再点「难的样本」——它一路走到底,每一层都不够自信。 这两个按钮之间的差别,就是这一章的全部赌注:你得先相信「大部分样本长得像前者」, 早退才划得来;如果所有样本都像后者,早退一分钱都省不下。
| 它假设 | 什么时候不成立 |
|---|---|
| 大部分输入其实很简单(难度分布很偏) | 任务本身就很难且均匀(每一个输入都要想很久)。 这时平均退出层数会贴着最深层走,辅助出口纯属白烧显存 |
| 置信度高 ≈ 答对 | 神经网络普遍偏自信——它会在错答案上给 0.95(第 6 节第二行), 早退等于把「自信的错误」提前固化成最终答案 |
| 省下的算力能换成时间 | 在 GPU 上不成立。GPU 快的原因是一条指令同时作用在成千上万个数据上, 按最长的那条路径计时。80% 的样本早退了,那 20% 仍然要跑满,整批就得陪着等 |
| 暗线 | 这一章的回答 |
|---|---|
| A 信息流动 | 输入输出的形状没变,变的是「这一批数据走完的是不是一块矩形」: 固定计算量时是整齐的矩形,早退后变成参差不齐的长条,同一时刻大家不再做同一件事。 完整的硬件账写在《硬件与算力账本》里 |
| E 它假设了什么 | 两条缺一不可:① 输入的难度分布严重不均;② 置信度高的地方通常就是答对的地方。 第一条错了早退省不下任何算力,第二条错了它会把「自信的错误」留下来 |
| F 违背了哪个直觉 | 「省了 60% 算力」≠「快一倍多」——GPU 按最长的那条路径计时。 更反直觉的是:算法上更优雅的早退,输给了工程上更土的级联和投机解码 |
它接住了上一章的什么:《神经符号与可验证推理》刚问过 「想多久」能不能按题目难度分配,这一章接着问「走多少层」。 更早的《MoE 混合专家》只是旁证。
它给下一章留了什么:既然「算多少」可以跟着输入变, 那「记住什么、忘记什么」是不是也可以?《持续学习与遗忘》要问的就是这个问题。
固定计算量假设所有输入一样难,而事实不是:早退给中间层挂出口,用「所有出口损失之和」训练,
让容易的输入走浅、难的走深。
但省下的 FLOPs 换不成墙钟时间——动态控制流打散了 GPU 的批,
所以真正落地的是把自适应放在模型外面的级联和投机解码。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。
第 6 节的结论是:真正上线的是投机解码,不是早退。 它在代码里长什么样?