从一个巧招到一整台机器
在前两篇指南里,你已经造好了引擎:自注意力让每个词都能从其他每个词那里收集信息,多头注意力则并行地跑好几次这样的查找,使模型能同时追踪语法、含义与指代。但有了引擎并不等于有了汽车。单独一层注意力是「浅」的——它只把信息混合一次就停了。[[transformer-architecture|Transformer]],就是当你拿起这台引擎、再把整辆车的其余部分围着它造出来时所得到的东西:如何把这些层叠起来、如何让它们保持稳定、以及如何让整套装置真正生成文字。
提出它的那篇著名的 2017 年论文,标题叫做*《注意力就是你所需要的一切》*——这是对当时主宰语言领域的循环网络的有意一击。那些更老的模型严格地从左到右读句子,一次一个词,像接力棒一样把一份不断更新的记忆往下传。这让它们训练起来很慢,而且读到句尾时往往已经忘了句首。Transformer 下的赌注很激进:彻底扔掉循环,用注意力一次性看遍所有词,让堆叠的层去做深层的思考。
一个模块:先注意力,再一个小脑子
Transformer 由一个重复的单元——*模块*——多次堆叠而成。每个模块依次做两件事。首先,一层注意力让每个位置混入其他位置的信息——这是*交流*步骤,词与词在这里互相说话。接着是一个[[feed-forward-block|前馈模块]]:一个小小的两层网络,*独立地*作用在每个位置上,每个词都复用这同一个小网络。如果说注意力是词在说话,那么前馈模块就是每个词各自走开,私下里琢磨它刚刚听到的东西。
这种分工的重要性超出第一眼的感觉。注意力在位置*之间*搬运信息,却几乎不做非线性的推理;前馈模块负责繁重的逐词变换,却看不到它的邻居。让两者交替进行——收集,再处理,收集,再处理——正是深层 Transformer 力量的来源。若数一数参数,前馈模块通常才是模型的*大头*,而不是注意力;模型所「知道」的很大一部分,就住在那些不声不响的小网络里。
还有一块东西跑在第一个模块*之前*:位置编码。因为注意力同时看所有词,它本身没有任何顺序感——对原始的注意力来说,「狗咬人」和「人咬狗」是同一袋词。位置编码给每个词元盖上一个标记,表明它*坐在哪个位置*,把过去由循环免费提供的词序重新补回来。
残差与层归一化:让它得以变深的胶水
把几十个模块叠起来听上去很容易,但深层网络出了名地难训练——梯度在穿过许多层往回传播时,会渐渐消失或者猛然爆掉(你在阶梯的更早处遇到过这个*梯度消失*问题)。两个简单的窍门让这种深度变得可以承受。第一个是[[residual-connection|残差连接]]:每个子层不去替换它的输入,而是把自己的输出*加*回输入上。模块算出一个小小的修正量,而原始信号则原封不动地径直穿过。
想象一位编辑在批改草稿。残差连接意味着编辑交还给你的是原稿*外加*页边的批注,而不是从头到尾重写一遍。文本能熬过五十位编辑的接力;梯度沿着同一条笔直的路往回走,也能活下来。没有残差,把 Transformer 训练到超过区区几层几乎都做不到。
第二个窍门是[[layer-normalization|层归一化]]:在每个子层之前(或之后),把每个位置上的数值重新居中、重新缩放到一个整洁的范围。这能防止信号在爬上层叠时漂到极端的数值,从而让每一层都接收到处于舒适区间的输入。把它*放在哪里*——「前归一化」(在子层之前归一)还是「后归一化」(在之后)——是一个实实在在的设计取舍;现代的大模型几乎全都采用前归一化,因为在很深的情况下它训练起来稳定得多。
# one Transformer block (pre-norm style) x = x + attention(layer_norm(x)) # communicate: words mix x = x + feed_forward(layer_norm(x)) # compute: each word thinks # stack this block N times (N = 12, 48, 96, ...)
编码器、解码器,还是两者都要
最初的 Transformer 是为机器翻译而造的,所以它有两叠模块——一个[[encoder-decoder-stack|编码器–解码器堆栈]]。*编码器*读入整句源文,并为它建起一份丰富的表示,其中每个词都能朝两个方向自由地关注其他每个词。*解码器*随后生成译文,并做两种注意力:它关注自己迄今为止已经产出的词,又通过[[cross-attention|交叉注意力]]回头探入编码器的表示,去查阅源文。编码器消化,解码器一边瞄着编码器的笔记一边写。
研究者很快注意到,你并不总是需要两半都要。只保留*编码器*,你就得到一个会阅读、会理解、却从不生成的模型——很适合给句子分类或打标签(BERT 一系就是这样工作的)。只保留*解码器*,你就得到一个纯粹的文本生成器。几乎你听说过的每一个聊天机器人式的大语言模型都是*仅解码器*的:一叠模块,唯一的任务就是一遍又一遍地预测下一个词。
解码器如何写作:一次一个词元
解码器靠[[autoregressive-decoding|自回归解码]]来生成文本:它预测一个词元,把它接到序列后面,再把整段重新喂进去以预测下一个——如此反复,就像一个只能不断添上下一个词、永远无法跳着往前写的作者。诀窍在于,为了学会这件事,一个词绝不能被允许偷看排在它*后面*的词;否则模型就会靠读答案来作弊。这一点由[[masked-attention|掩码注意力]]来强制:在解码器里,注意力被挡住、不准向前看,于是每个位置只能看见它自己和过去。
- 让提示词穿过整叠模块,看最后一个位置输出的向量。
- 把这个向量变成对整个词表的一个概率分布(在数万个可能的下一词元上做 softmax)。
- 从这个分布里挑出一个词元——可以贪心地取最大,也可以采样以增加多样性。
- 把它接到序列后面,从第 1 步重复,直到遇到一个停止词元。
这个循环也是为什么生成会让人觉得*是顺序的*、而且可能很慢:词元一个接一个地吐出来,每一个都得等上一个。有一项叫做 KV 缓存的巧妙优化,会把更早词元的注意力计算结果存下来,免得每一步都重算一遍——没有它,生成一段长回复会慢得没法用。它改变的是速度,而非本质:Transformer 写作的方式,仍然像你朗读时那样,一个词接着一个词。
值得诚实地说清这个循环是什么、又不是什么。模型并不是先规划好一整段答案、再把它打出来;它在每一步只是在估计:在迄今的所有内容之下,*接下来倾向于出现哪个词元*。那份流畅是真实的,常常令人惊叹,但背后并没有一本被查阅的事实账本——这正是为什么这些模型能信心十足地说出错误。这套架构是一台了不起的下一词预测器,而不是一位神谕。
它为何胜出
Transformer 几乎取代了它之前的一切,原因有一个被低估的:它*对并行很友好*。因为一层会同时处理每一个词、而不必等上一个,你可以在 GPU 上一口气把一整句话——甚至一整本书——灌进去。这使得在惊人体量的文本上训练成为可能,而事实证明:用更多数据训练的更大的 Transformer,就是会一直变好,平滑而可预测。这套架构赢的不只是质量;它赢在*规模上的可训练性*。
这一切都不意味着 Transformer 就是定论,那种「它是我们将永远需要的最后一种架构」的炒作也该打个折扣。它平方级的注意力开销是一道实打实的天花板,位置编码方案至今仍在被不断重新发明,认真的替代方案也正在被探索。可以公允地说的是:你如今已经理解的这一小撮想法——一叠叠注意力与前馈模块、用残差和层归一化粘合、一次生成一个词元——支撑着今天人们口中几乎每一个被称为「AI」的系统。你看的已不再是一个黑盒。你能叫出它每个部件的名字。