前言:一个平方项引发的革命
如果你对大语言模型稍有了解,你一定听过"注意力机制"这个词。2017年,Google的一篇论文《Attention Is All You Need》把它推上了舞台中央,此后几乎所有的大模型——GPT、BERT、LLaMA、Claude——都建立在它的基础之上。
但注意力机制并不是故事的起点,也不是终点。
故事的真正主角,是一个藏在公式深处的平方项——L²。
L是序列的长度,也就是模型一次能"看到"多少个token。L²意味着:当你想把序列长度翻倍,计算量不是翻倍,而是翻四倍。当你想把序列长度变成十倍,计算量变成一百倍。
这个平方项不是某个具体算法的缺陷。它是"让每个词看见所有词"这个需求本身要付出的代价。只要你想要全局信息交互,L²就会像幽灵一样出现——不管你用什么算法,不管你用什么硬件。
全连接?O(L²d²)。标准注意力?O(L²d)。线性注意力?终于把L²消掉了,但代价是精度损失。稀疏注意力?L²还在,只是把大部分边扔了。状态空间模型?绕开了注意力,但能否完全替代仍无定论。
整部大模型发展史,可以浓缩为一场与L²的持续博弈。每一次重大突破,都是对L²的一次妥协或一次战胜:
- 第一次博弈:用注意力机制替代全连接,复杂度从O(L²d²)降到O(L²d),Transformer诞生。
- 第二次博弈:用稀疏注意力减少交互的边,不再让每个token看所有人。
- 第三次博弈:用线性注意力改变计算顺序,在不丢边的情况下把L²消掉。
- 第四次博弈:跳出注意力框架,用状态空间模型等全新架构绕开L²。
这本书就是沿着这条线索写的。我们会从"为什么语言模型必须让每个词看见所有词"讲起,一步步走到当前的前沿,最后追问一个终极问题:L²能被彻底消灭吗?
在开始之前,先给你三组数字,让你感受一下L²的压迫感:
GPT-3的上下文长度是2048个token,隐藏维度d=12288。如果用朴素的跨位置全连接来实现全局信息交互,一层全连接的参数量就是633万亿——是整个GPT-3模型参数量的3600倍。这意味着,如果用全连接,哪怕只有一层,参数就已经爆炸到不可能实现的地步。
标准注意力把这633万亿降到了515亿次浮点运算,缩减了12200倍。这是Transformer存在的理由。
但当上下文窗口扩展到200万token时,标准注意力的计算量飙升到49152万亿次,而线性注意力只需要302万亿次——163倍的差距。这就是为什么长上下文模型必须寻找新的出路。
633万亿,515亿,302万亿。三个数字,三次跨越,一场仍在进行中的博弈。
整部大模型发展史,本质上就是一场与L²项的持续博弈
第一章 问题从何而来——想让每个词看见所有词
1.1 语言的本质是关联
读下面这句话:
"李明把钱包落在了银行旁边的长椅上,他回去找的时候已经不见了。"
这句话里的"他"指谁?你毫不迟疑地知道是李明。"银行"是什么意思?你不会理解为河岸,因为"钱包"和"长椅"排除了那个可能。但你做出这些判断的过程,并不是孤立地看每一个词——你的大脑在瞬间完成了词与词之间的关联:钱包、银行、长椅、他,这些词彼此印证,共同构建了一个连贯的场景。
这就是语言最根本的特性:一个词的意义,从来不在它自身,而在它与周围词的关系。
这个事实对人类来说如此自然,以至于我们几乎意识不到它。但对机器来说,这是一道必须正面回答的难题:如果你要让模型理解语言,你就必须让它学会词与词之间的关联。而要关联,就必须先"看见"对方。
想象一个极端的情况:如果模型每次只看一个词,它永远不知道"他"指代谁,永远分不清"银行"是河岸还是金融机构,永远无法判断"这个苹果很好吃"和"这个苹果出了新系统"里的"苹果"不是同一个东西。它就退化成了一本字典——知道每个词的统计含义,但不知道它们如何彼此作用。
所以,任何试图理解语言的模型,都必须解决一个核心问题:如何让每个token获取全局信息?或者说,如何让每个词"看见"所有其他的词?
这个问题看似简单,却隐藏着一个巨大的陷阱——而那个陷阱,就是L²。
1.2 朴素的梦想:全连接
"让每个词看见所有其他的词"——如果你是一个工程师,第一次听到这个需求,你会怎么做?
最直白的方案就是全连接。既然要让每个token都与所有其他token交互,那就把每个token的向量与所有其他token的向量直接连起来,学一套权重,让信息自由流动。
具体来说,假设序列长度为L,每个token用一个d维的向量表示。把所有L个token的向量拼接成一个长向量,维度是L×d。然后对这个长向量做一次线性变换,输出同样是L×d维的向量,这样每个输出的token都融合了所有输入token的信息。
这个线性变换的权重矩阵有多大?(L×d) × (L×d)。
复杂度:O(L²d²)。
纸上谈兵的话,这简直是完美方案——每个token都能直接读取所有其他token的所有维度,没有任何信息遗漏,没有任何近似。
但我们来算一笔账。
以GPT-3为例。它的上下文长度L=2048,隐藏维度d=12288。如果用跨位置全连接,一层全连接的权重矩阵大小是:
(L×d)² = (2048 × 12288)² = 25,165,824² ≈ 6.33 × 10¹⁴
约633万亿个参数。
而整个GPT-3 175B模型的参数量是多少?1750亿。这一层全连接的参数量,是整个模型参数量的3600倍。
一层就炸了,还不算前后的其他层。这就是全连接的命运:在数学上完美,在工程上死亡。
为什么会这样?因为全连接的参数量与序列长度的平方和维度平方同时增长。当L=2048、d=12288时,L和d都不算小,两者相乘再平方,数字直接失控。而语言模型恰恰需要同时处理很多词(L大)和很高的维度(d大),全连接的两面夹击让它注定不可行。
1.3 L²——那个无法回避的幽灵
现在我们可以更清楚地看到L²的含义了。
L²意味着:当序列长度翻倍,计算量翻四倍。当序列长度变成十倍,计算量变成一百倍。当序列长度变成一千倍,计算量变成一百万倍。
从GPT-3的2048个token到当前模型的200万个token,L增长了约1000倍。如果复杂度与L²成正比,那计算量增长了多少?一百万倍。
这是一个令人窒息的数字。摩尔定律每年带来大约2倍的硬件性能提升,但L²只需要序列长度增长41%就能吃掉这一年的全部红利。硬件在追,L²在跑,而且L²跑得更快。
更关键的是,这个平方项不是某个具体算法的缺陷,而是"全局信息交互"这个需求本身的代价。只要你想让N个元素两两交互,你就需要处理N²对关系——这是信息论的硬约束,不是换个算法就能绕开的。
但"绕不开"不等于"必须硬扛"。就像光速不可超越,但工程师可以通过优化路径、减少冗余、利用近似来让系统在光速限制下仍然高效运转。大模型领域也是如此——L²是天花板,但天花板下面还有巨大的空间可以挖掘。
事实上,大模型发展的所有关键技术,都可以理解为对L²的不同应对策略:
- 注意力机制:用动态权重替代固定全连接,从O(L²d²)降到O(L²d)——L²还在,但d²没了
- 稀疏注意力:扔掉大部分边,只保留"重要的"边——L²被截断
- 线性注意力:改变计算顺序,绕过L×L矩阵——L²被消解
- 状态空间模型:用固定大小的隐状态压缩历史——完全不依赖L²的交互模式
每一次突破,都是对L²的一次不同角度的进攻。有些是正面强攻(降低复杂度阶数),有些是迂回包抄(改变交互方式),有些是釜底抽薪(跳出注意力框架)。
在接下来的章节中,我们将逐一走进这几次博弈的战场,看看每一方是如何出招的,赢得了什么,又牺牲了什么。
第二章 第一次博弈——注意力机制的诞生
2.1 一个精妙的替代方案
2017年,Google Brain的团队发表了一篇论文,标题只有一句话:Attention Is All You Need。他们提出了Transformer架构,用注意力机制替代了此前主流的循环神经网络(RNN)和卷积神经网络(CNN)。
论文的核心贡献之一,是多头自注意力机制(Multi-Head Self-Attention)。它的计算复杂度是O(L²d)——比全连接的O(L²d²)少了一个d²因子,但L²还在。
这个d²是怎么省掉的?关键在于注意力权重的生成方式。
在全连接中,每对token之间的连接权重是独立学习的参数——第i个token到第j个token、第k个输出维度的权重,与到第j'个token、第k'个输出维度的权重,是完全独立的。所以参数量与L²d²成正比。
而在注意力机制中,每对token之间只有一个权重——注意力分数。这个分数是一个标量,不是d维的向量。它是通过Query和Key的点积动态算出来的,不是预先学好的固定参数。
参数量与L无关——这是注意力的魔法所在。不管你的序列有多长,注意力层的参数矩阵(W_Q、W_K、W_V)的大小始终是d×d。序列从2048变成200万,参数量一分钱不多。
但L²还在。因为注意力分数虽然有L×L个,不需要学,但需要算。而每一次计算都涉及d维向量的点积,所以总的计算量是O(L²d)。
这是第一次博弈的成果:L²d²降到了L²d,砍掉了一个d因子。看起来只是一步,但这一步的意义极其深远——它让Transformer在L较小时变得完全可行,而在此之前,全连接甚至连这个"较小"的场景都撑不住。
2.2 注意力到底做了什么——从"全连接"到"加权求和"
要真正理解注意力机制省下的那个d因子是怎么来的,我们需要回到一个更根本的问题:注意力到底做了什么?
先看全连接。假设我们有L个token,每个token是一个d维向量。我们想让第i个token的新表示依赖于所有其他token。全连接的做法是:对于第i个token的每一个输出维度,都学习一组L×d的权重,让这个输出维度与所有token的所有d个维度相连。
换句话说,全连接是"每个维度分别连"。第i个token的第1个输出维度,通过一组独立的权重,与所有L个token的所有d个维度相连;第2个输出维度又是另一组独立的权重,再与所有L×d个输入相连……依此类推,d个输出维度各自连各自的,互不共享。
这就是O(L²d²)的来源——L²对token之间的关系,d²对维度之间的关系,两者完全独立地叠加。
注意力的关键转变在于:它不再对每个维度独立学习连接权重,而是先为每对token算一个标量权重(注意力分数),然后用这个权重对Value向量做加权求和。
一句话说清:全连接是"每个维度分别连",注意力是"先算一个权重,再把向量加起来"。
具体来说,注意力分三步:
第一步,算注意力分数。对于第i个token(Query)和第j个token(Key),计算一个标量:q_i · k_j。这是一个d维点积,计算量O(d)。
第二步,对所有L个token做softmax归一化,得到L个注意力权重。这些权重加起来等于1,表示第i个token对其他所有token的"关注度"。
第三步,用这L个权重对所有token的Value向量做加权求和:output_i = Σ_j α_ij × v_j。这里α_ij是标量,v_j是d维向量,加权求和的结果仍然是一个d维向量。
关键就在第三步。注意力权重α_ij是一个标量——一个数,不是一个d维向量。同一个标量权重同时作用于Value的d个维度。也就是说,d个维度"共享"了L²的连接开销。
全连接里,每对token之间有d×d个独立参数(每个输出维度到每个输入维度各一个);注意力里,每对token之间只有一个标量权重。从d×d到1,这就是d²变成1的过程。但这个标量权重作用于d维Value,所以总的计算量从O(L²d²)变成了O(L²d)——省掉了一个d因子。
注意力矩阵A的大小是L×L——L²的幽灵第一次显形。但注意,它不再是(Ld)×(Ld)的庞然大物,而是一个"薄薄"的L×L矩阵。更关键的是,这个矩阵不是学出来的固定参数,而是通过Q和K的动态点积算出来的——参数量与L无关。
2.3 第一次博弈的战果
Transformer在2017年诞生后,迅速席卷了自然语言处理领域。BERT(2018)用Transformer的编码器做文本理解,GPT-2(2019)用Transformer的解码器做文本生成,此后几乎所有的语言模型都建立在Transformer之上。
标准注意力在L较小时运转良好。以GPT-3为例,L=2048,d=12288,标准注意力一次前向传播的浮点运算量约为515亿次。对于现代GPU来说,这是完全可以承受的负担。
515亿对比633万亿——全连接的参数量是注意力计算量的12200倍。这就是Transformer存在的理由:它用注意力替代全连接,在L=2048这个规模上,让"每个词看见所有词"从理论上的不可能变成了工程上的现实。
但L²还在。O(L²d)意味着计算量仍然随序列长度的平方增长。在L=2048时,515亿次运算看起来很轻松;但如果L变成200万呢?
515亿 × (2000000/2048)² ≈ 49152万亿。
从515亿到49152万亿,增长了近一百万倍。这就是L²的恐怖之处——它在L小时温顺得像只绵羊,在L大时凶猛得像头猛兽。
第一次博弈赢了第一仗,但L²还在暗处等待。它在等L变大。
第三章 L²的反扑——上下文窗口的扩张困境
3.1 更长的上下文,更强的能力
为什么我们需要更长的上下文窗口?
答案很简单:因为现实世界的信息不会乖乖地打包成2048个token。
一个典型的技术文档可能有几万字,一次深入的技术讨论可能跨越几十轮对话,一个代码仓库可能有数十万行。如果模型只能"记住"2048个token,那它读完一段就忘了另一段,回答问题时必须反复翻看——这不仅仅是效率问题,而是能力问题。很多推理任务本质上依赖长距离的信息整合:前面的假设影响后面的结论,开头的定义决定结尾的判断。窗口太短,这些关联就断了。
所以,扩大上下文窗口几乎是必然的趋势。从GPT-3的2K,到GPT-4的32K/128K,到Claude的200K,再到Gemini 1.5 Pro的2M——每一步扩张都带来了质的飞跃。2K窗口的模型只能处理短文本,128K窗口的模型可以读完一篇论文,2M窗口的模型可以消化整本书甚至整个代码库。
但每一步扩张,L²都在暗中加倍收税。
回顾一下标准注意力的计算量:O(L²d)。当L翻倍,计算量翻四倍。当L从2048增长到128K(增长约64倍),计算量增长约4096倍。当L进一步增长到200万(增长约1000倍),计算量增长约一百万倍。
这不是渐进式的压力,而是指数级的碾压。硬件性能每年提升大约2倍,但L从2K到2M带来了一百万倍的计算需求增长——硬件根本追不上。
3.2 算一笔200万窗口的账
让我们把数字摆出来,直观感受一下L²的压迫感。
以GPT-3的维度(d=12288)为基础,假设上下文窗口扩展到200万token:
标准注意力的计算量:
O(L²d) = (2,000,000)² × 12288 = 4 × 10¹² × 1.2288 × 10⁴ ≈ 4.92 × 10¹⁶
约49152万亿次浮点运算。
线性注意力的计算量(作为对比,我们将在第五章详细讨论):
O(Ld²) = 2,000,000 × (12288)² = 2 × 10⁶ × 1.51 × 10⁸ ≈ 3.02 × 10¹⁴
约302万亿次浮点运算。
标准注意力是线性注意力的163倍。
更触目惊心的是显存。标准注意力需要存储L×L的注意力矩阵A。当L=200万时:
2,000,000 × 2,000,000 = 4 × 10¹² 个元素
即使每个元素只用2字节(FP16),也需要8TB的显存。而目前最顶级的GPU(如NVIDIA H100)的显存是80GB。8TB / 80GB = 100张GPU,仅仅存储一个注意力矩阵就需要100张H100。
这还是一层、一个注意力头的情况。GPT-3有96层,每层96个头。当然,实际工程中不会真的存储完整的注意力矩阵,但这个数字足以说明问题:当L大到一定程度,标准注意力的L²项会让计算和存储同时爆炸。
3.3 L²的两种形态
L²的威胁不仅体现在计算量上,还体现在显存上。这是两种不同但相互交织的瓶颈。
计算瓶颈是直接的:O(L²d)的浮点运算量随L平方增长。在L=2048时,515亿次运算可以接受;在L=200万时,49152万亿次运算需要巨大的算力集群。即使并行度无限,单个token的延迟也会随L线性增长(因为每个token需要与所有L个token计算注意力分数),这在推理时尤其致命。
显存瓶颈更加隐蔽但同样致命:L×L的注意力矩阵随L平方增长。训练时需要存储这个矩阵以计算梯度,推理时需要存储KV Cache(虽然KV Cache是O(Ld)而非O(L²),但在大批量推理时同样会成为瓶颈)。
FlashAttention(2022)解决了一部分显存问题。它的核心思路是:不让注意力矩阵完整驻留在GPU的高速缓存(SRAM)中,而是分块计算,算完一块就丢弃,只在需要时重新计算。这样显存占用从O(L²)降到了O(L),但计算量仍然是O(L²d)——它只是让同样的计算更高效地利用硬件,并没有改变算法本身的复杂度。
这就像用更聪明的方式烧同样的燃料——省油,但不省路程。真正要驯服L²,必须在算法层面动刀:要么减少交互的边(稀疏注意力),要么改变计算的顺序(线性注意力),要么完全跳出注意力的框架(状态空间模型)。
L²的反扑已经到了不得不应战的地步。接下来的三章,我们将分别走进三次博弈的战场。
第四章 第二次博弈——稀疏注意力:不看所有人,只看重要的
4.1 核心思想:减少交互的边
L个token两两交互,共有L×L条边。标准注意力要计算所有这些边的权重,所以复杂度是O(L²d)。
稀疏注意力的思路非常直觉:真的需要所有L²条边吗?也许大部分token对之间根本不需要直接交互——第1个token和第1000个token,如果它们之间隔着999个token,也许通过中间token间接传递信息就够了。
于是问题从"如何高效地计算所有边"变成了"保留哪些边"。不同的回答催生了不同的稀疏模式,这是第二次博弈的起点。
4.2 滑动窗口注意力——只看邻居
最直觉的稀疏化方案:每个token只关注附近w个邻居。
这就像读书时,你的目光一次只扫过几个词,而不是同时盯着整页。w被称为窗口大小,通常是一个常数,比如256或512。
边数从L²降到L×w(每个token只连w条边),复杂度从O(L²d)降到O(Lwd)。当w为常数时,复杂度等价于O(Ld)——终于线性于L了。
这是一个巨大的进步。但代价也很明显:远处的token完全看不到。窗口外的信息被一刀切断,长距离依赖断裂。第1个token和第1000个token之间,没有任何直接的信息通路。
当然,通过多层堆叠,信息可以间接传递——第1层token 1看到token 1-256,第2层每个位置融合了256个邻居的信息,相当于有效感受野扩大到512……依此类推,经过k层,有效感受野约为k×w。如果w=256,经过8层,感受野约为2048——刚好覆盖一个中等长度的序列。
但这个间接传递是有代价的:信息每经过一层就会衰减一次,就像传话游戏,传的层越多,信息越失真。而且,如果需要跨越10000个token传递信息,需要的层数与窗口大小和序列长度都有关系,可能需要非常深的网络。
代表模型:GPT-3和Mistral等模型在推理时使用滑动窗口来控制KV Cache的大小,Longformer将滑动窗口作为基础注意力模式。
4.3 分解注意力——把注意力拆成两个方向
OpenAI在2019年提出的Sparse Transformer给出了另一种思路:与其让每个token同时看行和列上的所有token,不如把注意力拆成两个方向,交替进行。
具体来说,第一种注意力让每个token关注"同一行"的所有token——这里的"行"是把序列按固定长度分块后,同一块内的所有token。这相当于局部注意力,每个token只看自己所在的句子或段落。
第二种注意力让每个token关注固定间隔的token——比如每隔k个位置取一个,形成一种"步幅"模式。这相当于一种全局的稀疏采样,让token能够跳跃性地获取远处的信息。
两种注意力交替堆叠在不同的层中:第一层用行注意力,第二层用步幅注意力,第三层又用行注意力……这样,行注意力负责捕获局部关系,步幅注意力负责建立全局连接。经过若干层后,信息可以在行和列两个方向上间接流通,实现类似全连接的覆盖效果。
复杂度:O(L√L × d),介于O(Ld)和O(L²d)之间。它比标准注意力高效,但没有达到线性。
代表模型:Sparse Transformer,主要用于图像生成(如像素级图像建模)和音乐生成等需要处理长序列的任务。它的分解思想影响了后来很多稀疏注意力的设计。
4.4 局部+全局混合——关键token看所有人
滑动窗口有一个明显的弱点:远处的token完全看不到,只能靠多层间接传递。那如果我们允许少数"特权"token看到所有人呢?
这就是Longformer的核心方案。大多数token只看局部窗口,但少数"全局token"(比如[CLS]标记、段落开头标记、问题token等)可以看到序列中的所有token。全局token充当信息中转站——远处的token把信息汇聚到全局token,全局token再把整合后的信息分发给其他token。
BigBird进一步扩展了这个思路,提出了三段式稀疏模式:
- 局部窗口注意力:每个token看附近的w个邻居——保证局部信息
- 全局注意力:少量token看到所有人——保证长距离信息流通
- 随机注意力:每个token随机关注几个远处的token——打破确定性稀疏模式的局限,增加信息流通的多样性
随机连接看似随意,实际上有重要的理论意义。图论中的随机图有一个经典结果:只要每个节点随机连少量边,整个图就能以高概率连通。随机注意力利用了同样的原理——少量的随机连接就能让稀疏图变得"足够连通"。
复杂度:O(Lwd + g×L×d),其中w是窗口大小,g是全局token数量。通常w和g都是常数或远小于L,所以整体接近O(Ld)。
代表模型:Longformer、BigBird。Longformer在长文档分类和问答任务上表现优异,BigBird进一步将可处理序列长度推到了4K-8K(在当时的硬件条件下已经是突破)。
4.5 膨胀注意力——间隔采样,扩大感受野
滑动窗口的感受野受限于窗口大小w。如果想扩大感受野,直接增大w会增加计算量。有没有办法在不增加边数的情况下扩大感受野?
膨胀注意力借鉴了膨胀卷积(Dilated Convolution)的思想。它的做法是:每个token不是看连续的w个邻居,而是看间隔r步的w个token。r称为膨胀率。
举例来说,如果w=3,r=1(普通滑动窗口),token 10看到的是token 9、10、11。如果r=2,token 10看到的是token 6、8、10。如果r=4,token 10看到的是token 2、6、10。
有效感受野从w扩大到了r×w,但边数不变——仍然是每个token连w条边。
更有趣的是多膨胀率的叠加。不同的层使用不同的膨胀率:第一层r=1(看紧邻),第二层r=2(看每隔一个),第三层r=4(看每隔三个)……这类似于小波变换中的多尺度分析——低层捕获细粒度的局部模式,高层捕获粗粒度的全局结构。
复杂度:与滑动窗口相同,O(Lwd),但有效感受野大幅增加。
代表模型:Longformer中结合了dilated attention,Codec-Attention等研究也探索了类似思路。
4.6 LSH注意力——让相似的token自动找到彼此
前面几种稀疏模式都有一个共同特点:哪些边保留、哪些边丢弃,是人为设计好的。滑动窗口保留局部边,分解注意力保留行列边,混合模式保留局部+全局+随机边——这些都是研究者根据先验知识预设的模式。
但有没有一种方法,让模型自己决定看谁?
Reformer(2020)给出了一个答案。它的思路是:与其人工设计稀疏模式,不如让token自己找"该看谁"。具体机制是局部敏感哈希(Locality-Sensitive Hashing,LSH)。
LSH的核心性质:相似的向量更可能被哈希到同一个桶里。Reformer利用这一点,把Query和Key通过LSH分到若干个桶中,然后每个token只与同一桶内的token交互。相似的token自然聚在一起,不相似的token被分到不同的桶——这相当于一种数据驱动的自适应稀疏模式。
复杂度:O(L×b×d),b为桶大小,通常b远小于L。理论上可以达到O(L log L × d)。
优点:稀疏模式是动态的、随数据变化的,不需要人工设计。对于某些数据分布(如token之间天然存在聚类结构),LSH可以非常高效。
缺点:哈希有碰撞(不相似的token被分到同一桶)和遗漏(相似但应该关注的token被分到不同桶)。"相似"也不等于"需要关注"——两个token语义上可能很近,但在当前上下文中并不需要交互。实际加速往往不如理论预期。
代表模型:Reformer。
4.7 第二次博弈的战果与代价
稀疏注意力证明了:不需要L²条边也能做很多事。通过精心选择保留哪些边,模型可以在大幅降低计算量的同时,仍然保持相当强的语言理解能力。
各种稀疏模式可以归纳为三类策略:
固定模式——滑动窗口、分解、膨胀。简单、可预测、易于实现,但死板。它们对数据不做区分,不管输入是什么,稀疏模式都一样。这意味着它们可能保留了不需要的边,也可能丢掉了重要的边。
混合模式——局部+全局+随机。平衡了局部精度和全局覆盖,但依赖人工设计。全局token的选择、窗口大小的设定、随机连接的比例——这些都是超参数,需要调优。而且,对于不同的任务和不同的数据分布,最优的混合方案可能不同。
动态模式——LSH哈希。灵活、数据驱动,但不够稳定。哈希的随机性意味着同样的输入在不同次计算中可能产生不同的稀疏模式,这在需要确定性的场景中是个问题。而且"相似即可见"的假设并不总是成立。
三类策略的共同代价是:丢弃边意味着丢弃信息。被扔掉的那条边,可能恰恰是某个长距离依赖所必需的。多层间接传递可以部分弥补,但信息在传递过程中会衰减和失真——就像传话游戏,传的人越多,信息越走样。
"不看所有人"是一条不得已的退路。它牺牲了信息完整性来换取计算可行性。但如果能在不丢边的情况下降复杂度呢?如果能让每个token仍然有机会"看到"所有其他token,只是用更聪明的方式去计算呢?
这就引出了第三次博弈。
第五章 第三次博弈——线性注意力:改变计算顺序
5.1 标准注意力的计算瓶颈
标准注意力的计算公式是:
Attention(Q, K, V) = softmax(QK^T)V
瓶颈就在中间那一步:QK^T。
Q是L×d的矩阵,K也是L×d的矩阵。QKT是L×L的矩阵——这就是L²的物理化身。每个元素需要d次乘加,所以计算QKT需要O(L²d)次运算。之后还要乘以V,又需要O(L²d)次运算。总共O(L²d)。
能不能不先算这个L×L的矩阵?
这个问题看似无解——注意力权重本来就是L×L的,你不算这个矩阵,怎么得到注意力权重?但线性注意力给出了一个出人意料的答案:你可以不先算它,而通过改变乘法顺序,绕过这个L×L的中间结果。
5.2 关键洞察:改变乘法顺序
让我们仔细看标准注意力的矩阵乘法链:
softmax(QK^T)V
这实际上是三个矩阵的连乘:(L×d)×(d×L)×(L×d)。按照标准的从左到右的顺序,先算QK^T得到L×L的矩阵,再乘V。中间那一步产生了L²。
但矩阵乘法满足结合律。如果我们暂时忽略softmax(这是一个关键问题,稍后讨论),计算顺序可以改为:
Q(K^TV)
先算K^TV:这是(d×L) × (L×d),结果是d×d的矩阵。
再算Q(K^TV):这是(L×d) × (d×d),结果是L×d的矩阵。
L×L的中间结果消失了!
复杂度的变化:
- K^TV:d×d的矩阵,每个元素是L次乘加,总共O(Ld²)
- Q(K^TV):L×d的矩阵,每个元素是d次乘加,总共O(Ld²)
- 总复杂度:O(Ld²)
从O(L²d)降到O(Ld²)——L²消失了。
这个结果令人震惊。仅仅改变了乘法的顺序,复杂度就从关于L的二次方变成了关于L的一次方。当L远大于d时(比如L=200万,d=12288),这个差距是巨大的。
但等一下——softmax怎么办?
标准注意力中的softmax不是可有可无的装饰。它把QK^T的原始分数归一化为概率分布,确保每个token对所有其他token的注意力权重之和为1,而且权重非负。这对于注意力的合理性至关重要——没有softmax,注意力权重可能是负数,也可能任意大,模型的训练会变得不稳定。
softmax的问题在于它是非线性函数,不能简单地移到括号外面。softmax(QK^T)不等于Q × softmax(KT),因为softmax是逐行作用于QKT的每一行的,无法分解为对Q和K分别操作。
线性注意力的解决方案是:用核函数近似softmax。
核方法的核心思想:找一个特征映射φ,使得softmax归一化后的点积可以近似为φ(q)·φ(k)的内积。这样注意力公式就变成:
Attention(Q, K, V) ≈ φ(Q) × [φ(K)^T × V]
中间的φ(K)^T × V是d×d的矩阵,与L无关。计算顺序与之前相同:先算中间的小矩阵,再乘以Q。
不同的核函数选择产生了不同的线性注意力变体:
Performer(2020)使用随机特征映射(Random Feature Map)来近似softmax核,理论上可以以任意精度逼近标准注意力。
Linear Transformer(2020)使用简单的ELU激活函数+归一化作为特征映射,计算极其高效,但近似精度较低。
Linformer(2020)从另一个角度切入:不改变乘法顺序,而是通过低秩投影把L×L的注意力矩阵压缩为L×r(r≪L),复杂度降为O(Lrd)。
关键洞察:线性注意力在L远大于d时才占优。当L较小时(比如L=2048,d=12288,此时L<d),O(Ld²)反而比O(L²d)更大。以GPT-3的维度为例:
标准注意力:O(L²d) = 2048² × 12288 ≈ 5.15 × 10¹⁰(515亿)
线性注意力:O(Ld²) = 2048 × 12288² ≈ 3.09 × 10¹¹(3093亿)
线性注意力竟然是标准注意力的6倍!这是因为在GPT-3的配置下,d比L大得多,d²项的开销远超L²项。只有当L增长到远超d的时候(比如L=200万),线性注意力才展现出压倒性的优势:
标准注意力:O(L²d) ≈ 4.92 × 10¹⁶(49152万亿)
线性注意力:O(Ld²) ≈ 3.02 × 10¹⁴(302万亿)
163倍的差距。这就是为什么长上下文模型必须拥抱线性注意力或类似的近似方案。
5.3 分组查询:从头的维度减少开销
线性注意力从算法层面改变了复杂度的阶数,但还有一种更"朴素"的优化方式:不改变复杂度阶数,而是减少常系数。分组查询注意力(Grouped-Query Attention,GQA)就是这种思路的代表。
标准的多头注意力(MHA)中,每个头都有独立的Q、K、V。假设有h个头,每个头的维度是d/h,那么每个头都需要独立的K和V。在推理时,所有头的K和V都需要存储在KV Cache中,占用O(L×h×d/h)=O(Ld)的空间——与头数无关,但需要h组独立的K、V投影。
多查询注意力(MQA)提出了一个激进的方案:所有头共享同一组K、V。只有Q是每个头独立的。这样KV Cache只需要存储一组K、V,空间降为O(L×d/h),推理时的显存带宽需求大幅减少。
分组查询注意力(GQA)是两者的折中:把h个头分成g组,每组共享一组K、V。当g=1时就是MQA,当g=h时就是MHA。通过调整g,可以在精度和效率之间灵活权衡。
GQA不是改变算法的复杂度阶数——它仍然是O(L²d)。但它减少了一个重要的常系数:推理时KV Cache的大小和带宽需求。在长上下文推理中,这个常系数的影响可能是决定性的。当L=200万时,KV Cache本身就占据了大量显存,减少几倍的KV存储可能意味着从"装不下"变成"装得下"。
代表模型:LLaMA 2(GQA)、Mistral(GQA)、Gemini(推测使用MQA/GQA变体)。
5.4 第三次博弈的战果与代价
第三次博弈的战果是显著的:上下文窗口成功从2K扩展到1M甚至2M。线性注意力让L=200万时的计算量从49152万亿降到302万亿,节省超过99%。
与第二次博弈的对比可以帮我们更清楚地看到两次博弈的本质差异。
第二次博弈(稀疏注意力)的思路是"丢边"——从L²条边中选一部分保留,其余扔掉。复杂度降低是因为交互变少了,代价是信息不可逆地丢失。被丢弃的边所代表的关系,模型永远看不到,无论后续怎么处理都无法弥补。
第三次博弈(线性注意力)的思路是"换算法"——仍然保留所有L²条边的交互,但用数学变换避免显式计算L×L的矩阵。复杂度降低是因为计算方式的改变,而非交互范围的缩减。每个token仍然有机会"看到"所有其他token,只是"看得不够精确"——softmax被核函数近似,注意力权重的精度下降了。
一个是信息缺失,一个是信息失真。后者通常比前者更容易被模型容忍。信息缺失意味着某些关系完全不存在,模型无从学习;信息失真意味着关系的精度降低,但关系本身还在,模型可以通过训练来适应这种近似。
但两者也有共同的局限:当L较小(如2K-8K)时,标准注意力仍然是最佳选择。稀疏注意力在这个范围丢边太多,线性注意力在这个范围O(Ld²)反而比O(L²d)更大。两次博弈的方案都是为了长上下文而生的,在短序列上都不是最优解。
"近似"与"精确"的张力,成为此后所有方法的核心矛盾。而第四次博弈,将选择一条更激进的道路——彻底跳出注意力的框架。
第六章 第四次博弈——跳出注意力框架
6.1 状态空间模型:不用注意力也能建模序列
前三次博弈都在注意力的框架内打转:标准注意力、稀疏注意力、线性注意力——变的是计算方式,不变的是"每个token通过某种加权方式聚合其他token的信息"这个基本范式。
第四次博弈更激进:它质疑的不是一个算法的细节,而是整个注意力范式本身。它的核心问题是:非要用注意力不可吗?有没有一种完全不同的方式来建模序列?
状态空间模型(State Space Model,SSM)给出了一个肯定的回答。
SSM的灵感来自控制论中的经典状态空间模型。它的核心思想是:维护一个固定大小的隐状态(hidden state),每读入一个新token,就用一个线性变换更新隐状态,然后用隐状态来生成输出。整个过程不需要任何token-to-token的注意力计算,自然也就没有L²的问题。
Mamba(2023)是这一方向的代表。它的复杂度是O(Ld)——线性于L,线性于d。与标准注意力的O(L²d)相比,这不仅在L的方向上降了一个阶,而且整个计算过程是递归的:每个token的处理只依赖于当前的输入和上一步的隐状态,不需要回看所有历史token。
但这里有一个关键问题:如果每个token只依赖上一步的隐状态,那长距离依赖怎么捕获?隐状态的大小是固定的(维度为d),它不可能无限精确地记住所有历史信息。
Mamba的解决方案是选择性扫描(Selective Scan)。与传统的SSM不同,Mamba的参数不是固定的,而是随输入动态变化的——模型学会"记住重要的,遗忘不重要的"。这就像人类阅读:你不会记住每个词,但你会自动地保留关键信息,丢弃冗余细节。
与注意力的本质区别可以这样理解:注意力是"回头看所有历史"——每次需要信息时,都完整地检索一遍历史,精确但昂贵。SSM是"边走边压缩历史"——一边处理一边把信息压缩进固定大小的隐状态,高效但必然有损。
这个区别很像计算机科学中两种经典的数据访问模式:随机访问(可以随时读取任何位置的数据,但需要存储所有数据)和流式处理(数据依次流过,只保留有限的状态,但只能过一遍)。注意力是前者,SSM是后者。
6.2 混合架构:兼得两者的优势
纯SSM在效率上无可挑剔,但在精度上有所妥协——毕竟,固定大小的隐状态不可能完美地记住所有历史信息,尤其是需要精确回溯某些特定token时。
纯注意力则恰好相反:精度无可挑剔,但效率受制于L²。
那能不能两者兼得?
Jamba(2024,AI21 Labs)给出了一个答案:在SSM层中穿插少量注意力层。大多数层使用Mamba的SSM,提供高效的序列建模;每隔若干层,插入一层标准注意力,提供精确的信息回溯。
这个设计在直觉上很合理:大多数情况下,SSM的隐状态已经足够好——上下文信息已经隐含在压缩过的表示中,不需要精确回看。但在某些关键时刻,模型需要精确地引用某个具体的token(比如"上面提到的那个数字是多少"),这时注意力层就能发挥作用。
混合架构的复杂度取决于注意力层的比例。如果只有1/8的层使用注意力,那注意力的L²开销也相应减少到1/8。更重要的是,注意力层不需要每个token都看所有人——由于SSM层已经做了大部分信息整合,注意力层只需要做"校准"式的精确回看,可以进一步降低开销。
未来可能的方向:不是注意力 vs SSM,而是如何混合。注意力层的比例、位置、窗口大小,都可以作为可调的设计参数。甚至在训练过程中动态决定哪些层用注意力、哪些层用SSM,也是一个有趣的研究方向。
6.3 循环与回溯
线性注意力和SSM之间有一个深层的联系,可以通过"循环视角"来理解。
回顾线性注意力的公式:Attention(Q, K, V) ≈ Q(KTV)。如果我们把KTV的计算拆开,逐token累加:
S_t = S_{t-1} + k_t × v_t^T
其中S_t是第t步的累积状态矩阵(d×d),k_t是第t个token的Key向量,v_t是第t个token的Value向量。输出则为:
output_t = q_t × S_t
这个递推形式与SSM惊人地相似!S_t就相当于SSM中的隐状态,每步用一个线性变换更新。区别在于:SSM的隐状态更新是参数化的(有可学习的矩阵A、B、C),而线性注意力的"隐状态"更新是无参数的(直接累加k×v^T)。
这个联系意味着:线性注意力本质上就是一种特殊的循环模型,只是它的循环不是按时间步展开的,而是通过矩阵乘法并行计算的。在训练时,你可以用O(Ld²)的并行方式计算;在推理时,你可以像RNN一样逐步处理,每步只需O(d²)的计算。
RWKV(2023,Bo Peng)正是沿着这条思路设计的。它用时间衰减(time decay)替代注意力权重——越远的token,权重越小,衰减速度由可学习的参数控制。在推理时,RWKV像RNN一样逐步处理,只需要维护固定大小的隐状态,不需要存储所有历史token的KV Cache。在训练时,它可以展开为并行计算的形式,不损失训练效率。
RWKV的复杂度:训练时O(Ld²)(与线性注意力相同),推理时O(d²) per token(与RNN相同),O(Ld)总计。推理时的内存占用与序列长度无关——这是一个巨大的优势,特别是在长上下文推理场景中。
6.4 第四次博弈仍在进行
第四次博弈的方向是清晰的:跳出注意力框架,寻找完全不受L²约束的序列建模方式。但战果尚未完全确定。
SSM和混合架构在大规模上的验证还在进行中。Mamba在中小规模(数亿到数十亿参数)上展示了与Transformer相当甚至更好的性能,但在千亿参数规模上,是否仍然能够保持竞争力,目前还没有定论。注意力仍然是当前最强模型(GPT-4、Claude、Gemini等)的基石——这些模型在性能上的优势,可能部分来自于注意力机制的精确信息回溯能力。
但L²的压力只增不减。上下文窗口的扩张趋势不会停止:1M → 10M → ?当L增长到千万甚至亿级别时,任何L²的项都会变成不可承受的负担。到那时,注意力框架内的所有优化(稀疏、线性、分组查询)可能都不够用,必须依赖完全线性于L的架构。
第四次博弈的胜负尚未分晓,但战场已经铺开。下一次突破,可能来自一个我们还没有想到的方向。
第七章 L²之外——大模型发展的其他维度
7.1 参数规模:d的增长
在注意力复杂度O(L²d)中,L²是主角,d是配角。但配角的增长同样值得关注。
从GPT-2的d=768,到GPT-3的d=12288,再到更大模型的隐藏维度,d的增长虽然只是线性的,但叠加L²之后仍然很重。当L=2048、d=12288时,L²d ≈ 5.15 × 10¹⁰;当d翻倍到24576时(假设L不变),L²d ≈ 1.03 × 10¹¹——翻了一倍。看起来不多,但这是每层每个注意力头的开销,乘上层数和头数之后,绝对值相当可观。
更关键的是,d的增长不仅仅影响注意力——它影响模型的每一个组件。FFN的参数量是4d²(升维4倍再降回来),嵌入层的参数量是词表大小×d,每一层的总参数量与d²成正比。所以d的增长会让整个模型变贵,不仅仅是注意力层。
混合专家(Mixture of Experts,MoE)是应对d增长的一个重要思路。MoE的核心想法是:模型虽然总参数很多,但每次推理只激活其中的一部分(专家)。这样,虽然"纸面"参数量很大,实际计算量可以保持较小。
GPT-4、Mixtral等模型都采用了MoE架构。GPT-4的具体参数量未被官方公开,但普遍认为它是一个万亿参数级别的MoE模型,每次推理只激活其中的一小部分参数。Mixtral 8×7B有8个专家,每次激活2个,实际推理计算量约等于一个13B的稠密模型。
MoE没有改变注意力复杂度的阶数——注意力层仍然是O(L²d)或O(Ld²)——但它让d的增长不再等比例增加实际计算量。这使得模型可以在不爆炸性增加推理成本的前提下,拥有更大的总容量。
7.2 训练数据:从更多到更好
训练数据虽然不是L²的直接维度,但它与上下文窗口的扩张密切相关。
Kaplan等人2020年提出的缩放定律(Scaling Laws)揭示了一个重要规律:模型的能力主要取决于三个因素——参数量、数据量和计算量。三者需要协调增长,偏废任何一个都会导致性能瓶颈。
当上下文窗口从2K扩大到200万时,训练数据的组织方式需要相应改变。传统的训练数据是短文本片段(几千个token),模型在训练时从未见过超长序列,推理时面对长文本自然力不从心。长上下文训练需要构造超长的训练样本,这对数据收集和预处理提出了更高的要求。
长上下文训练还面临一个特殊的计算挑战:训练时需要在每个训练步骤中处理超长序列,而L²会让每一步的耗时暴增。所以长上下文训练的成本不仅仅是"更多的数据",更是"更贵的数据"。
一个折中方案是渐进式训练:先用短序列训练大部分能力,再逐步增加序列长度进行微调。这样可以用相对低廉的成本完成大部分训练,只在最后的阶段才承担L²的额外开销。
7.3 推理效率:KV Cache与内存墙
L²的问题不仅仅存在于训练阶段,推理阶段同样面临挑战——虽然挑战的形式不同。
推理阶段的主要瓶颈不是L²的计算量(因为自回归生成时每次只生成一个token,注意力计算是O(Ld)而非O(L²d)),而是KV Cache的存储和读取。
KV Cache是什么?在自回归生成时,模型需要存储所有已生成token的Key和Value向量,以便新token计算注意力。这些Key和Value的总量是O(Ld)——随序列长度线性增长。看起来不是L²的问题,但L的线性增长在实际中同样令人头疼。
以L=200万、d=12288、FP16精度为例,一个注意力头的KV Cache大小:
2,000,000 × 12288 × 2字节 × 2(K和V)≈ 98 GB
一个头就快100GB了。如果有96个头(GPT-3的配置),KV Cache总量约9.4TB。这显然不可能存在一张GPU的显存里。
即使使用GQA(比如8组共享K、V),KV Cache仍然需要约785GB。再考虑批处理(同时服务多个请求),显存需求进一步倍增。
这就是推理阶段的"内存墙":计算能力在增长,但显存带宽和容量的增长远远跟不上。模型推理的速度往往不是受限于计算(GPU的TFLOPS),而是受限于数据搬运(显存带宽的GB/s)。
针对这个问题,工程界发展了一系列优化方案:
PagedAttention(vLLM):借鉴操作系统的虚拟内存分页机制,把KV Cache分成固定大小的页,按需分配和回收,避免显存碎片,提高利用率。
KV Cache量化:把Key和Value从FP16(16位)压缩到INT8(8位)甚至INT4(4位),显存占用减半或减至1/4,代价是精度损失。
投机解码(Speculative Decoding):用一个小模型快速"猜测"接下来的几个token,再用大模型并行验证,如果猜测正确就一次接受多个token,加速生成。
这些优化的共同本质是:在精度损失最小的情况下,压缩L的足迹。它们不改变算法的复杂度阶数,但通过工程手段大幅降低了常系数,使得长上下文推理在实践中变得可行。
第八章 终极问题——L²能被彻底消灭吗?
8.1 信息论的下界
经过了四次博弈,我们有了越来越多的工具来应对L²。但一个根本性的问题始终悬在头顶:L²能被彻底消灭吗?
这不是一个纯粹的工程问题,它触及了计算与信息的深层关系。
设想一个最基本的需求:N个元素,每个元素都需要与其他所有元素交换信息。这意味着N²对关系需要被处理。无论你用什么算法——注意力、SSM、还是尚未发明的某种机制——只要你需要精确地处理所有N²对关系,复杂度就不可能低于O(N²)。
这有点像排序问题的下界:N个数排序至少需要O(N log N)次比较,这是信息论的硬约束,不存在O(N)的排序算法(对于一般的比较排序)。全局信息交互的下界是O(N²),同样是信息论的硬约束。
精确的全局注意力可能是计算上的最优解——如果算力无限的话。它直接处理所有N²对关系,没有任何遗漏和近似,信息流通的完整性得到了保证。问题不在于注意力本身,而在于N²的绝对量太大。
所以,L²不能被"消灭",只能被"绕过"。绕过的方式只有两种:要么接受近似(不精确地处理所有关系),要么接受遗漏(不处理所有关系)。所有降低复杂度的方法,本质上都在这两者之间做选择。
8.2 近似与精确的永恒张力
回顾四次博弈,每一次都是在"近似"和"精确"之间寻找平衡。
第一次博弈(标准注意力):用动态权重替代全连接,复杂度从O(L²d²)降到O(L²d)。这不是近似,而是对问题结构的利用——同一对token的注意力权重共享于d个维度。但L²仍然保留,精确性完整。
第二次博弈(稀疏注意力):丢弃大部分边。这是明确的近似——"不看"意味着"不知道",信息缺失。代价取决于丢弃的边中包含多少关键信息。对于许多自然语言任务,局部信息已经足够,所以稀疏注意力在实践中表现不错。但在需要精确长距离引用的场景(如"第十页第三个表格的第二行数据"),信息缺失就会导致性能下降。
第三次博弈(线性注意力):用核函数近似softmax。这是另一种近似——"看到了但不精确"。每对token之间仍然有交互,但交互的权重不再是softmax的精确值,而是核函数的近似值。信息失真,但不是信息缺失。
第四次博弈(SSM):用固定大小的隐状态压缩历史。这是一种更激进的近似——历史信息被压缩到d维的隐状态中,必然有损。但这种压缩是可学习的,模型可以学会保留重要的信息,丢弃不重要的。与稀疏注意力的"硬截断"不同,SSM的压缩是"软"的、连续的。
一个值得思考的问题:智能是否需要"精确的全局注意力"?
人类阅读也不是逐字扫描全文。你读一本书时,并不会在每句话上都精确地回忆前面所有的句子。你的大脑在做某种高效的"稀疏注意力"——关注重要的,忽略不重要的,偶尔需要精确回看时才翻回去找。
也许大模型也不需要精确的全局注意力。也许某种"足够好"的近似就足以支撑智能。这个问题的答案,可能决定了L²是否真的需要被"消灭"。
8.3 硬件与算法的协同进化
到目前为止,我们主要从算法的角度讨论L²的应对策略。但硬件层面的创新同样重要,而且常常与算法创新交织在一起。
FlashAttention(2022)是一个经典案例。它没有改变注意力算法本身——仍然是softmax(QK^T)V,复杂度仍然是O(L²d)。但它通过精细的GPU内存管理,把注意力计算的硬件利用率提升了2-4倍。具体来说,FlashAttention把Q、K、V分成小块,在GPU的高速SRAM中完成注意力的计算,避免了在全局显存(HBM)中存储完整的L×L注意力矩阵。
FlashAttention的意义在于:它证明了"不改算法,改硬件利用率"也可以大幅推进L²的边界。在算法创新遭遇瓶颈时,硬件友好的实现可以买来更多的时间。
专用芯片是另一个方向。GPU是通用计算设备,它的设计并不专门为注意力计算优化。TPU(Google)的矩阵乘法单元更适合大规模的注意力计算,NPU和其他专用芯片也在探索更高效的注意力实现。但专用芯片能改变的是常数因子,不是复杂度阶数——O(L²d)在TPU上仍然是O(L²d),只是跑得更快。
所以,算法创新与硬件创新的关系更像是协同进化,而非单方面驱动。算法创新(线性注意力、SSM)打开了新的可能性,硬件创新(FlashAttention、专用芯片)让现有算法跑得更远。两者交替推进,共同拓展着L²的边界。
一个有趣的问题:如果未来的硬件能够提供O(N²)量级的并行计算能力(比如光子计算或量子计算),L²是否就不再是问题了?答案是:可能。但那样的硬件目前还远未成熟,在此之前,算法层面的创新仍然是最现实的出路。
8.4 展望
上下文窗口的增长不会停止。
从2K到200万,窗口已经扩大了1000倍。但人类的知识工作者常常需要处理远超200万token的信息——一个大型代码库可能有上亿行代码,一个完整的法律案例库可能有数十亿个token。要达到这个量级,窗口还需要再增长50到500倍,L²相应地需要再增长2500到250000倍。
这意味着,即使线性注意力(O(Ld²))也可能不够用——当L增长到亿级别时,Ld²的绝对量同样不可忽视。SSM(O(Ld))可能是唯一能撑住这个规模的架构,但它的精度是否足够?混合架构能否在精度和效率之间找到最优平衡?
新的数学工具也在孕育中。线性注意力用核方法近似softmax,SSM用选择性扫描替代全局回看——这些都是已有的数学工具在新场景中的应用。未来是否还有未被发现的复杂度降阶方法?数学史上有许多出人意料的降阶案例(比如快速傅里叶变换把O(N²)降到O(N log N)),也许注意力计算也存在类似的"快速算法"。
但无论具体的技术路径如何,一个基本判断似乎不会改变:L²可能永远不会被"消灭",但会被不断"驯服"。每一次博弈都是一次驯服,每一次突破都让L²的阴影退后一步。而L²也在不断反扑——每当我们在一个规模上驯服了它,下一个更大的规模就会出现新的挑战。
大模型的未来,取决于我们与L²的下一场博弈。
后记:从633万亿到515亿
让我们回到开篇的三个数字。
633万亿。515亿。302万亿。
633万亿是跨位置全连接一层权重矩阵的参数量(GPT-3维度,L=2048,d=12288)。它代表了"让每个词看见所有词"这个需求的朴素代价——如果不做任何优化,直接全连接,这就是你要付出的代价。633万亿参数,一张GPU装不下,一个集群训不动,一个公司养不起。全连接在数学上完美,在工程上死亡。
515亿次是标准注意力一次前向传播的浮点运算量。注意力机制用"先算一个权重,再把向量加起来"替代了"每个维度分别连",复杂度从O(L²d²)降到O(L²d),省掉了一个d因子。12200倍的差距,这就是Transformer存在的理由。从633万亿到515亿,不是量变,是质变——它让大语言模型从"不可想象"变成了"可以落地"。
302万亿次是线性注意力在L=200万时的浮点运算量。标准注意力在同样的条件下需要49152万亿次——163倍的差距。改变乘法顺序,绕过L×L的中间矩阵,L²消失了。从515亿到302万亿,这看起来像是倒退(绝对数字更大了),但注意L已经从2048增长到了200万。在L=200万的尺度上,302万亿是"可以承受"的,而49152万亿是"不可能"的。
三个数字,三次跨越,一场仍在进行中的博弈。
每一次跨越背后,都是对L²的一次深刻理解与巧妙应对。第一次,我们理解了L²d²中d²的冗余——同一个权重可以作用于d个维度。第二次,我们理解了L²中大部分边是冗余的——不需要每个token都看所有人。第三次,我们理解了L²不一定需要显式计算——改变乘法顺序就能绕过。第四次,我们理解了L²不是不可替代的——完全可以用不同的范式来建模序列。
理解一层,突破一层。每一次理解都打开了新的可能性,每一次突破都让L²的阴影退后一步。
但L²也在不断反扑。每当我们在一个规模上驯服了它,下一个更大的规模就会出现新的挑战。从2K到200万,我们用了不到五年。从200万到2亿呢?从2亿到200亿呢?L²的增长是无情的——每翻1000倍,计算量就翻100万倍。
这场博弈没有终点,只有不断升级的回合。
而我们之所以还在博弈,是因为"让每个词看见所有词"这件事,值得。语言的本质是关联,理解语言就是理解关联。L²是关联的代价,而关联是理解的前提。只要我们想要机器理解语言——甚至理解世界——我们就必须面对L²。
这不是一个可以回避的问题,但也不是一个令人绝望的问题。从633万亿到515亿,人类已经证明了:深刻的理解可以换来巨大的简化。下一个12200倍的跨越,也许正在某个研究者的笔记本上酝酿。
附录
附录A:关键模型的参数与窗口对照表
| 模型 | 发布时间 | 参数量 | 上下文窗口 | 隐藏维度d | 注意力类型 |
|---|---|---|---|---|---|
| GPT-2 | 2019 | 1.5B | 1,024 | 1,600 | MHA |
| GPT-3 | 2020 | 175B | 2,048 | 12,288 | MHA |
| GPT-4 | 2023 | ~1.8T (MoE) | 128K | 未公开 | 推测GQA |
| LLaMA 2 | 2023 | 7B-70B | 4,096 | 4,096-8,192 | GQA (70B) |
| Mistral 7B | 2023 | 7B | 32K (滑动窗口8K) | 4,096 | GQA |
| Longformer | 2020 | 149M | 4,096 | 768 | 局部+全局 |
| BigBird | 2020 | 1.3B | 8,192 | 2,048 | 局部+全局+随机 |
| Reformer | 2020 | 1.3B | 64K | 1,024 | LSH |
| Performer | 2020 | - | 128K+ | - | 线性注意力(FAVOR+) |
| Gemini 1.5 Pro | 2024 | 未公开 | 2,000,000 | 未公开 | 推测GQA+稀疏 |
| Claude 3 | 2024 | 未公开 | 200,000 | 未公开 | 推测GQA |
| Mamba | 2023 | 130M-2.8B | 无硬限制 | 768-2,560 | SSM (无注意力) |
| RWKV-4 | 2023 | 1.5B-14B | 无硬限制 | 2,048-4,096 | 线性RNN |
| Jamba | 2024 | 52B (MoE) | 256K | 4,096 | SSM+注意力混合 |
注:部分模型的参数为推测值,官方未公开。
附录B:三种复杂度的数学推导
B.1 跨位置全连接:O(L²d²)
输入:L个token,每个d维,拼接为Ld维向量。
权重矩阵:(Ld)×(Ld)。
输出:Ld维向量。
计算量(FLOPs)= (Ld)² = L²d²
以GPT-3参数(L=2048,d=12288):
(2048 × 12288)² = 25,165,824² ≈ 6.33 × 10¹⁴(约633万亿)
B.2 标准多头注意力:O(L²d)
假设单头注意力,Q、K、V均为L×d矩阵。
步骤1:计算S = QK^T
- (L×d) × (d×L) → L×L矩阵
- 每个元素是d次乘加,共L²个元素
- FLOPs₁ = L² × d
步骤2:softmax(忽略,非乘加操作为主)
步骤3:计算softmax(S) × V
- (L×L) × (L×d) → L×d矩阵
- 每个元素是L次乘加,共L×d个元素
- FLOPs₃ = L² × d
总FLOPs = 2L²d,即O(L²d)
以GPT-3参数:
2 × 2048² × 12288 ≈ 1.03 × 10¹¹(约1030亿)
(515亿为单次QK^T或SV的计算量)
B.3 线性注意力:O(Ld²)
核心:改变计算顺序,先算K^TV再乘Q。
步骤1:计算K^TV
- (d×L) × (L×d) → d×d矩阵
- 每个元素是L次乘加,共d²个元素
- FLOPs₁ = L × d²
步骤2:计算Q(K^TV)
- (L×d) × (d×d) → L×d矩阵
- 每个元素是d次乘加,共L×d个元素
- FLOPs₂ = L × d²
总FLOPs = 2Ld²,即O(Ld²)
以GPT-3参数(L=2048,d=12288):
2 × 2048 × 12288² ≈ 6.18 × 10¹¹(约6180亿)
以L=2,000,000,d=12288:
2 × 2,000,000 × 12288² ≈ 6.04 × 10¹⁴(约604万亿)
B.4 对比总结
| 方法 | 复杂度 | L=2048, d=12288 | L=2M, d=12288 |
|---|---|---|---|
| 跨位置全连接 | O(L²d²) | 6.33 × 10¹⁴ | 不可计算 |
| 标准注意力 | O(L²d) | 1.03 × 10¹¹ | 4.92 × 10¹⁶ |
| 线性注意力 | O(Ld²) | 6.18 × 10¹¹ | 6.04 × 10¹⁴ |
注:L=2048时d>l,标准注意力更优;L=2M时L≫d,线性注意力更优。
附录C:注意力变体一览
| 变体 | 核心思路 | 复杂度 | 代表模型 |
|---|---|---|---|
| MHA(多头注意力) | 每个头独立Q、K、V | O(L²d) | GPT-3, BERT |
| MQA(多查询注意力) | 所有头共享K、V | O(L²d),KV Cache减至1/h | PaLM, StarCoder |
| GQA(分组查询注意力) | 每组头共享K、V | O(L²d),KV Cache减至1/g | LLaMA 2, Mistral |
| MLA(多潜在注意力) | K、V压缩到低维潜在空间 | O(L²d),KV Cache大幅减少 | DeepSeek-V2/V3 |
| 滑动窗口注意力 | 每个token只看w个邻居 | O(Lwd) | Mistral, Longformer |
| 分解注意力 | 行/列交替注意力 | O(L√L d) | Sparse Transformer |
| 局部+全局混合 | 窗口+全局token+随机 | O(Lwd + gLd) | Longformer, BigBird |
| 膨胀注意力 | 间隔采样扩大感受野 | O(Lwd) | Longformer |
| LSH注意力 | 哈希分桶,相似token交互 | O(Lb d) | Reformer |
| 线性注意力 | 核方法近似softmax | O(Ld²) | Performer, Linear Transformer |
| 低秩注意力 | 投影到低维 | O(Lrd) | Linformer |
| SSM | 固定隐状态递归 | O(Ld) | Mamba |
| 线性RNN | 时间衰减+循环 | O(Ld) | RWKV |
附录D:术语表
| 术语 | 英文 | 含义 |
|---|---|---|
| Token | Token | 文本被分词后的最小单位,可以是一个词、一个子词或一个字符 |
| 注意力 | Attention | 一种让每个token聚合其他token信息的机制,通过Query-Key-Value计算 |
| 多头注意力 | Multi-Head Attention | 多组并行的注意力计算,每组有不同的投影参数 |
| 自注意力 | Self-Attention | Q、K、V都来自同一序列的注意力 |
| FFN | Feed-Forward Network | 前馈神经网络,逐位置独立应用的两层MLP |
| KV Cache | Key-Value Cache | 推理时缓存已生成token的Key和Value,避免重复计算 |
| 复杂度 | Complexity | 算法所需的计算量或内存量随输入规模增长的关系 |
| 全连接 | Fully Connected | 每个输出维度与所有输入维度相连的线性层 |
| 稀疏注意力 | Sparse Attention | 只计算部分token对之间的注意力,其余丢弃 |
| 线性注意力 | Linear Attention | 用核方法近似softmax,改变乘法顺序消除L²项 |
| 状态空间模型 | State Space Model | 用固定大小隐状态递归建模序列的架构 |
| MoE | Mixture of Experts | 混合专家模型,每次推理只激活部分专家参数 |
| 上下文窗口 | Context Window | 模型一次能处理的最大token数量 |
| LSH | Locality-Sensitive Hashing | 局部敏感哈希,相似向量更可能被分到同一桶 |
| FlashAttention | Flash Attention | 通过分块计算优化GPU内存利用率的注意力实现 |
| GQA | Grouped-Query Attention | 分组查询注意力,多组头共享K、V |
| MQA | Multi-Query Attention | 多查询注意力,所有头共享K、V |
| FLOPs | Floating Point Operations | 浮点运算次数,衡量计算量的单位 |