想象一下小区组织全体居民大会:800 户人家站在广场上,每一户都必须跟其他每户握手寒暄。800×800,足足 64 万次握手,从清晨握到深夜还没握完。更糟的是,来年小区扩建成 1600 户,握手次数会变成 256 万——涨了 4 倍!这就是完整注意力机制在长序列面前的困境:序列越长,交互次数按平方爆炸式增长。 后来,一位聪明的社区主任想出了新方案:不必人人都认识所有人。你只需要跟隔壁邻居打声招呼,跟楼栋长握个手,再向居委会主任汇报一下近期情况,就能掌握整个小区的动态。连接变少了,但关键信息一条没丢。这就是稀疏注意力——用精心设计的少量连接,替代全量的两两交互,让模型能轻松处理超长序列。 本文将从“握手困境”出发,带你认识局部窗口、全局 Token 等稀疏模式,揭秘 Longformer、BigBird 等经典模型如何把理论变成现实,再看到工程师们如何用掩码矩阵和分块计算将这套方案落地。
掌握稀疏注意力,你就能在真实项目中处理超出常规长度限制的文档、基因序列和代码库,让模型在算力不变的前提下“看得更远”——这是走向高级 NLP 工程师的必经之路。
可视化演示
动态演示稀疏注意力的核心机制,通过总览/传输/转换/输出四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
稀疏注意力:稀疏注意 稀疏注意力的设计动机与复杂度 局部窗口注意力的连接模式 核心机制可视化 稀疏注意力整体架构与关键组件
复杂度困境
回到小区居民大会。当居民人数 n 从 800 涨到 1600,握手次数从 64 万涨到 256 万——涨了整整 4 倍。这就是二次增长的可怕之处:规模只翻一倍,代价却翻两番。标准注意力机制恰恰面临同样的难题。为了让模型理解一个词在句子中的含义,注意力机制会让每个 Token(你可以把它理解为“文本被切成的小片段”)与其他所有 Token 两两打分,生成一张 n×n 的“关注度图表”。这张图表就是 QK^T 矩阵。
完整注意力的数学形式如下:
这张 n×n 的图表带来两个直接后果。第一,计算量随 n 平方增长,处理 8192 个 Token 时,光是打分就要做约 6700 万次运算;第二,内存同样爆炸——这张图表本身就要占用 n² 个浮点数的空间。所谓“长序列受限”,就是模型在 512 个 Token 内表现良好,一旦扩展到几千上万,算力和显存双双告急。许多 NLP 工程师被迫“截断”文档,把长文切成碎片再拼接,宝贵的远距离信息就此丢失。
当小区变成 10 万人的大城市,全体握手的大会再也开不起来了。能不能换一种方式组织交流?这正是下一节要解决的问题。
- 计算相似度矩阵将查询矩阵 Q 与键矩阵 K 的转置相乘,得到 n 个位置两两之间的原始打分,形状为 n×n。
- 缩放稳定梯度除以 \sqrt{d_k}(d_k 为键向量的维度),防止分数过大导致后续 softmax 进入梯度饱和区。
- 归一化权重对每一行施加 softmax,把原始打分变成一组和为 1 的注意力权重。
- 加权聚合将权重矩阵与值矩阵 V 相乘,对每个 Token 的值向量做加权求和,得到最终输出。
稀疏化思想
社区主任的新方案是这样的:第一,每位居民只需要跟自家隔壁几户打招呼——这叫局部窗口;第二,每栋楼选一位楼栋长,楼栋长要认识楼里所有人,而普通居民只需向楼栋长汇报——这些楼栋长就是全局 Token。这样一来,居民之间的连接数从“人人握手”降为“邻里寒暄 + 定期汇报”,信息传递却依然畅通。
将这套思路翻译成注意力机制,我们需要一张“谁可以联系谁”的名单——这就是掩码矩阵 M。M 与 QK^T 形状相同,位置 (i, j) 填 0 表示 Token i 可以关注 Token j,填 -∞ 表示禁止关注。把 M 加到打分矩阵上,再经过 softmax,被屏蔽的位置权重自然归零,等效于没有连线。稀疏注意力的一般形式:
三种典型的稀疏模式随之诞生:局部窗口注意力让每个 Token 只看前后 w 个邻居;全局 Token 注意力让少数选定位置(通常是句首 CLS 或任务相关标记)关注整个序列;带状(膨胀)模式则每隔若干个 Token 取一个位置建立连接,像编织渔网一样扩大视野。这些模式可以单独使用,也可以叠加组合,形成不同的“社区组织方案”。
邻居之间聊天保持了亲切感,楼栋长汇报保证了全局视野——稀疏注意力就这样用“结构”换来了“效率”。接下来看看这套理念在真实模型中如何开花结果。
- 定义掩码矩阵 M构建一个与打分矩阵同形的 n×n 矩阵,0 表示放行,-∞ 表示拦截。
- 分数叠加掩码将 M 加到缩放后的相似度矩阵上,被屏蔽位置的分数被压到负无穷。
- softmax 自动归零-∞ 处的值经过 softmax 后权重趋近于 0,等价于完全不关注该位置。
- 加权求和与完整注意力一样乘以 V,输出形状完全不变,下游模块无需任何调整。
经典模型
不同的社区会选择不同的组织方案。有的小区每栋楼设楼栋长(Longformer),有的小区在楼栋长之外还随机安排居民互助小组(BigBird)。这些方案就是稀疏注意力的经典落地模型。
Longformer(长型 Transformer)采用“滑动窗口 + 少量全局 Token”的组合。每个 Token 只与前后各 w 个位置的邻居计算注意力,同时选出少量 Token(如 [CLS] 标记)作为全局节点,与所有位置相连。这种设计让它的复杂度滑落到接近线性。BigBird 在此基础上加入第三类连接:随机注意力——每个 Token 随机与 r 个其他 Token 建立连接,模拟“在社区里随机认识几个陌生人”的效果,进一步保证了信息在长距离上的传播通道。两类模型的复杂度可统一写成:
其中 n 是序列长度,w 是窗口半径,g 是全局 Token 数量。当 w 和 g 固定时,总交互次数随 n 线性增长——从二次跌到一次,这是质的飞跃。实验表明,Longformer 能处理 4096 甚至更长 Token 的文档,BigBird 在基因序列等超长数据上表现优异。值得注意的是,随机连接虽然看起来“不靠谱”,但数学上它保证了任意两个 Token 之间都存在足够短的路径,信息可以在图结构中高效流动。
从“全员握手”到“楼栋长制”,经典模型证明了稀疏化不是幻想。但具体怎么设计才能让连接既省又快?下一节聊聊模式设计中的门道。
- 局部交互项 n·w每个 Token 只与窗口内约 w 个邻居交互,n 个 Token 合计约 n·w 次交互。
- 全局交互项 n·g每个 Token 额外关注 g 个全局位置(楼栋长),合计 n·g 次交互。
- 线性复杂度w 与 g 是固定常数时,总复杂度由 n 主导,O(n·w + n·g) 近似于线性。
模式设计
窗口开多大?全局 Token 放哪几个位置?随机连接有多少条?这些问题决定了稀疏注意力的实际效果,就像社区组织方案必须因地制宜:老小区关系紧密,小窗口就够用;新建的开放式社区人员流动大,就得安排更多楼栋长和互助组。
窗口大小是最核心的超参数。窗口太小,Token 只能看到身边的只言片语,理解不了长距离指代;窗口太大,又会失去稀疏的意义。实践中 w 常在 8~128 之间按任务调参。全局 Token 的放置同样讲究——最常用的是放在序列开头(如 [CLS] 标记),让它在分类任务中充当“汇总人”;也有工作把全局 Token 均匀散布在序列各段,类似每栋楼都设楼栋长。窗口注意力的单行计算量很简单:
不同的任务天然适合不同的稀疏结构。代码理解任务中,语句内部依赖强、跨函数依赖弱,小窗口加几个全局 Token 就够;长程文本摘要则要求更密集的全局连接,让摘要位置能“俯瞰”全文。研究者还发现,分层稀疏(浅层用大窗口、深层用小窗口)能让模型先建立全局印象、再聚焦局部细节,类似先看小区地图再挨家走访。
模式设计像“组织社区”,而这一切最终要落到账本上——省下来的握手次数到底有多少?效率和收益如何量化?进入下一节。
- 窗口跨度 2w+1每个 Token 关注左右各 w 个位置,再加上自己,共 2w+1 个位置。
- 逐行统计总量n 个 Token 每行执行窗口内注意力,总交互次数为 n×(2w+1)。
- 线性近似当 w 是固定常数时,复杂度随 n 线性增长,写作 O(n·w)。
效率分析
组织一次 800 户的稀疏大会,握手次数从 64 万降到多少?我们来算一笔账。设序列长度 n=4096,窗口半径 w=16,全局 Token 数 g=1。完整注意力需要 4096² ≈ 1677 万次交互;稀疏注意力每行只需要关注 33 个窗口邻居加 1 个全局 Token,总交互约 4096×34 ≈ 13.9 万次。两者相除,节省约 120 倍。加速比公式如下:
除计算量外,内存节省同样显著。标准注意力必须物化一张 n×n 的注意力权重矩阵——当 n=8192 时就是 6700 万个浮点数,约 256MB 显存(单卡根本放不下)。稀疏注意力采用块稀疏存储或即时计算,只需保存每行窗口内的值,内存从 O(n²) 降到 O(n·w)。这意味着在同样的显存预算下,稀疏模型可以支撑 8 倍甚至更长的序列,对 NLP 工程师来说等于“免费”把模型的处理长度上限抬升了一个量级。
账算完了,理论很美好,但真正把“省下来的握手”变成训练速度,还需要扎实的工程实现。最后看看掩码矩阵和分块计算如何落地。
- 完整连接数 n²完整注意力中每对 Token 都要交互,总连接数为 n²。
- 稀疏连接数每行保留窗口内 2w+1 个位置与 g 个全局位置,共 n(2w+1+g) 次交互。
- 节省倍数两者相除得到约 n/(2w+1+g) 的加速比,代入 n=4096, w=16, g=1 约为 120 倍。
工程实现
把稀疏注意力写进代码,第一步是构造掩码矩阵。以滑动窗口为例:用一个 n×n 的矩阵,初始全部填 -∞,然后把窗口内的位置改成 0,再额外放行全局 Token 所在的行与列。前向传播时只需一步加法,就能让 softmax 自动屏蔽所有非法位置:
第二步是分块计算。如果直接构造完整的 n×n 稀疏矩阵再去乘,内存依然吃紧。工程上常用“分块”技巧:把序列切成若干块,只在块内计算注意力;全局 Token 则单独作为一个块参与所有计算。这样做既减少了矩阵填充量,又能利用 GPU 的矩阵乘法加速。Hugging Face Transformers 库已经内置了 Longformer 和 BigBird 的实现,训练时只需设置 attention_window 等参数即可调用。真正的工程落地还需要注意:推理时可以把掩码预先转成稀疏格式(如 CSR/CSC),进一步减少访存;在分布式场景下,全局 Token 需要跨卡通信,因此要精心设计它在张量并行中的放置位置。
至此,从理论到工程的全链路打通了。稀疏注意力用“更少的握手”换来了“更远的视野”,让长序列处理从奢侈品变成了日用品。
- 定义邻居集合Token i 的合法关注集合由窗口位置与全局 Token 位置两部分组成。
- 合法位置放行掩码为 0,不改变原始注意力分数。
- 非法位置拦截掩码为 -∞,softmax 后权重归零,实现“静默屏蔽”。
AI 应用场景
长文档智能审查
阶段:模型微调与推理
解决的问题:传统模型对长文档必须先截断,丢失关键条款信息;稀疏注意力让 100 页合同一次性读入。
具体案例:某法律科技公司用 Longformer 微调合同风险审查模型。原始合同平均 8000+ Token,过去 Truncate 到 512 后常常漏掉隐藏在文档中部的免责条款。改用滑动窗口 + 全局 Token 后,模型可完整覆盖全文,风险条款召回率提升 23%。
基因序列变异检测
阶段:数据预处理与模型训练
解决的问题:DNA 序列长达数万碱基对,局部 CNN 捕捉不到远距离碱基之间的调控关系,完整注意力又算不动。
具体案例:基因研究团队用 BigBird 对整段基因序列建模,利用随机注意力建立碱基之间的长程通路,在启动子区域识别任务上,相比滑窗 CNN 的 F1 分数提升约 15%,且训练显存占用仅为传统 Transformer 的 1/40。
代码仓库语义搜索
阶段:模型部署
解决的问题:代码文件长、结构复杂,函数内部依赖与跨文件引用并存,稀疏结构天然契合代码的局部性与全局引用。
具体案例:某代码智能助手将函数体按行切分为 Token 序列,用窗口注意力捕捉语句块内部逻辑,用全局 Token 指向函数定义处,支持 8192 Token 的完整文件编码。搜索召回准确率比截断方案提升 31%。
Python 演示
import numpy as np def window_mask(n, window_size, global_idx=None): """生成稀疏注意力掩码: 窗口内 + 全局 token""" mask = np.full((n, n), -1e9) for i in range(n): start = max(0, i - window_size) end = min(n, i + window_size + 1) mask[i, start:end] = 0.0 if global_idx is not None: mask[:, global_idx] = 0.0 mask[global_idx, :] = 0.0 return mask def sparse_attention(Q, K, V, mask): """执行稀疏注意力计算 (演示用)""" d = Q.shape[-1] scores = Q @ K.T / np.sqrt(d) + mask weights = np.exp(scores) / np.sum(np.exp(scores), axis=-1, keepdims=True) return weights @ V if __name__ == "__main__": n, d = 512, 64 rng = np.random.default_rng(42) Q = rng.normal(size=(n, d)) K = rng.normal(size=(n, d)) V = rng.normal(size=(n, d)) w = 8 mask = window_mask(n, w, global_idx=0) dense_conn = n * n sparse_conn = int(np.sum(mask > -1e8)) print(f"序列长度: {n}") print(f"完整注意力连接数: {dense_conn}") print(f"稀疏注意力连接数: {sparse_conn}") print(f"计算量节省: {dense_conn / sparse_conn:.1f} 倍") out = sparse_attention(Q, K, V, mask) print(f"输出形状: {out.shape}")
mask = np.full((n, n), -1e9)用极小的 -1e9 模拟 -∞,初始化一张“全员拉黑”的名单。mask[i, start:end] = 0.0在窗口范围内“放行”,这些邻居位置可以正常通信。mask[:, global_idx] = 0.0让所有 Token 都能关注全局 Token,相当于人人可以向楼栋长汇报。mask[global_idx, :] = 0.0同时让全局 Token 能关注所有人,楼栋长也要走访全楼。scores = Q @ K.T / np.sqrt(d) + mask打分矩阵加上掩码,被屏蔽位置直接压到负无穷。np.exp(scores) / np.sum(np.exp(scores), axis=-1, keepdims=True)softmax 归一化,屏蔽位置权重自动归零。dense_conn / sparse_conn用连接数比值来量化“省了多少握手”。
常见误区
误区稀疏注意力听上去像“丢数据”——随便扔掉一部分连接,省多少算多少,反正模型也不差那几条。
正解稀疏注意力恰恰相反,它的每一次“砍掉”都是精心设计的结构选择。局部窗口保证了对近邻的精细建模,全局 Token 保证了整体视野,随机连接(BigBird)也只是为了保证图连通性的辅助手段。这些模式有明确的先验逻辑和理论依据,与“随机丢弃”有本质区别。
为何常见:人们看到“稀疏”会联想到随机、稀疏矩阵存储中的填零,很多科普文章也只讲“少算一些”,从没解释模式背后的设计含义。
误区注意力连接数量少了,模型获取的信息就少了,效果理应不如完整注意力。
正解在超长序列任务上,稀疏注意力往往不输甚至超过完整注意力。一方面,全局 Token 保留了至关重要的全局信息;另一方面,完整注意力在长序列上训练不稳定、容易过拟合,而稀疏结构天然带有正则化效果。Longformer 和 BigBird 的论文在多个长文本基准上都报告了与完整注意力相当或更优的结果。
为何常见:直觉上“信息越多越好”,忽略了完整注意力在超长输入下本身存在优化难题,也低估了稀疏结构带来的泛化收益。
误区注意力瓶颈主要表现为计算慢,内存上似乎没什么差别,反正模型参数都一样多。
正解标准的完整注意力需要物化一张 n×n 的注意力权重矩阵,n=8192 时仅此一项就占用约 256MB 显存。稀疏注意力采用块稀疏存储或即时计算,不构建全量矩阵,内存占用从 O(n²) 降至 O(n·w)。正因如此,它才被广泛应用于单卡处理超长序列的场景。
为何常见:多数复杂度分析只提“浮点运算次数”,忽略了注意力矩阵本身也是存储大户,学习者自然看不到内存维度的收益。
误区既然窗口大了能看更多邻居,那就把窗口直接设成整个序列长度,效果肯定更好。
正解当窗口等于序列长度时,稀疏注意力就退化为完整注意力——复杂度回到 O(n²),稀疏的优势荡然无存。窗口大小的选择应基于任务特性,并接受精度与效率的权衡。实际工程里,代码理解用小窗口(局部依赖强)、长文摘要用大窗口或更多全局 Token,才是合理做法。
为何常见:人们默认“更大的感受野 = 更好的模型”,忽略了稀疏注意力的本质是用结构性先验换取效率,而不是无脑扩充视野。
面试题
Q1. 标准自注意力的计算复杂度是?
- A.线性 O(n)
- B.二次 O(n²)← 正确答案
- C.对数 O(logn)
- D.三次 O(n³)
答案:B。标准注意力需要计算 n 个 Token 两两之间的打分,生成 n×n 的相似度矩阵,因此复杂度为 O(n²)。这就像小区全体居民大会,每户都要跟所有其他户握手,连接数随户数平方增长。
Q2. 稀疏注意力降低计算复杂度的核心手段是?
- A.降低模型层数
- B.只关注部分位置← 正确答案
- C.缩小词向量维度
- D.增大批处理大小
答案:B。稀疏注意力通过掩码矩阵限制每个 Token 只关注窗口内的邻居和少数全局 Token,从而将复杂度从 O(n²) 降到接近线性。缩小词向量维度虽然也能减少计算量,但那是改变特征表示,不属于稀疏注意力的定义范畴。
Q3. Longformer 的注意力模式不包括下列哪一项?
- A.滑动窗口注意力
- B.全局Token注意力
- C.随机稀疏连接← 正确答案
- D.窗口内全连接
答案:C。Longformer 采用「滑动窗口 + 全局 Token」的组合,没有随机注意力。随机稀疏连接是 BigBird 在窗口与全局之外引入的第三类模式,用于增强长距离信息通路。
Q4. 在掩码矩阵中,被屏蔽位置通常填入什么值?
- A.直接填 0
- B.负无穷大← 正确答案
- C.正常的 1
- D.正无穷大
答案:B。被屏蔽位置填入 -∞(实现时常用 -1e9),这样加上原始打分后依然接近负无穷,softmax 归一化时该位置的权重趋近于 0,等效于完全忽略该 Token。如果填 0,softmax 仍会分配一定的注意力权重,屏蔽就失效了。
Q5. 全局 Token 在稀疏注意力中的主要作用是?
- A.增加模型参数量
- B.补偿局部视野局限← 正确答案
- C.降低训练难度
- D.提升推理速度
答案:B。局部窗口只能看到身边几个邻居,视野受限;全局 Token(如 CLS 标记)能关注整个序列,同时被所有 Token 关注,充当信息的“集散中心”,从而补偿局部注意力的视野盲区。
Q6. 序列长度翻倍时,完整注意力的计算量变为原来的多少倍?
- A.变为原来的 2 倍
- B.变为原来的 4 倍← 正确答案
- C.没有明显变化
- D.变为原来的 8 倍
答案:B。完整注意力复杂度为 O(n²),n 变为 2n 后,计算量为 (2n)² = 4n²,即原来的 4 倍。这正像是居民从 1000 户增加到 2000 户,握手次数从 100 万涨到 400 万。
Q7. 设序列长度 n=4096,窗口半径 w=16,全局 Token 数 g=1,稀疏注意力相比完整注意力约节省多少倍计算量?
- A.约为 2 倍
- B.约为 16 倍
- C.约为 120 倍← 正确答案
- D.约为 4096 倍
答案:C。完整连接数 n² ≈ 1677 万;稀疏模式每行关注 2w+1+1 = 34 个位置,总连接数约 4096×34 ≈ 13.9 万。加速比 = n/(2w+1+g) = 4096/34 ≈ 120 倍。C 选项正确。D 选项没有考虑常数项 2w+1+g,误以为节省倍数等于 n。
Q8. 以下哪些属于稀疏注意力的典型模式?
- A.局部窗口注意力← 正确答案
- B.全局Token注意力← 正确答案
- C.随机稀疏连接← 正确答案
- D.全连接的注意力
答案:ABC。局部窗口、全局 Token、随机稀疏连接(见 BigBird)是稀疏注意力的三种典型模式。全连接注意力是完整注意力形式,复杂度为 O(n²),不属于稀疏范畴。
Q9. 关于 BigBird,下列说法正确的有?
- A.含滑动窗口注意力← 正确答案
- B.包含全局 Token← 正确答案
- C.包含随机注意力← 正确答案
- D.复杂度仍是二次方
答案:ABC。BigBird 的核心是“窗口 + 全局 + 随机”三种模式的组合,复杂度接近线性 O(n)。D 选项错误:BigBird 正是为了摆脱二次复杂度而设计的,它在保留全局信息的同时用随机连接保证长距离通路。
Q10. 稀疏注意力的优点包括?
- A.降低计算复杂度← 正确答案
- B.减少内存占用← 正确答案
- C.支持更长序列← 正确答案
- D.效果一定更好
答案:ABC。稀疏注意力从 O(n²) 降到接近线性,内存占用同步下降,因此可以处理更长的序列。D 选项过于绝对:虽然许多长文本任务中稀疏注意力表现不输甚至超越完整注意力,但“一定更好”的说法是错误的。