假设你是一位宴会总策划,要举办一场容纳 \( n \) 位宾客的超级晚宴。按老规矩,每位宾客必须与在场的其他所有宾客逐一握手寒暄——这场晚宴的成本就是 \( n \times n \) 次握手。宾客从 100 人加到 1000 人,成本涨了 100 倍;加到 10000 人,就是约 1 亿次握手,几乎不可能完成。 Transformer 的自注意力机制,恰好就是这种“全员寒暄”:序列里的每个 Token(可以理解为一个词或一个图像块)都要与所有 Token 计算相关性,开销随序列长度平方增长。因此面对长文档、长视频、高分辨率图像时,显存和算力都会被瞬间榨干。 稀疏注意力(Sparse Attention)给出了一个新玩法:给每位宾客发一张“社交清单”,规定只与哪些人交流。于是出现了三种经典方案——邻座寒暄(条纹型)、同桌寒暄(块状)、横竖接力(轴向)。它们用接近线性的成本,换取近似全注意力的表达能力。这篇内容,就是带你把这套“宴会社交规则”彻底看懂:每种模式怎么设计、什么时候选它、实现时有哪些坑。
掌握稀疏注意力,等于掌握在有限 GPU 显存下处理超长序列的核心武器。无论你要做长文本大模型、高分辨率视觉模型还是多模态工程化,这都是绕不开的实战技能。
可视化演示
展示Dense全注意力矩阵O(n²)与Sparse稀疏模式(条纹型/块状/轴向)的连接结构对比及复杂度优化效果,切换模式理解超长序列注意力降本原理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Dense全连接注意力矩阵 标准Self-Attention每个Token与所有位置计算注意力,形成n×n密集矩阵,内存和计算均为O(n²) 序列长度n增大时GPU显存指数增长,2K序列需约16GB显存,4K需64GB,限制长文本处理 Attention(Q,K) = softmax(QK^T/√d) | O(n²·d) memory & compute Dense Attention的O(n²)复杂度是处理超长序列的核心瓶颈
注意力复杂度困境
设想你举办一场盛大的答谢宴,请了 100 位宾客。如果规则要求“每位宾客都必须与在场所有宾客逐一握手寒暄”,那么全场要完成接近 5000 次握手;宾客加到 1000 人,握手次数飙到约 50 万次;加到 10000 人,就是接近 5000 万次。宾客规模稍有增长,人力预算就彻底失控。这不是策划不努力,而是规则本身决定了成本呈平方级暴增。
Transformer 的自注意力也是同样的“全员寒暄”协议。序列中的每个 Token(可以理解为一个词或一个图像块)都要和所有其他 Token 互相打听“你是什么内容”,再按相关性加权汇总所有人的信息。Token 数量翻倍时,注意力得分矩阵从 \( n \times n \) 变成 \( 2n \times 2n \),计算量和显存占用都要翻 4 倍。这就是为什么处理一篇 8000 Token 的长文档时,全连接注意力会立刻让 GPU 显存告急。
在具体实现中,注意力机制把每个 Token 编码成三个向量:Query(我想找什么)、Key(我是什么)、Value(我能提供什么)。通过 Query 与所有 Key 做点积,得到一张 \( n \times n \) 的“相关度表”,再按相关度加权求和 Value。这张表的规模和平方级复杂度,构成了 Transformer 处理长序列时的最大瓶颈。
宴会策划方被“全员握手”的规则压得喘不过气。要破局,就不能再让每位宾客和所有人寒暄,而必须修改社交规则本身——这正是稀疏注意力登场的理由。
- 复杂度函数 \( T(n) \)注意力操作的总计算量和内存占用,是序列长度 \( n \) 的函数。
- 平方增长 \( O(n^2) \)\( n \) 越大时,总开销的增长速度与 \( n^2 \) 成正比。
- 注意力矩阵规模 \( \mathbb{R}^{n \times n} \)得分矩阵有 \( n \) 行 \( n \) 列,每一格对应一对 Token 的相关性。
稀疏模式设计
精明的主办方决定改规则:不再强制全员寒暄,而是给每位宾客发一张“社交清单”,上面明确列出应该与哪些人交谈。只要清单设计得合理,交流效率就能大幅提升,宾客也不会因为被冷落而抱怨。
Sparse Attention 就是给注意力机制发清单。它提前规定每个 Token 只与哪些位置的 Token 交互,这些连接模式是固定且结构化的,不是随机决定,所以既能大幅压缩计算量,又不至于丢失关键信息。所谓“稀疏”,指的就是注意力矩阵中只有少部分位置允许有值,其余位置直接跳过,不参与计算。
实现上最常见的手段是掩码(mask),也就是一张“许可名单”:允许的连接位置记为有效,其余位置在计算时被屏蔽。每个 Token 平均只关注 \( s(n) \) 个位置,总计算量就从 \( O(n^2) \) 降到了 \( O(n \times s(n)) \)。下面要讲的条纹型、块状、轴向三种模式,就是三张风格迥异的“社交清单”。
“社交清单”决定了宴会的成本,也决定了你会错过哪些消息。接下来三种模式,正是对“该跟谁聊”这个问题的三种不同回答。
- 新复杂度 \( C(n) \)稀疏注意力下的总计算量。
- 平均连接数 \( s(n) \)每个 Token 实际关注的 Token 个数。
- 远小于 \( n \)稀疏模式让平均关注数远小于序列总长度。
- 线性复杂度相当于 \( n \) 乘以一个很小的常数,增长率大幅放缓。
条纹型稀疏
宴会现场的宾客按长条座椅排成一行。主办方规定:每位宾客只需要和前后左右 \( w \) 个座位的宾客交流。离得太远的人,就让邻座替我传话——这样既省了体力,又不至于完全脱离社交网络。
条纹型稀疏,也叫滑动窗口注意力(Sliding Window Attention)。每个 Token 只与位于它前后 \( w \) 范围内的 Token 计算注意力,反映在注意力矩阵上,就是只保留沿主对角线延伸的一条“条纹”。窗口之外的位置一律屏蔽,复杂度主要取决于窗口宽度 \( w \),而不是序列总长 \( n \)。
文本数据天然具有强大的局部性:一个词和紧挨着它的几个词之间的相关性,远高于和十万八千里外的词的相关性。因此条纹型在语言建模中性价比极高。同时,通过叠加多层滑窗注意力,每一层的感受野会逐步扩大,远处信息可以通过中间 Token 一格格“接力”传递过来,不必依赖单层的直接连接。
这就像长桌宴上的“邻座接力”:虽然离得远的宾客素未谋面,但一句话通过若干位邻座的口耳相传,最终能传遍全场。条纹型用最小的社交成本,保住了消息在局部范围内的快速流通。
- 窗口半径 \( w \)每个 Token 向前、向后各能看到的 Token 数量。
- 单个 Token 的交互数每个 Token 只需与 \( 2w+1 \) 个邻居计算注意力,与 \( n \) 无关。
- 总复杂度\( n \) 乘以一个常数,增长率近似线性。
块状稀疏
主办方这次的方案是把宴席分成若干张圆桌。每位宾客只需与本桌其他宾客寒暄,跨桌交流一概省略。想认识其他桌的朋友?请同桌的“话痨”代为引荐,或者等服务员上菜时顺便带句话。
块状稀疏(Blockwise Sparse Attention)把序列切分成固定大小的块,每个 Token 只与本块内的 Token 交互。它和条纹型的关键区别在于:块状看重的是“同组归属”,而不是“空间距离近”。两个 Token 哪怕物理上离得很远,只要被分到同一个块,依然可以建立直接连接。
在工程实现上,块状模式天然适合 GPU 的矩阵分块乘法。GPU 会把数据按块加载到片上内存,块内的完整注意力矩阵正好可以用高性能矩阵运算一次算完,避免频繁的显存随机访问。因此块状稀疏在不牺牲太多信息的前提下,通常能达到比条纹型更高的硬件吞吐。
分桌制让宴会成本从“全员寒暄”骤降为“同桌寒暄”,代价是跨桌信息被切断。因此,块的大小和位置选择,永远是与数据语义相互妥协的结果——下一节我们会看到另一种更聪明的妥协方式。
- 分块数 \( m \)序列被切分成 \( m \) 个互不重叠的块。
- 块大小 \( b \)每块包含的 Token 数,由总长度除以块数得到。
- 块内全连接同块内部两两交互,块与块之间完全断开。
轴向稀疏
如果宴会宾客不是坐长条桌,而是整整齐齐排成方形方阵——就像婚礼草坪上按列摆放的椅子——主办方可以采取一个更巧妙的做法:第一轮交流,每位宾客只与同一排的宾客握手;第二轮交流,每位宾客只与同一列的宾客点头致意。两轮下来,每个人都能接收到来自整行和整列的信息,相当于覆盖了整个方阵。
轴向稀疏注意力(Axial Attention)就是专门针对这种二维乃至高维结构设计的。普通注意力会把一张 \( H \times W \) 的特征图强行拉成一维序列,序列长度立刻变成 \( HW \),在全连接模式下开销是 \( (HW)^2 \),完全不可接受。轴向注意力把它拆成两次一维注意力:一次沿高度轴(对每一行做序列注意力),一次沿宽度轴(对每一列做序列注意力)。
用一个 64×64 的图像特征图举例:全连接注意力需要对 4096 个 Token 两两计算,而轴向方案只需要先做 64 次长度为 64 的行注意力,再做 64 次长度为 64 的列注意力。总计算量从 \( O(16M) \) 级别降到了 \( O(4096 \times 128) \),足足省了两三个数量级。这也是视觉 Transformer 和图像生成模型常用的稀疏策略。
方阵宾客用“横排握手 + 竖排点头”完成了对全场的间接覆盖。当数据自带天然的二维结构时,轴向方案几乎就是为它量身定做的社交礼仪。
- 二维展开特征图有 \( H \) 行 \( W \) 列,总 Token 数记为 \( HW \)。
- 行轴注意力每个 Token 关注同一行的 \( W \) 个 Token,开销为 \( O(HW \cdot W) \)。
- 列轴注意力每个 Token 关注同一列的 \( H \) 个 Token,开销为 \( O(HW \cdot H) \)。
- 两次合并总开销行轴加列轴,远小于全连接的 \( (HW)^2 \)。
实践选型与对比
最终宴会策划组要拍板:用邻座寒暄(条纹)、同桌寒暄(块状)还是方阵接力(轴向)?答案取决于宾客怎么坐、来宾名单有多长,以及你雇得起多少服务员——也就是 GPU 算力与显存预算。
一句话选型原则:文本与长文档通常优先选条纹型或块状;图像、视频等高维数据优先选轴向;若担心全局信息缺失,可以额外加几个全局 Token 作为“主持人”,让所有人只跟主持人广播。三种模式也可以组合拼接,设计出自适应混合方案,但复杂度也随之上升。
从计算量看,条纹型 \( O(nw) \) 在短距离依赖强的文本上性价比最高;块状 \( O(nb) \) 的 GPU 吞吐通常更好;轴向 \( O(HW(H+W)) \) 在高分辨率视觉任务上优势显著。从精度看,主流稀疏注意力模型都能把性能控制在接近全注意力的水平,远优于简单粗暴的随机丢弃。真正决定上限的,是所选稀疏模式与数据分布是否匹配。
三种“寒暄方案”没有绝对优劣。宴会的最终效果取决于策划者是否读懂了宾客结构:长桌宴席用邻座接力,圆桌酒会用同桌寒暄,方阵草坪用横竖点头——稀疏注意力的选型,本质上就是一场关于结构与预算的匹配游戏。
- 复杂度比 \( \eta \)稀疏方案与全连接方案的成本比例。
- 分子 \( C_{\text{sparse}} \)稀疏注意力的实际开销。
- 分母 \( C_{\text{dense}} \)全连接注意力的开销。
- 极限行为当 \( s(n) \) 远小于 \( n \) 时,\( \eta \) 趋近于 0,计算量接近线性。
AI 应用场景
长文档理解与法律合同审查
阶段:模型微调与推理
解决的问题:合同、研报动辄上万 Token,全连接注意力的 \( n \times n \) 矩阵会让显存直接爆掉;传统做法只能粗暴截断文档,导致模型漏掉关键条款。稀疏注意力配合全局 Token,可以在完整上下文上进行推理。
具体案例:一家法律科技公司用块状稀疏加全局 Token 处理 15000 Token 的合同,条款摘要准确率从截断方案的 71% 提升到 88%,显存占用仅为全注意力的 35%。
高分辨率医学影像分析
阶段:视觉模型训练
解决的问题:整张病理切片往往有数亿像素,拉平成序列后 Token 数量巨大,全连接注意力不可行。轴向稀疏把二维图像的行与列分别做一维注意力,既保留空间结构又显著降低开销。
具体案例:某影像组学团队用轴向注意力处理 4096×4096 的病理切片 patch,训练速度提升约 3 倍,分类 AUC 与全注意力持平。
长视频时序建模
阶段:多模态模型推理
解决的问题:视频相邻帧强相关,但跨帧建模的计算开销随序列长度急剧增长。条纹型滑窗注意力天然匹配时间局部性,只需维护一个滑动窗口即可聚合局部运动信息。
具体案例:视频理解模型用 32 帧的滑窗注意力替代全局注意力,推理显存下降 60%,动作识别准确率基本不降。
Python 演示
import numpy as np def dense_attention(Q, K, V): # 全连接注意力: 每个 token 与所有 token 交互 scores = Q @ K.T weights = np.exp(scores - scores.max(axis=-1, keepdims=True)) weights = weights / weights.sum(axis=-1, keepdims=True) return weights @ V def stripe_attention(Q, K, V, w=3): # 条纹型稀疏: 每个 token 只关注前后 w 个邻居 n = Q.shape[0] out = np.zeros_like(V) for i in range(n): lo = max(0, i - w) hi = min(n, i + w + 1) idx = np.arange(lo, hi) s = Q[i] @ K[idx].T p = np.exp(s - s.max()) p = p / p.sum() out[i] = p @ V[idx] return out def block_attention(Q, K, V, b=8): # 块状稀疏: 每个 token 只关注同一块内的 token n = Q.shape[0] out = np.zeros_like(V) for i in range(n): blk = (i // b) * b hi = min(n, blk + b) idx = np.arange(blk, hi) s = Q[i] @ K[idx].T p = np.exp(s - s.max()) p = p / p.sum() out[i] = p @ V[idx] return out def count_connections(n, mode, **kw): # 统计各种模式的连接总数, 用于对比计算量 if mode == 'dense': return n * n if mode == 'stripe': return n * (2 * kw.get('w', 3) + 1) if mode == 'block': return n * kw.get('b', 8) return 0 if __name__ == '__main__': N, D = 64, 16 rng = np.random.default_rng(0) Q = rng.standard_normal((N, D)) K = rng.standard_normal((N, D)) V = rng.standard_normal((N, D)) outs = { 'dense': dense_attention(Q, K, V), 'stripe': stripe_attention(Q, K, V, w=3), 'block': block_attention(Q, K, V, b=8), } for name, o in outs.items(): print(name, 'output shape:', o.shape) conns = { 'dense': count_connections(N, 'dense'), 'stripe': count_connections(N, 'stripe', w=3), 'block': count_connections(N, 'block', b=8), } print('connections:', conns)
scores = Q @ K.T一次性算出所有 Token 两两间的相关度得分,形成 \( n \times n \) 矩阵。weights = weights / weights.sum(axis=-1, keepdims=True)对每一行做归一化,等价于 Softmax 的数值稳定版本。lo = max(0, i - w); hi = min(n, i + w + 1)把关注范围裁剪到窗口内,避免索引越界。idx = np.arange(lo, hi)用索引切片代替全量矩阵,只让当前 Token 和窗口内 Key 做点积。blk = (i // b) * b计算当前 Token 所属块的起始下标,实现“同块相连、跨块断开”。count_connections快速估算三种模式各产生多少连接,n=64 时分别是 4096、448、512。
常见误区
误区刚接触时以为 Sparse Attention 就是像 Dropout 一样随机丢掉一些连接,省算力又省心。
正解稀疏注意力的掩码是结构化、确定性的:条纹型只保留对角线附近的邻居,块状只保留同块 Token,轴向只保同行或同列。随机丢弃每个样本都要重新采样,没有固定结构,在 GPU 上也无法利用块矩阵加速。对比宴会的比喻:主办方既不会随机抽人握手,也不会规定“说错话就断交”,而是提前把社交清单写成明文规则。
为何常见:Dropout 在神经网络里太常见,看到“丢连接”就自然联想到随机化,忽略了“结构化”才是稀疏注意力的灵魂。
误区条纹型只允许相邻几个 Token 交互,那模型不就永远看不到远处的信息了吗?
正解单层窗口确实只能看到局部,但多层堆叠后,每一层都可以把上一层的输出继续做窗口交互,感受野随之逐层扩大。更可以通过少量全局 Token 把全局信息“广播”进来。这就像宴会里的消息靠邻座一格格接力传,最终全场都能知道,不需要每个人直接面对面。
为何常见:把注意力层当成了孤立的单层操作,忽略了深度网络中层级递进带来的信息传播能力。
误区块状稀疏实现最简单,把序列按固定大小切开就行,反正大家都是省算力。
正解块边界的选择直接影响模型效果。如果一句完整的话被硬生生切成两半,跨块的强语义关系就会丢失。实际工程里常用重叠块、跨块跳层或全局 Token 来弥补。好比酒席上把一对合作伙伴分到两桌,再想沟通就只能靠服务员传话,信息损耗在所难免。
为何常见:分块看起来是个纯工程操作,容易忽略它隐含的感受野限制和语义约束,只有跑完实验看到效果下滑才反应过来。
误区既然三种模式各有优点,那把条纹、块状、轴向全叠加起来,效果肯定最好。
正解模式组合必须与数据结构匹配。文本适合条纹或块状,图像适合轴向,盲目混用会增加索引和掩码复杂度,甚至引入大量无效计算。好比你不能让宴会同时执行“邻座握手 + 同桌寒暄 + 方阵集合”三种方案,宾客会被指挥得晕头转向,满意度反而下降。
为何常见:忽略了不同稀疏模式的适用范围和数据先验,把“稀疏”误当成可以随意裁剪的万能工具。
面试题
Q1. 标准自注意力机制的计算复杂度是?
- A.线性增长
- B.平方增长← 正确答案
- C.对数增长
- D.立方增长
答案:B。自注意力要对 \( n \times n \) 对 Token 两两计算相关性,序列长度翻倍时工作量约变为原来 4 倍,因此是平方增长。这就像全员握手寒暄的宴会,宾客翻倍时握手次数约翻四倍。
Q2. 稀疏注意力的核心思想是什么?
- A.只让部分Token互相交互← 正确答案
- B.让所有Token都互相交互
- C.不让任何Token互相交互
- D.把Token顺序随机打乱
答案:A。Sparse Attention 提前设计连接模式(窗口、块、行列轴),让每个 Token 只与少数关键位置交互。B 是全连接注意力;C 等于切断所有信息流,模型无法学习;D 只是改顺序,不改变连接数量。
Q3. 条纹型稀疏注意力利用了以下哪种先验?
- A.数据存在强局部相关性← 正确答案
- B.数据存在全局规律性
- C.数据完全随机分布
- D.数据与位置毫无关系
答案:A。条纹型(滑窗)只保留对角线附近的连接,其依据是文本中邻近 Token 的相关性远高于远处位置,这与“邻座寒暄”的直觉一致。全局规律性是全局 Token 才关心的先验,C 和 D 与注意力设计相悖。
Q4. 以下哪些说法符合块状稀疏注意力的特点?
- A.更适配GPU分块并行加速← 正确答案
- B.块边界选择影响模型效果← 正确答案
- C.可以完全替代条纹型注意力
- D.对硬件无需任何适配
答案:AB。块状把序列切块做局部密集注意力,天然契合 GPU 的分块矩阵乘法;同时块边界若与语义切割不匹配,跨块信息会丢失。不同稀疏模式各有适用场景,不能完全互相替代,硬件适配也是工程中必须考虑的环节。
Q5. 轴向稀疏注意力最适合处理哪类数据?
- A.二维图像特征图← 正确答案
- B.一维音频波形
- C.单行文本序列
- D.离散符号序列
答案:A。轴向注意力把二维结构拆成行轴加列轴两次一维注意力,图像和视频特征图天然具有 \( H \times W \) 结构,所以最合适。一维文本和音频更适合条纹型或块状稀疏。
Q6. 以下哪些属于稀疏注意力的实际收益?
- A.减少计算量和显存占用← 正确答案
- B.彻底消除所有精度损失
- C.支持超长序列处理← 正确答案
- D.强制保留全部连接
答案:AC。稀疏注意力通过减连接降低 \( O(n^2) \) 开销,让数万 Token 的长序列也能放进显存。但“减连接”必然带来信息取舍,不可能彻底消除精度损失;D 恰恰与稀疏思想相反,是在描述全连接。
Q7. 滑窗注意力通过堆叠多层可以做到什么?
- A.让感受野随层数扩大← 正确答案
- B.让每层窗口严格变小
- C.让关键词全局消失
- D.让相邻层完全断连
答案:A。单层滑窗只能看到局部邻居,但多层堆叠后,远距离 Token 可以通过中间 Token 一格格“接力”传递,感受野逐层扩展。这对应宴会传言通过邻座接力传遍全场的过程;B、C、D 都会破坏信息传播。
Q8. 块状稀疏中块边界设置失误可能带来什么后果?
- A.跨块的强语义关系丢失← 正确答案
- B.模型效果明显下滑← 正确答案
- C.显存开销自动归零
- D.计算复杂度完全消失
答案:AB。块边界如果切断了强关联的 Token(比如把一句话一分为二),模型就无法建立直接跨块连接,最终效果明显下滑。开销不会凭空消失,只是从密集计算转移成了索引与掩码管理的复杂度。
Q9. 以下哪个不属于三种典型稀疏模式?
- A.条纹型稀疏模式
- B.块状稀疏模式
- C.轴向稀疏模式
- D.环形稀疏模式← 正确答案
答案:D。三种经典稀疏模式是条纹型、块状和轴向。环形不是标准稀疏模式名称,它像“让宾客在圆桌旁握一圈手”,直觉上合理,但并没有对应的成熟注意力设计。
Q10. 复杂度比 \( \eta = s(n)/n \) 趋近于 0 意味着什么?
- A.稀疏方案开销远小于全连接← 正确答案
- B.稀疏方案开销远大于全连接
- C.稀疏方案与全连接开销相当
- D.稀疏方案开销无法被估计
答案:A。\( \eta \) 是稀疏复杂度与全连接复杂度的比值。\( \eta \to 0 \) 代表每个 Token 的平均连接数 \( s(n) \) 远小于序列长度 \( n \),成本趋近线性;反之若 \( \eta \) 接近 1,说明稀疏几乎没省下计算量,方案选型可能出了问题。