班上要办读书分享会。最开始只有 4 个人,大家两两凑对聊心得,一共 6 次对话就聊完了。后来老师把全班 40 人都加进来,按“每个人跟其他 39 人单独聊”的规矩,需要 780 次对话——一节课根本聊不完,教室里吵成一团。这时候班长站出来说:“大家别两两聊了,把心得都报给我,我整理成一份纪要,再统一发给每个人。”40 个人只需约 80 次沟通,信息还都传达到了。这个“两两对话 → 汇总分发”的思路,正是大模型处理超长文本的关键——线性注意力(Linear Attention)。 Transformer 的自注意力机制就像那场“两两对话”:序列里有 n 个词,每个词都要和另外 n−1 个词计算关联,总计算量随 n 呈平方级爆炸。而线性注意力通过改写计算公式,把复杂度从 O(n²) 压到 O(n),让长文本、长上下文不再被算力和显存卡死。这篇文章带你从一场分享会,看懂线性注意力的原理、代价和应用。
学懂线性注意力,等于拿到长上下文时代的“效率钥匙”——无论是超长文档问答、流式大模型推理,还是端侧设备部署,你都能一眼看穿该用哪把刀。
可视化演示
展示标准注意力到线性注意力的公式改写、核函数分解与softmax近似、O(n²)到O(n)复杂度对比,切换模式理解长序列优化核心原理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
标准注意力到线性注意力改写 标准注意力 softmax(QK^T)V 需先计算n×n注意力矩阵,内存和计算复杂度均为O(n²) 线性注意力利用结合律改写为 φ(Q)(φ(K)^T V),先算φ(K)^T V(d×d)再乘φ(Q),复杂度降为O(nd²) softmax(QK^T)V → φ(Q)(φ(K)^T V) | O(n²) → O(n) 公式改写通过计算顺序调整实现复杂度从平方到线性的飞跃
注意力瓶颈
读书会人一多,教室里就乱了:40 个人如果坚持“每两人私下聊一次”,需要 780 次对话,一上午都聊不完。更可怕的是,人数翻倍后,对话次数不是翻倍而是翻四倍——8 个人的分享会只要 28 次对话,16 人就要 120 次。这就是平方增长的威力:随着人数 n 增大,两两配对的次数按 n(n−1)/2 爆炸。
Transformer 的自注意力机制正是这样一场“全员两两对话”。每个词(token)都要和序列里其他所有词计算关联分数,形成一个 n×n 的关联矩阵。当处理一篇 10 万 token 的文档时,光这个矩阵就有 100 亿个元素,算不过来,更存不下。这就是长序列任务的“注意力瓶颈”:计算复杂度和显存开销都被平方项卡死。
用公式看,标准自注意力是这样算的:
整体复杂度可以记为:
回到读书会:既然两两对话是祸根,那就别两两聊了。班长的“汇总分发”方案,本质是把每个人都参与的“穷举对话”,改造成“一收一发”的线性流程——这正是打破注意力瓶颈的直觉起点。
- n² 项n×n 的关联矩阵,序列一长立刻失控。
- 乘 d矩阵乘法的特征维度开销,让 n² 项雪上加霜。
- 优化目标想办法把 n² 换成 n,让 d² 项成为主导——这就是线性注意力的使命。
线性化原理
班长的方案要落地,得先定一套“报数规则”:每个人都必须把自己的“标签”和“内容”写成一张卡片交给班长。卡片格式统一了,班长才能快速归类。但原来的两两对话有个特殊习惯——softmax 必须知道全班所有人的分数才能归一化,这就好比每个人要等所有人都报完数才能决定自己和谁多聊几句,根本没法拆开单独处理。
线性注意力的聪明之处,是换掉这套“必须看全集”的规则:用核函数 φ 替代 softmax。规则变成:每个人先把 Q 和 K 都做一次“投影”,变成新的档案。由于投影后的亲和分数可以直接拆成“φ(Q_i) 点乘 φ(K_j)”两个独立因子的乘积,班长就可以先把所有人的“标签内容”汇总起来,再统一回答提问——不再需要等全局归一一遍。
核函数版线性注意力的单点公式是:
这个改写最大的红利:亲和分数是“两个独立投影向量”的内积,于是求和符号可以重新组合——班长可以先收卡片、后发纪要,彻底摆脱“两两对话”的平方命运。
- φ(Q_i) 查询档案把“我想问什么”投影成高维提问向量,等价于把相同意图的提问拉近。
- φ(K_j) 键档案把“我是谁/我有什么标签”投影成键向量,保证非负,模拟 softmax 权重的非负性。
- 内积亲和分提问档案点和键档案点,算出两者“聊得来”的分数。
- 分子聚合内容按亲和分给每个回答者加权,把内容 V_j 汇总。
- 分母归一化把亲和分总和除回去,让输出尺度稳定,发挥 softmax 分母的作用。
结合律重排
为什么换了核函数就能省下数量级的计算?玄机在矩阵乘法的结合律。原来的计算公式里,φ(Q)φ(K)^⊤ 要先乘出一个 n×n 的“亲和大表”,再右乘 V;但结合律允许我们先算后面的乘积。
这就好比班长收到 40 张卡片后,不必先做一张“谁和谁聊得来”的 40×40 对照表,而是先把所有卡片按标签归好类、把同一标签下的内容揉成一个“分类要点册”(KᵀV),等有人提问时,直接查册子、取要点。前者要建 1600 格的大表,后者只需要一本不到 100 页的小册子——数据规模完全不同。
数学上就是这么一节结合律的事:
这就像班长把“逐人核对”优化成“提前归档”:40 个人时还不觉得,4000 人时对照表要建 1600 万格,而小册子始终只有几百页。结合律这一下,把长序列从“不可算出”拉回了“小菜一碟”。
- 左边先算亲和矩阵:φ(Q)φ(K)^⊤ 得到一个 n×n 矩阵,这就是那个巨大的“两两对话记录本”。
- 结合律换括号矩阵乘法满足 (AB)C = A(BC),括号怎么加都不改变最终结果。
- 右边先聚合 KᵀV:φ(K)^⊤ 先和 V 相乘,得到形状为 d×d 的“分类要点册”,与序列长度 n 彻底解耦。
- 复杂度降阶从依赖 n² 变成依赖 d²,只要 d 远小于 n,计算量就从“平方”跌落成“线性”。
内存优化
分享会开到一半,最大的烦恼不是聊天次数,而是笔记本不够用。两两对话模式下,班长要记下每个人和每个人的聊天记录——40 人就有 780 段记录,4000 人得 800 万段,笔记本堆成山。这就是标准注意力的显存危机:光是 n×n 的关联矩阵,就把显存吃干抹净。
线性注意力因为先算 KᵀV,历史信息被压缩成一个固定的 d×d 小册子,不再需要保存任何随序列长度增长的关联矩阵。4000 人的分享会和 40 人的分享会,班长手里的册子一样厚——册子的尺寸只由“卡片标签的种类 d”决定,和来多少人无关。
显存开销的对比一目了然:
显存从“平方”变“线性”,直接后果是:以前塞不进显存的一整本小说、一整份证监会招股书,现在可以完整喂给模型了。这就像班长终于把堆成山的笔记本换成了一本薄薄的归档册——长文档场景从此“放得下”。
- n² 关联矩阵亲和分数表占用的显存,这是最大的无底洞。
- n d 的 Q/K/V序列本身带来的矩阵,尚可接受。
- 线性注意力的状态KᵀV 聚合后只有 d×d,此外只多一层核变换,没有额外平方项。
精度权衡
天下没有免费的效率。纪要再详细,也丢掉了现场的语气、表情、即兴追问——信息被压缩必有损耗。线性注意力也一样:核函数只是“近似”模拟 softmax 的权重分布,而不是精确复刻它。
两个关键损耗点:一是核近似误差——φ 是手工设计的(比如 ELU+1、余弦相似度),它和指数函数 softmax 并非完全等价,注意力分布会走样;二是信息压缩——KᵀV 把所有历史揉成一个 d×d 的状态矩阵,相当于班长把 4000 人的心得压成 100 页的册子,细节注定被抹平。很多论文报告,在线性注意力下,模型在长距离依赖的 recall 任务上精度会下降几个点到十几个点。
误差可以写成:
那怎么取舍?答案是按任务挑核函数:任务对长程检索要求高,用更强的核(比如随机特征近似 softmax);任务只需要“大体上记得住”,用简单的 ELU+1 核就够快。精度不是免费的,但也不是只能全有或全无——班长可以决定纪要写多细。
- softmax 权重矩阵标准注意力理想的亲和权重,是我们要逼近的“金标准”。
- 核近似权重φ(Q)φ(K)^⊤ 归一化后得到的近似权重。
- 范数度量用矩阵范数衡量两者的差距,差距越大,精度损失越明显。
稀疏配合
班长很快发现,纪要虽好,但总有些“重点人物”值得单独深聊——比如作者本人、关键数据页。这就是稀疏注意力的思路:与其和所有人泛泛而谈,不如挑几个重点对象细细聊,其余人看纪要。线性注意力负责“全局粗粒度概览”,稀疏注意力负责“局部细粒度精读”,两者恰好互补。
实践中常见的混合架构:一部分注意力头用局部窗口(只看左右 r 个邻居,捕捉相邻词的细粒度关系),另一部分用全局锚点(随机采样少数全局位置,或者放几个固定的“全局 token”),再配合一路线性注意力兜底,保证每条信息都不被彻底漏掉。这样拼起来,计算量依然可控:
这就像分享会的最终形态:重点人物单独约谈,普通心得看纪要,既不遗漏关键细节,又不被全员对话拖垮。稀疏与线性不是二选一的对手,而是可以并肩作战的搭档。
- 窗口注意力 n·r每个 token 只和 r 个邻居计算注意力,r 是固定的小常数,不随 n 膨胀。
- 线性注意力 n·d²KV 聚合与分发的主体开销,随长度线性增长。
- 两路互补相加局部精读 + 全局概览,各自承担不同的信息粒度的捕捉职责。
位置保留
班长把纪要发下去,大家傻眼了:册子里的条目没有编号,谁先发言、谁后发言全乱了——“张三说反对”和“张三说支持”如果顺序颠倒,意思完全不同。注意力本身不感知顺序:无论是标准注意力还是线性注意力,计算时都把序列当成了“一袋子词”。
标准注意力之所以还能理解语序,是因为输入早就叠加了位置编码。线性注意力同样必须在核变换或分数计算中注入位置信息,否则模型就是个“词袋”。目前主流方案有两类:RoPE(旋转位置编码),把位置信息编码成向量的旋转角度;ALiBi(注意力线性偏置),直接给亲和分数加上与距离成正比的惩罚项,让模型天然更关注近邻。
RoPE 的核心操作是二维旋转:
回到分享会:有了编号的纪要才是好纪要。位置编码就是那串“编号”,虽然不参与内容的语义,但没有它,整本纪要就是一团乱麻——任何注意力变体都别忘了这一环。
- 旋转矩阵 R2×2 的旋转矩阵,作用是把向量旋转一个角度。
- 旋转角度与位置成正比位置 m 越靠后,旋转角度越大,位置信息就烙在了向量方向上。
- 内积蕴含相对位置旋转后的两个向量做点积,结果只取决于两者的位置差,从而把“相对顺序”注入注意力分数。
实战选型
现在你手里有三套交流方式:全员两两对话(标准注意力)、记录员汇总分发(线性注意力)、重点约谈+纪要(稀疏+线性混合)。问题是——什么场合用哪一套?
标准注意力精度高,但序列一长就爆算力爆显存;线性注意力效率高,但会丢细节;稀疏注意力补上了细节,却可能漏掉全局长程依赖。工程上的黄金法则是看 n 和 d 的关系:当序列长度 n 远大于特征维度 d 时,线性注意力的优势碾压级地体现出来;当 n 和 d 差不多甚至 n 更小时,标准注意力反而更划算。
做一个复杂度对照:
读书会的道理放在工程里一样成立:小沙龙(短文本)直接围炉夜谈,几千人的大会(超长文档)必须请班长做纪要,重要的报告再单独约谈。看懂复杂度,你就掌握了选型的直觉——在效率与精度之间,永远有第三条混合的路。
- n 远大于 d 时标准注意力的 n² 项压制一切,必须上线性注意力或混合架构。
- n 较小时平方项吃不下多少资源,标准注意力的精度优势更值得保留。
- 折中方案局部窗口 + 全局锚点 + 线性兜底,用混合成本换取精度与效率的平衡。
AI 应用场景
超长文档问答
阶段:长序列推理优化
解决的问题:律师审一份 50 万 token 的招股书,标准注意力要算 250 亿个关联分数,显存直接爆掉;线性注意力把历史压缩成 d×d 状态,整份文档可以一次读完。
具体案例:某法律科技公司将线性注意力层嵌入文档问答模型后,用户上传整本 IPO 招股书,90 秒内得到回答:“该公司的核心风险集中在应收账款周转率持续下降,涉及金额约 3.2 亿元。”过去需要分段处理、丢失跨章节关联,如今全程在线。
流式大模型推理
阶段:增量解码优化
解决的问题:ChatGPT 类应用每生成一个新 token,都要重新计算它和所有历史 token 的注意力,历史上算过的东西又得重算一遍;线性注意力把 KV 缓存压缩成固定的 d×d 状态,每来一个新 token 只做一次增量更新,推理时延大幅下降。
具体案例:某对话模型的推理服务从标准注意力切换到线性注意力后,长对话的平均首 token 延迟从 800ms 降到 120ms,显存占用变为恒定值,不再随对话轮数上涨。
端侧离线朗读
阶段:模型压缩与边缘部署
解决的问题:手机、车载设备显存只有几个 GB,标准注意力跑不动长文章;线性注意力用固定状态换取全局长程信息,低端设备也能流畅朗读整本小说。
具体案例:某阅读 App 的离线 TTS 前端接入线性注意力编码器后,在 2GB 内存的入门手机上,能将 5 万字文章一次性编码,朗读流畅度提升 40%。
Python 演示
import timeimport numpy as np def elu_plus_one(x): # ELU(x)+1 核函数:保证输出为正,模拟 softmax 权重的非负性 return np.where(x > 0, x + 1.0, np.exp(x)) def softmax_attention(Q, K, V): # 标准自注意力:O(n^2 d),先算 n×n 亲和矩阵再乘 V scores = Q @ K.T / np.sqrt(Q.shape[-1]) weights = np.exp(scores - scores.max(axis=-1, keepdims=True)) weights /= weights.sum(axis=-1, keepdims=True) return weights @ V def linear_attention(Q, K, V): # 线性注意力:O(n d^2),利用结合律先算 K^T V Q_phi = elu_plus_one(Q) K_phi = elu_plus_one(K) KV = K_phi.T @ V # (d, d),与序列长度 n 无关 out = Q_phi @ KV # (n, d) denom = Q_phi @ K_phi.sum(axis=0) # (n,) return out / denom[:, None] def compare_complexity(): d = 16 print(f"{'n':>6} {'softmax(s)':>12} {'linear(s)':>12}") for n in [64, 128, 256, 512, 1024]: rng = np.random.default_rng(n) Q = rng.normal(size=(n, d)) K = rng.normal(size=(n, d)) V = rng.normal(size=(n, d)) t0 = time.perf_counter() softmax_attention(Q, K, V) t1 = time.perf_counter() t2 = time.perf_counter() linear_attention(Q, K, V) t3 = time.perf_counter() print(f"{n:6d} {t1 - t0:12.4f} {t3 - t2:12.4f}") if __name__ == '__main__': compare_complexity()
elu_plus_one(x)实现 ELU+1 核函数,把 Q/K 映射为非负向量,替代 softmax 保证权重非负。scores = Q @ K.T / np.sqrt(Q.shape[-1])标准注意力先算所有两两亲和分数,形成 n×n 矩阵,这正是平方复杂度的根源。weights = np.exp(scores - scores.max(...))用减最大值技巧做数值稳定的 softmax。KV = K_phi.T @ V线性注意力的灵魂:先让 K 与 V 聚合,得到一个 d×d 的小矩阵,从此与序列长度无关。out = Q_phi @ KV查询矩阵直接查“分类要点册”,一次矩阵乘法完成所有位置的分发。denom = Q_phi @ K_phi.sum(axis=0)计算归一化分母,等价于公式中的 φ(Q) 对全量 φ(K) 的加权和。compare_complexity()在同一台机器上跑出两种算法的耗时表,n 越大、线性优势越明显。
常见误区
误区“矩阵乘法有结合律,先算 KᵀV 还是先算 QKᵀ,结果应该一模一样吧?那线性注意力不就是个纯工程优化吗?”
正解结合律保证的是在“同一个亲和函数”下结果一致,但线性注意力还偷偷换了亲和函数——用核函数 φ 的线性点积近似 softmax 的指数函数。φ 是近似而不是恒等,所以最终权重分布并不等于 softmax 注意力,精度会有损耗。
为何常见:教材上只画了 (QKᵀ)V = Q(KᵀV) 的等式,初学者很容易忽略等式两边的 Q/K 已经穿上了核函数的“马甲”。
误区“既然是 O(n) 对 O(n²),那长文本无脑换线性注意力就行了,肯定快一个数量级。”
正解线性注意力的真实复杂度是 O(nd²),核变换和归一化也有额外常数开销。当 n 不够大(比如 n 只有几百、d 却是上千),nd² 反而可能超过 n²d。一般要 n 比 d 大一个量级以上,线性优势才真正显现;短序列场景用标准注意力往往更划算。
为何常见:只盯着渐进复杂度的大 O 记号,忽略了常数因子和 d² 项的影响——大 O 描述的是趋势,不是具体机器上的绝对耗时。
误区“KᵀV 把历史都存进状态里了,状态是有序的,位置信息应该天然保留吧?”
正解KᵀV 的本质是对所有位置做求和,求和天然不区分先后顺序——丢给它的是一条条“卡片”,卡片上并没有编号。想让模型知道“谁先谁后”,必须显式注入位置编码,比如 RoPE 旋转编码或 ALiBi 偏置,否则长文本的语序信息会全部丢失。
为何常见:“状态”这个词给人“按顺序存储”的错觉,实际上它只是一个无序的统计量,和 RNN 循环更新的状态是两码事。
误区“稀疏注意力也是把复杂度降到线性,那直接用稀疏注意力就行了,还要线性注意力干嘛?”
正解稀疏注意力只对局部窗口或采样位置计算注意力,远处的“非采样位置”之间存在信息盲区,长程依赖会漏;线性注意力虽然做了信息压缩,但理论上每个位置都参与了全局聚合,不漏任何 token。二者一个重细节、一个重覆盖,工程上往往叠加使用。
为何常见:两者常被并列在“高效注意力”分类下,让人误以为它们是功能等同的替代品,实际上互补性远大于替代性。
面试题
Q1. 标准自注意力的计算复杂度是什么?
- A.线性增长,与序列长度成正比
- B.平方增长,n×n 两两配对← 正确答案
- C.对数线性增长,n log n 量级
- D.立方增长,n×n×n 量级
答案:B。标准自注意力要为每个 token 计算它和所有 token 的亲和分数,形成 n×n 关联矩阵,再乘以维度 d,复杂度为 O(n²d)。选项 B 正确;A 是线性注意力的目标,C 是某些稀疏/近似方法的复杂度,D 夸大了实际开销。
Q2. 线性注意力能把复杂度降为线性的关键操作是什么?
- A.缩小词典大小,减少词表维度
- B.用核函数改写点积,并利用结合律先算 KᵀV← 正确答案
- C.把句子切块,各块独立计算注意力
- D.用稀疏矩阵只保存非零的亲和分数
答案:B。线性注意力把 softmax 换成核函数 φ,使亲和分数可分解,再通过结合律把 (φ(Q)φ(K)ᵀ)V 重排成 φ(Q)(φ(K)ᵀV),避免了 n×n 矩阵。B 正确;A 与序列长度无关,C 是分块近似,D 是稀疏注意力思路。
Q3. 核函数 φ 在线性注意力中的核心作用是什么?
- A.把特征维度从 d 压缩到 1,省显存
- B.让亲和分数保持非负,替代 softmax 的归一化性质← 正确答案
- C.为每个 token 增加一个可学习的偏置项
- D.对梯度做裁剪,防止训练时梯度爆炸
答案:B。softmax 保证注意力权重非负且和为 1。线性注意力去掉 softmax 后,靠 φ 将 Q/K 映射到非负空间,保证“亲和分数非负”,再用分母归一化模拟“和为 1”。B 正确;A 是维度变换但与核函数定位不符,C、D 是训练技巧。
Q4. 线性注意力中 KᵀV 聚合完成后,矩阵的形状是什么?
- A.n×n,随序列长度平方增长
- B.n×d,随序列长度线性增长
- C.d×d,与序列长度 n 无关← 正确答案
- D.d×n,是亲和矩阵的转置
答案:C。K 的形状是 n×d,转置后是 d×n,乘以 V(n×d)得到 d×d。这个矩阵相当于“每个标签对应的内容摘要”,是固定大小的状态,不随 n 变化,这正是线性注意力省内存的关键。
Q5. 线性注意力中归一化分母的作用是什么?
- A.防止矩阵乘法溢出,提高数值稳定性
- B.让每行权重之和为 1,模拟 softmax 的归一化← 正确答案
- C.把输出维度对齐到词表大小
- D.加速 KᵀV 的矩阵乘法
答案:B。线性注意力用 φ(Q)ᵀφ(K) 替代 softmax 后,权重总和不再是 1,会导致输出尺度随序列长度变化。分母将所有亲和分累加并除回去,等价于 softmax 的归一化因子,让加权权重重新“和为 1”。
Q6. 线性注意力相比标准注意力的主要缺点有哪些?
- A.核函数近似导致亲和分数有偏差← 正确答案
- B.完全无法处理长度超过 1000 的序列
- C.历史信息被压进 d×d 状态,细粒度细节被抹平← 正确答案
- D.训练时无法并行计算
答案:AC。核函数只是 softmax 的近似,分布有偏差;KᵀV 把所有位置的信息求和压缩,单个词的细节必然丢失。B 错误,线性注意力恰恰擅长长序列;D 错误,线性注意力的矩阵乘法也可以高度并行。
Q7. 以下哪些场景更适合使用线性注意力?
- A.一次性读完整本 20 万 token 的小说← 正确答案
- B.20 词以内的短句翻译
- C.手机端离线朗读整篇长文章← 正确答案
- D.32×32 小图的图像分类
答案:AC。线性注意力在 n ≫ d 时优势最大,长文档和端侧长文本场景正合适;短句和小图上 n 很小,标准注意力精度更高,线性注意力的 d² 项反而吃亏。
Q8. 稀疏注意力和线性注意力在混合架构中的关系是什么?
- A.互斥关系,只能二选一
- B.稀疏管局部细节,线性管全局概览,互补融合← 正确答案
- C.串行关系,先线性后稀疏各跑一遍
- D.等价关系,两者数学上完全一致
答案:B。稀疏注意力用局部窗口或全局采样捕捉精细局部关系,线性注意力用压缩状态覆盖全部位置,二者解决的信息粒度不同。实践中把多头拆成不同分工再融合,取长补短,是常见的高效架构设计。
Q9. 因果线性注意力(每个位置只看过去)最推荐的实现方式是什么?
- A.每个位置都重新计算一遍全部前缀
- B.维护 O(1) 递推状态,增量更新 KᵀV 和分母← 正确答案
- C.把未来位置的键向量置零来近似
- D.用固定滑动窗口截断历史
答案:B。因果线性注意力可以利用求和的可累加性:状态 S_{t} = S_{t-1} + φ(k_t)v_t^⊤,分母同理增量更新,每步只做 O(d²) 更新,与历史长度无关。A 退化为平方复杂度,C 会浪费计算,D 丢失了全部远程历史。
Q10. 线性注意力模型如何补充位置信息?
- A.RoPE 旋转位置编码,内积保留相对距离← 正确答案
- B.ALiBi 注意力线性偏置,距离越远惩罚越大← 正确答案
- C.在 V 向量上直接叠加绝对位置向量
- D.把位置信息融入核函数映射的输入← 正确答案
答案:ABD。RoPE 通过对 Q/K 做旋转编码使内积自然反映相对位置;ALiBi 直接给亲和分数加线性偏置;将位置信息输入核函数也可以让 φ 感知顺序。C 虽然也能编码位置,但直接污染内容向量,并非主流做法,故不选。