上一章的 Mamba 是去掉了注意力。这一章讲的是另一条路: 保留「每个词看向所有词」这个思想,但换一种算法去算它, 让复杂度从平方变成线性。这条路走了六年,直到 2025 年才第一次在公平比较下(同样的数据、参数量、训练设置)赢了全注意力。
| 对比项 | 高效注意力(阶段 6) | 线性注意力(本章) |
|---|---|---|
| 改的是什么 | 工程实现 | 数学结构 |
| 复杂度 | 仍然是 O(n²),只是常数变小、显存变少 | 真的变成 O(n) |
| 代表 | FlashAttention、PagedAttention | Linformer、Performer、RWKV、RetNet |
| 结果一样吗 | 完全一样,是精确的等价重写 | 不一定——多数方案是近似 |
| 能叠加吗 | 能,而且通常一起用。FlashAttention 优化的是「算得快不快」, 线性注意力优化的是「要算多少」。两者不在一个维度上 | |
FlashAttention 说:「该算的量不变,但我算得更聪明、更省显存。」
线性注意力说:「我要改掉算的方式,让要算的量本身就少一个数量级。」
互动 · 一句话的差别:显存随序列长度怎么长
注意力的公式是 softmax(QKᵀ)·V。这里有个绕不过去的障碍: 那个 n×n 的矩阵必须先算出来,因为 softmax 是在它上面做的。
但如果你把 softmax 换成一个核函数 φ(·)(也就是对 Q 和 K 分别做一次逐元素的非线性变换), 这个矩阵乘法就可以用结合律重新结合:
互动 · 挪一下括号,计算量差多少个数量级
这个「挪括号」不是技巧,是矩阵乘法结合律的普通应用。 两边的数学结果完全一样,只是乘法顺序不同——注意,这里比的是同一个 φ 下的两种括号顺序; 把 softmax 换成 φ 本身,才是收费的那一步(第 M 节细讲)。 把鼠标移到下面的符号上——对应的滑块会亮起来。
鼠标停在 n 上——上面第一个滑块会亮;停在 d 上——第二个滑块会亮。
然后把 n 拖到最大、d 拖到最小,看中间那个「倍数」读数会变成多少位数。
看清楚 n 和 d 在两次里的位置——它们刚好换了地方:
· 先算 QKᵀ:项里有一个 n²,所以 n 一长就平方地炸;
· 先算 KᵀV:项里只有 d²,n 是一次的。
而且那个中间结果只是一个 d × d 的矩阵,它和 n 完全无关。
两条式子相等的时候:n²d = nd² → n = d。
序列长度 n 大于模型维度 d 时,先把 KV 相乘更划算。
而实际的大模型里,n 常常是几万甚至几十万,d 只有几千——n 远远大于 d,所以线性注意力赢面很大。
但注意:这个「d×d 的中间结果」就是它全部的容量。这是它最大的优势,也是它最大的隐患(下一节讲)。
像算「每个学生和每个老师两两聊一遍」的总工作量。
先算 QKᵀ:先把所有两两组合都列出来(一张 n×n 的大表),再逐个处理——
表本身就占地方,而且做一次要 n² 次比较。
先算 KᵀV:先把所有老师的意见汇总成一份摘要(大小只和每个词的维度 d 有关,和词的个数 n 无关),
然后每个学生只读这份摘要。
摘要的大小是固定的——这就是它便宜的原因,也是它装不下所有细节的原因。
(类比管到「摘要大小固定」为止:真实的摘要是一个 d×d 的矩阵,不是一份文字。)
上面那个「d×d 的摘要」暴露了线性注意力最深的那个问题。
下面这个互动把它量化出来:用一个固定大小的状态去存 n 组键值对,然后试着取回来。
这不只是「模型层」的抽象问题:它直接决定了
互动 · 状态容量测试(写入与读取)
上面那张卡就是全部机制。写进去是一次外积——k ⊗ v
把「一个键」和「一个值」铺成一张 d×d 的表,再整个累加到状态上,成本是常数;
读回来是一次矩阵乘。
看清楚读回那一行:它把目标项和不相关项的权重写成了「键之间的相似度」——
kj · k 就是「第 j 格的字迹叠在目标格上的多少」。
只要那些键不是两两垂直,这个数就不为 0,干扰就是真实的。
顺便对比一下:这个 d × d 的 S,和《状态空间模型》那一章的
固定状态 h 是同一个东西——
两章做的是同一件事,只是「怎么把新信息写进去」不一样:
SSM 用递推(h ← Āh + B̄x),
线性注意力用外积(S ← S + k⊗v)。
看那个读回公式:你想要的只有 j = 目标那一项,但所有其它项都会以「键的相似度」为权重混进来。
键越不互相垂直,干扰越大。
当 n ≤ d 且键互相接近正交时,误差接近 0——能精确取回。
一旦 n 超过 d,键必然开始互相重叠,干扰急剧上升,取回的东西就不准了。
这不是实现问题,是固定维度状态的表示容量上限。注意力没有这个限制,因为它能随时回头看原文——
代价就是那个 n×n 的存储。而这个存储就是
像用一本固定 32 章的笔记本去记 100 条信息。
记到第 33 条时你没有新章了,只能把新内容挤进已经写过的章——
原来那章的字迹就被涂花了。
更麻烦的是取回的时候:你想查第 5 条,翻到那章,发现上面叠着第 47 条和第 92 条的字迹,
你没法确定哪一部分才是原来那条。
而全注意力相当于一个无限大的书架:每条信息单独占一个格子,永远不会互相涂花。
代价是你得为每个格子付租金——那就是 n×n 的存储。章数越多,租金涨得越快。
这一章从头到尾都在讲这笔租金值不值。
互动 · 把一个查询的读回拆开:哪一部分是它自己,哪一部分是别人叠上来的
前三节说的其实是同一件事的两种说法:把括号挪一下(第 2 节), 中间就会凭空多出一个 d×d 的盒子(第 3 节)。 下面这张图把它画出来——两条路算出来的东西一模一样,只是中间那个盒子的大小差了 (n/d)² 倍。
核心大图 · 同一个结果,两个大小完全不同的中间盒子
挪括号是恒等变换,一步近似都没有。上面两个输出矩阵逐格相同,
差的那一丁点是浮点误差(差异那一栏会显示成 1e-16 这种)。
真正收费的是下一步:把 softmax 换成核函数 φ。下一张图讲的就是这笔费用。
第一行是「写进去」,第二行是「读回来」。 公式里出现的每个符号,在图上、在滑块上都有对应的一块。
微型图解 · 为什么 n 一超过 d,就开始互相干扰
高维空间里,互相垂直的方向最多只有 d 个——所以一旦 n 超过 d,
键之间必然开始互相像,非对角线就再也压不下去。这就是容量上限的全部来历。
它和第 3 节那张误差曲线量的是同一件事:一个画的是起因(键重叠了),
一个画的是后果(取回来的东西错了)。
| 方案 | 用什么手段 | 核心思路 | 代价 |
|---|---|---|---|
| Linformer 2020 |
低秩投影 | 先假设 n×n 的注意力矩阵是低秩的(几百行里其实只有少数几个方向在起作用), 再用一次投影把键和值从长度 n 压到固定长度 r | 低秩假设不总成立;r 是固定超参 |
| Performer 2020 |
随机特征 | 用随机傅里叶特征(一圈随机抽的正弦、余弦,充当坐标)把 softmax 核近似成可拆的两半,从而能套结合律 | 近似有方差;要采足够多的特征才准 |
| Linear Transformer 2020 |
换核函数 | 干脆不用 softmax,直接用 elu(x)+1 当核函数 | 核变了,表达能力就和注意力不一样了 |
| RWKV 2023 |
时间混合 + 通道混合 | 把注意力换成两个模块:一个管跨时间(像 SSM),一个管跨通道。 推理时是 RNN,训练时可以并行 | 不是注意力的近似,是一个新架构 |
| RetNet 2023 |
衰减因子 | 给远距离的位置乘一个衰减,于是同一套参数支持三种算法: 并行(训练)、递归(推理)、分块(长序列) | 衰减是固定的,不能按内容调整 |
| Mamba 2023 |
状态压缩 | 见上一章。和线性注意力是对偶的——Mamba-2 证明了这一点 | 同「固定容量」的那个上限 |
| GLA / DeltaNet / Lightning Attention 2024-25 |
门控 / 增量规则 | 给状态加上可学习的门,或者用误差修正的方式写入 (新键进来时先减掉旧值再写新的) | 是目前在容量利用上做得最好的一类 |
三条路:n×n 这块地方,各自从哪里省掉
互动 · softmax 的「放大」是它压掉干扰的工具;换成核函数就没了
互动 · 另一条完全不同的路:把所有远距离的项按固定倍率压小
互动 · 换一种写入方式,容量利用率差多少(两条线都是真跑出来的)
点一下看每一步改了什么
| 类别 | 方法 | 核心那一行公式 | 今天的状态 |
|---|---|---|---|
| 低秩近似 | Linformer、Nyströmformer | K′ = E K E 把 n 个键压到 r 个的投影矩阵 |
基本被后续方案取代 |
| 核方法 | Performer、Linear Transformer | φ(Q) (φ(K)ᵀ V) | 理论上漂亮,但近似误差在长依赖任务上明显 |
| 递归架构 | RWKV、RetNet、HGRN | S_t = γ S_{t−1} + k_t v_tᵀ | 活跃。RWKV 有独立社区,RetNet 的思想被广泛借鉴 |
| 状态空间 | S4、Mamba、Mamba-2 | h_t = Ā h_{t−1} + B̄ x_t | 与线性注意力合流(SSD 对偶) |
| 门控线性注意力 | GLA、DeltaNet、Kimi Delta Attention | S_t = diag(α_t) S_{t−1} + k_t v_tᵀ diag = 对角矩阵;α_t 是每步「忘多少」的门控 |
目前最被看好的方向,容量利用率最高 |
| 混合架构 | Jamba、Zamba、MiniMax-01、Kimi Linear | 每 r 层留 1 层全注意力 | 实际部署的主流答案 |
| 代价 | 具体表现 | 什么时候真的会痛 → 换成什么 |
|---|---|---|
| ① 近似误差在长依赖上放大 | 短序列看不出差别,一到长序列,「取回某个具体信息」这类任务就露馅(第 3 节的容量测试就是它的量化) | 要精确检索(「大海捞针」、长推理链)→ 保留几层全注意力,别全换 |
| ② 表达能力和注意力不相等 | 换掉 softmax 就是换掉了一个函数类,理论上两者有表达力差距: 论文证明这类固定状态模型在「跟踪状态变化」这类任务上有计算能力上限 (The Illusion of State,ICML 2024) | 任务要做状态跟踪、形式语言 → 让带 softmax 的层兜底 |
| ③ 训练不如 FlashAttention 成熟 | 固定状态在序列上滚动,很难像分块注意力那样吃满 GPU,显存省了、算力利用率反而更低 | 序列不够长(n ≲ 几万)→ 先用 FlashAttention,线性不划算 |
| ④ 不能用现成的 KV Cache 基建 | 推理时状态是固定大小的,和「缓存所有历史 K、V」是两种模式,调度、批处理、投机解码都要重做 | 已有成熟推理栈要复用 → 混合架构(只换部分层) |
互动 · 既然乘法次数少,为什么没赢?把代价③ 量化出来
| 进展 | 具体做了什么 | 意义 |
|---|---|---|
| MiniMax-01 2025 年初 |
大部分层用 Lightning Attention(线性),每 8 层插一层完整的 softmax 注意力。 总参数 4560 亿,每次激活 459 亿,支持百万级上下文 | 第一次把线性注意力推到千亿参数的实际部署规模, 证明了混合方案能跑通 |
| Kimi Linear 2025 年底 |
混合线性注意力架构,用 Kimi Delta Attention + 多头潜在注意力(MLA:把长长的 K、V 压成一个短向量再缓存的写法), 在同样的数据、参数量、训练设置下第一次超过了完整的全注意力 | 这是一个标志性节点。在此之前,线性注意力的叙事一直是 "用一点质量换很多效率";这次是质量和效率同时占优 |
| 层选择的实证发现 | 有研究系统测试了哪些层可以换成线性注意力,结论是: 开头和结尾的层通常可以换,中间层必须保留 softmax 注意力 (Training-time Selection of Linear Vs. Softmax Attention) | 这解释了为什么"均匀的 1:7 混合"不是最优—— 该换哪一层,比换几层更重要 |
2020-2023 的叙事是「线性注意力取代注意力」,结果失败了——固定状态的容量上限是硬的。 2024 年 Mamba-2 的「状态空间对偶」把线性注意力和 SSM 打通成同一套数学。 2025 年之后叙事变成「编排:把合适的层换成线性,其余保留注意力」,这次成功了。
互动 · 「编排」到底省了多少:每一层要占多大缓存
| 章 | 关系 |
|---|---|
| 阶段 6 · 高效注意力 | 那条路线是工程优化(FlashAttention 分块、GQA 共享 KV、PagedAttention 管显存), 复杂度仍是 O(n²)。和本章的路线可以叠加 |
| 阶段 6 · 推理与 KV Cache | KV Cache 是注意力推理的必需品,它的大小随序列线性增长。 线性注意力把这个缓存换成了一个固定状态—— 这是它省显存的真正来源,也是它容量受限的根源 |
| 阶段 8 · 状态空间模型 Mamba | 上一章。Mamba-2 的 SSD 证明了这两者是同一回事, 所以这一章和上一章其实是同一枚硬币的两面 |
| 阶段 8 · 自适应计算 | 那边讲「按难度分配算力」,本章讲「按结构压低算力」, 两者都是在回答「怎么不浪费计算」 |
这一章在路线图上的位置
d × d 的摘要。两章压的是同一个东西:优势同一个来源,限制也同一个来源。
下一章《图神经网络》换个方向——讲「谁和谁相连」。
回到第 3 节那个「状态容量测试」,把第一个滑块「写进去的键值对数量 n」从 4 慢慢拖到 128。 盯住两个读数:全注意力的「权重缺口」基本不动,线性注意力的「重建误差」随 n 平滑上升, n 到 d 附近已经到 100% 量级。那个量级,就是「固定容量装不下原文」被量化出来的样子。
信息流动、牺牲、参数账本、反直觉四条,正文里都已经讲过,这里只留两条最有信息量的。
| 暗线 | 这一章的回答 |
|---|---|
| D 跑在什么上 | 推理时带宽受限,训练时看情况。 · 推理:全注意力要为每个 token 存 KV Cache 并反复读回,瓶颈是显存带宽; 线性注意力只需要维护一个 d×d 的状态,与 n 无关,带宽压力几乎是常数;· 训练:线性注意力的 KᵀV 是一个正规的矩阵乘,
能吃满 GPU 的矩阵单元,反而是优势——而那个 d×d
中间量小到能完全待在片上——见 《硬件与算力账本》。这就是它比 SSM 在训练侧更讨喜的原因:它的运算形状对硬件友好。 |
| E 它假设了什么 | 一个非常具体的假设:「注意力矩阵能被一个核函数近似」。 也就是把 softmax(q·k) 换成 φ(q)·φ(k)。
这不是恒等变换,是一个逼近。而 softmax 的那个指数放大效应(让大的更大、小的趋零) 正是它能把干扰项压下去的原因——换成多项式核就没了这个放大效应,干扰项全都冒出来。 所以「固定容量装不下」和「核函数不像 softmax」其实是同一个问题的两面。 |
把括号挪一下——softmax 挡着挪不动,换成核函数 φ 才能挪,中间那个 n×n 就变成与 n 无关的 d×d,
复杂度从 O(n²d) 降到 O(nd²),交叉点在 n = d。
但这个 d×d 就是全部容量:n 超过 d,键互相重叠,精确取回没了——这是固定维度状态的硬上限,不是调参能救的。
所以真正的答案是编排:少量全注意力层守住精确检索,其余换线性换吞吐。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。