首页 / 资讯中心 / 文章详情

Transformer核心算法演进:从自注意力到长文本大模型

Transformer核心算法演进:从自注意力到长文本大模型 ★ FEATURED ARTICLE
2017年我读到《Attention Is All You Need》时印象其实是矛盾的。一方面self-attention的全局建模能力确实漂亮另一方面O(n²)复杂度让我下意识觉得这种架构只会停留在中等长度序列上撑不起真正的长文本场景。后来的发展大家都看到了transformer不仅成了NLP的默认底座还一路蔓延到图像、语音、多模态甚至连近年大模型里最核心的算法选型也都围绕transformer架构在不断演进。我想把这几年观察到的“核心算法是如何一步步被改出来的”讲清楚从Q/K/V注意力本身到复杂度优化、位置编码、归一化策略、注意力头配置再到Decoder-only范式。不管你是要做模型训练、推理优化还是单纯想理解大模型底层这条演进线都值得过一次。这里不会只堆结论我会把每一步背后的动机、代价和实际取舍都拆开说。理解这些比记住一堆模型名字更能帮你应对新出的模型。1. 起点问题为什么循环网络会被自注意力取代1.1 RNN序列建模的硬伤远不止“不能并行”先从RNN说起。RNN的致命问题不是简单的不支持并行而是序列建模的方式决定了信息必须沿着时间步逐步传递。每一步隐状态既要表达当前输入又要保留过去的记忆这个隐状态本质上是个“有损压缩瓶口”。LSTM注入门控以后缓解了梯度消失但距离很远的位置之间要经过多层门控复合信号早就衰减或扭曲了。机器翻译里把整句编码成一个向量的做法尤其明显句子越长语义细节越难塞进一个固定向量。比如一篇新闻稿把开头的主语和结尾的时间地点强行压缩到同一个向量里中间的转折关系很容易被平均掉。这个问题不是靠加深循环层就能解决的因为无论堆多少层路径仍然是线性的信息依然要一站一站传下去。真正让序列建模发生质变的是把“路径距离”这个概念直接抹平。Transformer让任意两个token之间都有一条直连路径不需要经过中间token的中转。从信息论视角看这相当于把一条容易衰减的串行信道换成了全连接网络。代价是每条路径都要显式建模相关性于是就有了自注意力那个n×n的相似度矩阵。1.2 Attention机制从辅助走向主角的临界点Attention也不是Transformer原创的。2014年前后Bahdanau等人在神经机器翻译里引入的attention本质上是动态加权源端隐状态让decoder每一步能“按需查阅”源端信息而不是只靠最后一个向量。这个思路解决了一个实际问题但还没有脱离RNN的主干。Transformer的突破在于把attention完全提升到主架构层面每一个位置的表示都通过它与其他所有位置的注意力来生成。于是任意两个token之间的距离被拉到了1长距离依赖不再是经过若干步传播而是直接计算相关性。这在算法设计上是个根本转变用全局检索代替顺序传递同时让所有位置的计算天然可以并行。所以讨论Transformer的核心算法演进起点其实是这个选择为什么要放弃顺序结构答案不是“RNN不好”这么简单而是RNN的串行瓶颈和长程衰减在规模化训练里太吃亏。Transformer把这条路跳过去之后后面所有演进都围绕两个核心问题展开一是如何让注意力更快、更省、能处理更长序列二是如何在保持表达力的同时让训练更稳定。理解了这两个靶子后面所有改进就都能对号入座。2. 自注意力精算Q/K/V设计、缩放点积与多头的数学逻辑2.1 Attention运算中的“查询-键-值”到底在做什么要理解自注意力可以先把它想成一个数据库检索系统。每个输入token经过三套不同的线性变换分别得到查询Query、键Key和值Value。查询是“我想找什么”键是“我身上有什么索引”值是“我实际提供的内容”。某个请求与前一个位置的键越匹配注意力权重越大输出就越偏向前一个位置的值。在自注意力场景中这个机制是模型自己对自己的序列做检索每个token都能根据整个序列的内容决定自己的表示。从实现角度看所有token的Q、K、V可以被组织成矩阵因此可以用矩阵乘法一次算完所有token之间的相似度。这也是并行性的来源不再是逐步计算而是一次性算出一张完整的关系表。具体公式可以写成Attention(Q, K, V) softmax(Q * K^T / sqrt(d_k)) * V矩阵Q和K的每一行对应一个token的查询和键。Q和K的转置相乘得到n×n的相似度分数矩阵softmax把每行归一化成概率分布最后用这些概率对V做加权求和得到每个token的新表示。2.2 缩放因子sqrt(d_k)一个经常被忽略的稳定性设计公式里除以sqrt(d_k)很多入门文章把它当作“经验性技巧”实际上这里藏着训练稳定性的关键。假设Q、K中的元素是均值0、方差1的随机变量那么单个维度乘积的均值是0、方差是1对d_k个维度的点积结果来说方差会累积到d_k。如果不对点积做缩放当d_k变大时点积数值的方差也会变大。Softmax的输入一旦落到两端饱和区梯度会变得非常小模型几乎无法学习。除以sqrt(d_k)可以让点积方差回到1左右让softmax保持在梯度敏感的区间。这是基于随机变量方差性质的推导不是拍脑袋的经验。实际训练中不缩放也能跑通小模型但深层模型和长序列场景下会明显难训。很多复现Transformer失败的项目最后排查下来就是漏了这个因子或者实现时数据类型精度不对。2.3 多头注意力如何让模型同时看到多种关系一个注意力头只能有一组线性映射也就是说它只能用一种相似度度量来衡量任意两个token的关系。但一段文本里的关系是多种多样的有的头适合关注相邻词有的头适合追踪句法依存有的头适合捕捉跨句话题。如果只用单头模式会被迫压缩到同一个空间里。多头注意力把输入投影到h个平行子空间每个头独立计算注意力最后拼接再经过一次输出投影。由于每个头的初始线性映射不同它们会被逼着分化成不同的语义角色。实验和后来的分析都表明这种分工是自动出现的而不是人为指定的。Transformer原始论文里d_model512、h8、每个头维度64这个配置到今天仍是很多模型的起点。多头付出的额外参数不算大但让模型表达空间立刻丰富起来这是它能以相对较低成本碾压单头注意力的主要原因。3. 复杂度突围稀疏、线性与IO感知的注意力演进3.1 平方复杂度在长序列场景中先卡住显存自注意力的直接计算复杂度是O(n²·d)n是序列长度d是特征维度。表面上看这是个“计算量”问题实际第一卡点是显存注意力权重矩阵本身是一个n×n的矩阵需要在显存里显式存下来。我算过一个直观数据n8192、float32时单层注意力矩阵就是8192×8192×4字节约268MB。如果模型有三四十层又不用任何优化显存很快会被中间矩阵占满。所以当大家想把Transformer用到长文本、长视频序列时“平方”根本不是细节而是第一堵墙。后面所有高效注意力算法目标都是拆掉这堵墙。这里容易有个误区以为O(n²)只是慢实际上它同时限制了批量大小和序列长度。很多时候不是算不动而是显存放不下连batch size 1都跑不了。理解这一点再看稀疏注意力和FlashAttention的动机就会清楚很多。3.2 稀疏注意力用局部全局连接近似完整关系最早被大量验证的做法是稀疏注意力。Longformer的思路很直接保留一个滑动窗口让每个token只看附近若干token同时额外设置少数全局token比如CLS让信息可以通过它们跨区域传播。BigBird在此基础上又加了随机连接证明窗口、随机、全局三种模式的组合能够在理论上逼近完整注意力的表达能力。视觉里的Swin Transformer也采用了类似哲学。它把注意力限制在局部窗口内再用窗口移位获得跨窗口连接既把复杂度降下来了又保留了层次化的视觉感知。稀疏注意力的核心代价是必须人工决定哪些位置需要被关注。任务不同最佳模式也不同长文本问答里局部窗口可能不够全局token的选点需要试验图像任务里窗口大小本身就是超参数。 它不像标准自注意力那样“无脑”调起来更麻烦。3.3 线性注意力把softmax换成特征映射后的计算重排另一个方向是从数学上消掉n×n矩阵。完整softmax注意力要先算QK^T再softmax再乘以V。线性注意力把softmax中的指数相似度拆成两个独立特征映射的内积形式然后利用矩阵结合律把运算顺序改成φ(Q) * (φ(K)^T * V)这样先算φ(K)^T * V得到一个d×d的小矩阵再与φ(Q)相乘复杂度从O(n²)降到了O(n)。这类方法在超长序列检索、DNA序列建模等场景有应用但效果普遍不如完整注意力因为它把softmax的归一化竞争性抹掉了。没有了归一化模型很难通过注意力权重做“选哪个、忽略哪个”的离散判断。我自己的经验是线性注意力更适合序列非常长、但对质量要求不极端严苛的任务如果资源允许优先尝试FlashAttention往往更划算。3.4 FlashAttention的真实贡献不省计算省内存搬运FlashAttention经常被误归为近似注意力这其实是最大的误解。它计算的注意力结果和标准注意力完全一致只是改变了计算顺序和存储策略。GPU有两块存储片上SRAM很快但很小显存HBM很大但慢。标准做法是频繁把QK^T等中间矩阵写到HBM再从HBM读出来一遍遍搬运。FlashAttention把Q、K、V分块放到SRAM里每个block内做完整softmax再用online softmax的思想逐步累积结果全程不落盘完整注意力矩阵。效果是显存占用从O(n²)降到O(n)速度提升明显。它优化的是IO搬运而不是计算量。现在主流训练框架里FlashAttention基本可以无脑开启这也让长上下文在工程上变得现实了很多。如果项目里发现训练长序列时GPU利用率低先确认是不是没开FlashAttention开了以后瓶颈往往会从前向计算转移到通信或数据加载这是我自己踩过的坑。4. 位置编码演进出sin/cos、相对编码与RoPE4.1 为什么自注意力必须额外补充位置信息自注意力有个性质如果把输入序列打乱顺序输出也只会随之打乱而不会改变任意两个位置之间的关系结构。因为它只看内容相似度不看谁在谁前面。对语言来说顺序就是信息。“张三打了李四”和“李四打了张三”的词完全一样语义完全相反。所以Transformer在最初设计中就必须显式加入位置信息。这个模块看似配角实际撑起了今天长文本外推能力的大半。很多项目训练时一切正常一换序列长度就崩往往就是位置编码选型的问题。位置编码本身也从最初的固定三角函数一路演进到可学习绝对位置编码、相对位置编码、旋转位置编码RoPE再到零参数的ALiBi。4.2 绝对位置编码的两种形态固定式与可学习式原始Transformer使用固定三角函数编码不同维度用不同频率的sin/cos生成。好处是参数少、不学习、可以尝试外推更关键的是由于三角函数的和差化积公式理论上编码后两个位置向量的点积能包含相对位置信息。不过在深层网络里这种相对信息能不能被有效利用并不一定。到了BERT时代大家发现直接用可学习的位置embedding更简单效果当时也更好所以大量预训练模型都采用了它。可学习绝对位置编码的问题是训练长度固定模型见过多长就只能处理多长。如果训练时最长512推理时来了1024超出部分的位置embedding是从未训练过的随机值效果自然崩。后来为了让模型能处理长文档大家才重新转向相对位置类编码因为相对距离比绝对序号更容易泛化你说“隔了两句话的关系”比说“第5个词和第120个词的关系”更本质。4.3 相对位置编码与Transformer-XL的外推思路绝对位置编码把“第i个位置”当作独立标签相对位置编码则直接建模“第i和j个位置相距多远”。Transformer-XL使用相对位置编码后模型在训练长度之外也能延续一定距离因为距离关系比绝对序号更容易迁移。T5的处理更直接给注意力分数加一个由相对距离决定的可学习bias让模型在打分时知道两个token离得远还是近。这类设计的直觉是语言中“相邻”“相隔两个词”“跨句”这些距离模式是稳定的而具体出现在第几段并不重要。不过相对位置编码的实现细节通常更绕比如需要调整K和V的拆分方式网络层数一变就容易搞混。我在复现Transformer-XL时曾花了大半天排查维度不对齐的问题原因就是相对位置索引的偏移量没写对。位置编码虽然看着只有几行代码但确实是实现时最容易出错的地方之一。4.4 RoPE为什么成了LLM的事实标准旋转位置编码RoPE是近几年大模型里用得最多的位置编码。它的核心想法很漂亮把每个位置对应的Q或K向量在高维空间里旋转一个与该位置相关的角度。两个旋转后的向量做内积时旋转不改变向量长度只改变相位所以内积结果恰好只依赖两个位置的旋转角之差也就是相对位置。这种设计把位置信息与注意力计算融合得不露痕迹同时具备相对位置编码的外推优势。更重要的是后续对RoPE做长度外推很方便直接对旋转角做线性插值或NTK插值就可以把模型推到训练长度之外不需要改动模型结构。Llama、Qwen这些开源模型都用它生态工具也都对齐了所以它成为事实标准不是偶然。如果需要在超长上下文场景部署模型RoPE加插值方案是目前最成熟的方向之一。4.5 外推替代方案ALiBi如果你不想引入复杂的旋转公式ALiBi是另一个有趣的思路。它完全不做位置embedding而是在注意力分数上直接减去一个与两个位置距离成正比的惩罚项让模型天然对“远距离”降低权重。这种设计几乎零参数在短训练、中长推理的外推场景上表现不错。我实际测评中发现ALiBi在需要较长外推的任务里比较省心但训练充分的大模型里RoPE配合插值通常更稳。位置编码没有银弹关键是定义清楚你手里的序列长度需求和外推目标。如果训练和推理长度一致可学习绝对位置编码足够如果要外推RoPE或ALiBi是更稳的选择。这个判断越早做后面返工越少。5. 同是Transformer外壳内部件一直在换归一化、激活、共享头5.1 Post-LN到Pre-LN的稳定化改动原始Transformer把LayerNorm放在残差相加之后也就是Post-LN。理论上Post-LN表达能力更强因为它不对残差路径做额外限制但实际训练大模型时容易不稳定需要warmup和精细调参。后来GPT-2和很多开源模型改用Pre-LN先对输入做LayerNorm再进行注意力或前馈网络最后残差直接相加。Pre-LN的残差路径更干净梯度更容易跨层流动训练更稳定。代价是模型最终效果可能略弱于Post-LN但和“能不能训起来”相比这个代价非常好接受。工程上我见过不少照着原始Transformer搭模型的朋友第一版堆不出深度改成Pre-LN以后几十层就能稳定跑了。现在看主流LLM的开源代码几乎都是Pre-LN或者它的变体。如果你自己从零训练Transformer先把这一步改对比调一堆学习率更有效。5.2 从LayerNorm到RMSNorm的一步简化LayerNorm要计算均值和方差然后做归一化。RMSNorm的研究者发现均值那一步其实可以省掉只要用RMS均方根做缩放就足够稳定而且省了不少计算。听起来像小改动但对几十亿参数模型来说省一个reduce对训练吞吐是有实际影响的。LLaMA系列用的就是RMSNorm。从算法演进角度看RMSNorm少了一次中心化偏移的可学习参数也少了一层统计耦合训练时更干脆。如果你的模型在训练时发现LayerNorm统计均值长期偏离0仿照RMSNorm砍掉中心化通常会更快收敛。当然这不是万能技巧但在很多场景下确实能让归一化这块更简洁。现在新开源模型普遍用RMSNorm也说明这种简化在工程上是划算的。5.3 激活函数ReLU到GELU、SwiGLU的演进Transformer前馈网络里的激活函数也在演进。原始论文用ReLU简单高效但负数区域梯度完全为0容易造成神经元死亡。BERT和GPT-1开始用GELU它用标准正态累积分布做平滑门控0附近不是尖点梯度更连续训练更稳。后来PaLM、LLaMA、很多LLM用SwiGLU把门控线性单元和Swish组合起来等于一个分支负责“内容”另一个分支负责“门控”。SwiGLU在同等计算量下通常能带来稳定的效果提升但会额外增加参数。实际使用时常常要把中间层维度缩小比如从4倍降到约2.67倍来抵消参数增量。这里给个参数建议表激活函数典型中间层倍数特点ReLU4倍简单快速容易神经元死亡GELU4倍平滑梯度预训练更稳SwiGLU约2.67倍门控机制效果好但参数多这个维度调整看起来小但对训练吞吐影响很大。我见过有人把SwiGLU的中间层继续设成4倍结果参数量爆炸训练速度直线下降效果却没提升。激活函数选型时一定要连同维度一起看。5.4 从MHA到MQA/GQA推理成本驱动的头结构变化注意力头结构的最大演进动力来自推理阶段的KV cache。标准多头注意力MHA每个头都独立存K和V序列越长显存越大。推理时这些KV要一直存在所以有人做了MQA让所有头共享同一个K和V。共享以后KV cache大幅缩小但表达能力下降模型质量可能有折扣。折中方案是GQA把注意力头分成若干组组内共享一组K/V。GQA在质量和KV cache之间取得了平衡比如Llama 2 70B就用了GQA。如果你在做长上下文服务的部署KV cache是绕不开的工程问题。MQA/GQA这类结构改动远比单纯加显存更实际。下面这张表可以帮你快速决策类型K/V共享方式KV cache开销适用场景MHA每头独立最高训练阶段追求表达上限MQA所有头共享一组最低轻量推理接受质量回落GQA组内共享折中生成式LLM质量与显存平衡实际开发时训练阶段可以用MHA充分训练推理阶段再做GQA转换或量化这种思路在一些部署实践中已经很常见。不过要注意训练和推理的注意力头配置不一致时需要做参数重构不能简单改名了事。6. 范式位移Decoder-only与条件计算带来的新问题6.1 BERT与GPT左右两条路的结果从Transformer衍生出来的早期路线分两支。BERT走Encoder-only架构用双向上下文预训练在GLUE、SQuAD等理解类任务上统治了很久。GPT走Decoder-only架构用因果语言模型做生成一开始更擅长续写。当时很多研究者的判断是两种架构各司其职理解归BERT生成归GPT。后来的发展大家都清楚生成式AI成为大模型主流后两边在规模、生态、社区投入上开始明显倾斜。这种偏差背后有算法理念的原因BERT的预训练目标需要额外任务头才能迁移而GPT的自回归目标天然把所有任务统一成“预测下一个token”下游使用时几乎不需要架构改动。看起来只是训练目标的差别实际变成了整个产品形态的差别。6.2 为什么生成式大模型把Decoder-only当成默认架构除了统一任务很方便Decoder-only在工程上也更好扩展。因果注意力意味着所有位置只看左侧显存中KV的形态整齐推理时逐token生成天然符合KV cache的更新方式。Encoder-Decoder架构虽然双向理解更强但生成时仍然要从Decoder走一遍编码端和解码端的调度更复杂推理开销也更大。再加上近年一些对照实验显示在同等参数量和训练数据下Decoder-only在下游任务上比Encoder-Decoder不弱甚至更强。这直接推动元模型、Llama、Qwen等几乎所有主流大模型都选了Decoder-only。倒不是说Encoder-Decoder没有价值而是在当前规模化生成的范式中Decoder-only的工程优势太明显。如果只是做纯理解任务Encoder-only依旧有其价值但如果你要做一个通用助手Decoder-only几乎是最省事的起点。6.3 MoE、多模态等架构层面的新变量说Transformer架构演进还不能不提MoE。MoE不是改注意力算法而是把FFN层换成多个专家网络并通过门控网络对每个token动态选择专家。它以条件计算的方式让模型参数量大幅增加但单次推理只激活一部分参数。Mixtral、DeepSeek等模型把MoE和Transformer结合后长上下文的性价比进一步提升。多模态方向则出现把图像、音频都当作token序列输入到Transformer的做法。核心算法时代的很多技巧都能原样保留只是模态编码器不同。这些都说明Transformer的核心算法演进不会停在“注意力本身怎么算”而会在“结构算法如何匹配实际算力”上继续延伸。我入行这几年最大的感受是很多看似理论优雅的演进最初都来自工程上的“卡脖子”问题。FlashAttention来自显存瓶颈Pre-LN来自深度训练不稳定GQA来自推理KV cache膨胀。如果你自己做项目别急着追新模块先看看当前流程卡在哪一层序列一长就崩优先看注意力复杂度模型越深越难收敛优先看归一化和残差服务端KV cache太吃显存优先看GQA。按这个思路去选架构算法比复制别人的配置要有效得多。这也是我把前面那些演进串成一条逻辑线的意义把每个新模块的名字都还原成它原本要解决的问题用的时候自然知道怎么选。
阅读完成 · 觉得有帮助?
咨询建站