让 Transformer 自己排层序:Library of Layers 论文精读
11 月 2 日提交的 Library of Layers 让路由器在推理时从层库里挑选并排序 transformer 块,用一个库大小参数同时覆盖稠密、循环深度与稀疏 MoE 三种形态。本文拆解它的架构、因果性难题、窗口注意力设计与实验证据。
程序员写算法,靠的是把同样的可复算子和循环、条件判断按不同顺序串起来。语言模型反过来:无论输入什么,几十层 transformer 永远按同一个顺序从头跑到尾,层序在架构设计那一刻就被写死了。
2026 年 11 月 2 日,Abdellah Rahmani、Sean McLeish、Ang Li、Sanae Lotfi、Pascal Frossard、Micah Goldblum 六人把一篇 32 页的论文放上 arXiv:《Library of Layers (LoL): Adaptively Ordering Transformer Layers at Runtime》。核心主张只有一句:让模型在推理时自己决定下一层执行哪一块,层序变成可学习的计算,而不是固定的结构。代码与预训练细节公开在 arXiv:2611.03526,实现见 github.com/arahmani1/library-of-layers。
固定层序的代价
论文的切入点是复用与浪费。一个训练好的 transformer 里,不同深度学到的东西并不均匀:浅层偏向词法与局部模式,深层偏向语义整合与长程推理。既然某些"计算原语"会在多个深度反复出现,那把它们在不同位置各自存一份参数,本质上是用参数换结构上的偷懒。
此前的研究沿两条路试图缓解这件事:
- MoE(混合专家):把 FFN 换成多个专家,每个 token 只走少数几个,用稀疏激活换容量。代表工作从 Shazeer 等人的稀疏门控专家层,到 Switch Transformer。
- 循环 / 循环深度模型:同一组层反复执行,把算力变成可以在推理时拧的旋钮。Huginn 就是这条路的最新示范——3.5B 参数、prelude-core-coda 三段式,循环块在训练中随机采样执行次数,从而学会适应任意循环数(arXiv:2502.05171)。
- 动态跳层:按输入跳过某些层,如 Mixture-of-Depths 一类做法。
但论文指出,这三类方法都保留了一个隐含前提:层的执行顺序仍然固定。可以少走几层,可以让同一层多跑几遍,可以从多个专家里挑,但"第 3 层永远在第 4 层之前"。LoL 要动的正是这条。
三段式结构:固定头尾,中间可路由
LoL 沿用循环模型的骨架,把网络切成三部分:
- prelude:固定顺序的解码器层,全序列因果注意力,负责把 token 映射进隐空间。
- routed core:核心区,包含一个容量为
L的块库{E_1, ..., E_L},每次前向从库里按序挑选D块执行。 - coda:固定顺序的解码器层,负责解码输出。
这里有两个必须分清的计数:库大小 L 是"存了多少个不同的块",路由深度 D 是"执行了多少次块应用"。论文把每个库块叫 expert,每次应用叫 routed depth,把某一串具体选择叫 routing path。例如 L=3、D=3 时,E_1 → E_3 → E_1 就是一条复用了某个块、又完全没用另一个块的路由路径。
关键的巧思在于:L 和 D 是两个独立的旋钮,而它们的相对大小直接决定了模型落在哪个架构家族里。
L很小、D很大:块必须被反复复用,退化成循环 transformer(Huginn 那种形态)。L很大、D不变:大部分块在某次前向里根本不参与,退化成稀疏 MoE。L = D:每个深度用不同的块,接近稠密堆叠。
也就是说,稠密、循环深度、稀疏 MoE 三种形态被收进同一个参数族,切换只需要改一个数字。论文认为这是它相比前作最本质的贡献——不是新造一种架构,而是指出这三种架构其实是同一个连续谱上的取值。
因果性难题与跨步窗口注意力
真正棘手的地方不在"怎么选",而在"选完之后注意力怎么算"。
如果允许每个 token 位置独立选择层序,那么某个 token 在第 ℓ 个路由深度被某块处理出来的向量,做注意力时会遇到前序位置在另一块、另一组 Q/K/V 投影下算出来的向量。论文明确写了实测结果:这种 Q-K 不匹配会让训练不稳定,性能明显变差。
反方向的极端同样不行。给整个上下文只选一条层序,因果性自然保住了,但决策只能基于第一个 token 或 prompt——后面涌现的信息全被浪费,路由退化成一种昂贵的常量。
论文的解法是按窗口路由 + 跨深度错位窗口(strided window attention)。做法有三层:
- 在每个路由深度,把序列切成长度为
W的窗口,同一窗口内所有 token 共享同一个 expert 和同一组路由权重,注意力限制在窗口内部、保持因果。这样 Q-K 永远来自同一组投影,不匹配问题消失。 - 窗口边界每个深度错开
S个位置。第ℓ个深度的偏移量是delta_ℓ = (ℓ-1) * S mod W。位置i属于哪个窗口由w_i^(ℓ) = floor((i + delta_ℓ) / W)给出。 - 错位让相邻深度的窗口互相重叠,信息得以跨窗口流动,等效于随深度增长的视野——和滑动窗口注意力逐层扩大感受野是一个道理。
论文给的例子很直观:序列长度 n=8、W=4、S=2 时,深度 1 切出 {0..3} 和 {4..7};深度 2 切出 {0,1}、{2..5}、{6,7};深度 3 回到第一种切法。第 5 个 token 在深度 1 是新区间的第一个位置,到深度 2 就能看见第 3、4 个 token。prelude 和 coda 则恢复全序列因果注意力。
路由器:一个线性层,只看前面
路由器本身刻意做得极简——一个线性层,因为太复杂会吃掉架构节省下来的收益。
输入怎么取是关键。为保证因果性,选第 k 个窗口的 expert 时,只能看 0 ≤ j < k 的窗口;具体是把这些窗口各自的隐状态均值再取均值,喂给线性层。第一个窗口没有前驱,就输入一个可学习的、随深度变化的向量 e^(ℓ) 与首 token 隐状态的均值。
训练上有三处工程细节值得记:
- 负载均衡:采用 loss-free 的均衡策略,不给总损失加辅助项,避免把负载均衡的代价和语言建模目标混在一起。
- 残差缩放:被选中块的残差更新按其路由概率缩放,梯度因此可以沿路由概率回传到路由器。
- 探索噪声:softmax 前给路由 logits 加高斯噪声,鼓励训练早期多试不同路径,思路沿自 Shazeer 等人的 MoE 论文。
此外,每块内的归一化之后用 FiLM 注入随深度变化的缩放与偏置,让同一组参数在不同深度仍能表现出差异——否则一个块在深度 3 和深度 15 执行起来完全无差别,路由的意义就被削弱了。
相比 MoE 的逐 token 路由,LoL 的按窗口路由得到的是更粗粒度的训练信号:一整个窗口的 token 共享一次路由决策,梯度在决策上聚合,而不是每个 token 各投一票。
让训练便宜一点:growing
训练成本主要由路由深度 D 决定,这一点很残酷:D 小则便宜但模型浅、效果差;D 大则效果好但每一步都贵。
LoL 采用渐进加深(growing):先用浅核心训练,再在训练过程中逐步加大 D,把大部分算力花在较浅的模型上,最后得到一个用于部署的深层模型。这么做还有个副作用是好的——早期深度小,路由器试探不同 expert 的成本低,探索更充分。这与循环模型"训练时逐步增加循环次数"、以及渐进堆叠(progressive stacking)是同一思路。
1B 规模的实验里用的是 1-sqrt 调度,覆盖 75% 的训练过程。
实验:路径可读,也可被操纵
论文最引人注意的不是性能,而是"路由路径"这个人造物居然可解释、可干预。
语言按路径聚类
用 360M 参数模型、4 层 prelude + 4 层 coda + 16 深度核心,在 FineWeb-2 的 10 种语言等量混合语料上训 10B token。取验证集,把每个窗口在每个深度选中的 expert 编码成 one-hot 并拼接,做 PCA 降到二维:路径按语言分开,拉丁字母语言彼此靠近。言下之意是——同一批层,只是执行顺序不同,就构成了不同语言的计算路径。
迷宫与数独:层序即算法
迷宫实验最能说明问题。8×8 无环迷宫上用五种算法求解:BFS、DFS、A*、双向搜索、死胡同填充。五种算法输出的轨迹语法完全一样,都是一串访问过的格子,唯一的区别是访问顺序。如果模型能把"层序"学成"算法",那么改变层序就该改变访问顺序。
论文的做法是:训练时把策略信息只给路由器,然后对每种策略提取"众数路径"(mode path,指每个位置取平均路由概率最高的 expert,并固定其残差权重);推理时把策略描述替换成中性填充符,强制模型走对应路径。结果强制哪条路径,模型就以接近 100% 的准确率执行对应算法。
数独同理,五种解题策略各有自己的步骤语法;强制众数路径后,模型的策略识别准确率同样接近 100%。反过来,不用强制路径、只在上下文里给策略描述 token,模型也能以接近 100% 的准确率解出未见过的新棋盘。
路由概率里藏着安全信号
用 FineWeb 序列上已有的 harmfulness 评分,把 0 分当安全、4 到 5 分当不安全,等量混合后训 10B token,训练过程中不提供任何标签。之后在路由概率上拟合一个线性 ridge 回归:
- 窗口级探针,留出集 AUROC 0.92;
- 序列级探针(跨窗口取平均),AUROC 0.95。
标签打乱作为对照则退到随机水平。这说明不安全文本在模型内部确实走了不同的计算路径,而这种差异可以在不对路由器做任何监督的情况下线性读出。当然,能读出和能控制是两件事,论文在讨论里也承认,这类干预能否迁移到对话场景里的撒谎、算计行为,仍是未解问题。
性能:不吃亏,但也没赢
1B 参数、16 层结构(4 层 prelude + 8 深度核心 + 4 层 coda),Nemotron 与 OpenMath 混合数据,约 90 ExaFLOPs 的等算力预算,全部指标落在两个标准误以内:
| 模型 | ARC-E | ARC-C | HellaSwag | PIQA | GSM8K |
|---|---|---|---|---|---|
| Vanilla(全注意力) | 40.8 | 28.2 | 31.4 | 56.6 | 29.7 |
| Vanilla(滑动窗口) | 49.5 | 28.5 | 31.3 | 58.8 | 27.5 |
| LoL | 50.3 | 29.1 | 31.2 | 59.7 | 27.9 |
唯一显著的差别是全注意力的 vanilla 模型在 ARC-Easy 上掉到了 40.8,而 LoL 与滑动窗口版本都在 50 附近;GSM8K 上 LoL 略低于两个基线,27.9 对 29.7 与 27.5。作者的说法是"competitive",不是"better"——这点值得尊重,也没必要替它吹。
库大小的扫描更有信息量。360M 规模、至少 6 个学习率、Muon 与 AdamW 分别调参:
- 对照循环模型:把 LoL 的库大小固定成 Huginn 循环块的大小,10B token FineWeb,loss 持平,但 LoL 的种子间方差更大——作者归因于路由器初始化导致不同种子的探索路径不同。
- 对照稀疏 MoE:3:2 稀疏度(MoE 每层 3 专家 2 激活,LoL 用 24 专家跨 16 路由深度),约 10 ExaFLOPs。MoE 的 loss 约 2.75,LoL 约 2.8,差 0.05。
这 0.05 的差距,作者并不回避,只是提醒:在潜空间推理类模型里,交叉熵略高而下游表现很强的情况并不罕见。
离生产还有多远
论文自己在讨论部分写得很克制:"这是对动态层序的初步探索,我们相信后续工作会大幅改进这个设计。"
现实约束至少有三条:
- 规模。全部实验在 360M 与 1B 两个量级,没有万亿级 token 的大规模验证。路由带来的训练不稳定性在小模型上可以调参糊过去,放大之后是否仍然成立,未知。
- 推理系统的适配成本。按窗口、按深度动态选块的执行方式,对算子融合、KV cache 布局、批处理都是新问题。这不是论文要解决的问题,但它是落地时必须解决的问题。
- 方差。同样的配置换随机种子,路径就变,最终 loss 也随之浮动。可解释性在这里是双刃剑:路径可读,也意味着结果对初始化更敏感。
真正的意义
LoL 的价值不在于它比谁强几分。它的价值是把三个曾被当作不同家族的东西摆到同一张谱系图上:稠密堆叠、循环深度、稀疏 MoE,只是"库有多大、执行多深"这两个数字在不同位置的取值。一个参数切换架构形态,这件事本身就重构了我们对"模型结构"这个概念的理解边界。
更远一点,论文讨论了两个方向。其一是测试时扩展:推理深度可以超过训练深度,架构上已经预留了这道门。其二是可控性——如果换一条路由路径就能换一种解题策略,那么未来的对齐工作也许不必改权重,而是改路径。
当模型开始自己拼装计算图,"架构"就不再是一个固定不变的东西了。
参考资料
- Rahmani, McLeish, Li, Lotfi, Frossard, Goldblum. Library of Layers (LoL): Adaptively Ordering Transformer Layers at Runtime. arXiv:2611.03526v1,2026-11-02。https://arxiv.org/abs/2611.03526
- 论文 HTML 全文:https://arxiv.org/html/2611.03526v1
- 代码:https://github.com/arahmani1/library-of-layers
- Geiping 等. Scaling up Test-Time Compute with Latent Reasoning: A Recurrent Depth Approach(Huginn)。arXiv:2502.05171。https://arxiv.org/abs/2502.05171
(内容由AI生成,仅供参考)