活字 从规则到大模型
正在加载 3D
小猫 没有 跳上 桌子 , 因为 它 太 累 了

这台设备或浏览器没有开启 WebGL2,这里显示同一装置的静态图;正文里的演示与文字说明照常可用。

3D 画面没能加载。

点一枚字模选择提问的词 · 拖动旋转 · 向下滚动,字模拆成 Q / K / V 三层

第 03 章2013—2017

注意力

一个词怎么知道该看句子里的哪个词?

2017 年,一篇翻译论文的标题写着“注意力就是你所需要的一切”⁠[1]⁠。从那以后,几乎所有大模型都建在这种结构上。

提问的词

点一枚字模选择提问的词 · 拖动旋转 · 向下滚动,字模拆成 Q / K / V 三层 粉色是“指代头”,蓝色是“邻近头”,两色重叠的地方颜色变深。 注意力权重为手工设定的示意值,不来自真实模型

从词的坐标到注意力

短短四年里,处理语言的方式换了两次底座。

  1. 2013

    word2vec:词变成向量

    Mikolov 等,Google

    解决了什么
    过去的系统把词当成互不相关的编号,“猫”和“狗”之间没有任何联系。
    带来了什么变化
    用几百维的向量表示词,用法相近的词距离也近,还能做“国王 − 男人 + 女人 ≈ 女王”这样的类比⁠[2]⁠。
  2. 2014

    序列到序列:读完再写

    Sutskever 等,Google

    解决了什么
    翻译的输入和输出长度不同,很难用固定的结构处理。
    带来了什么变化
    编码器读完整句话并压成一个向量,解码器再逐词写出译文⁠[3]⁠。但长句子的信息很难全部塞进一个向量。
  3. 2014

    注意力机制:回头看原句

    Bahdanau、Cho、Bengio

    解决了什么
    长句翻译时,那个固定长度的向量成了瓶颈。
    带来了什么变化
    解码每个词时,回头查看原句的每个位置,按相关程度加权取用信息⁠[4]⁠。
  4. 2017

    Transformer:只用注意力

    Vaswani 等,Google

    解决了什么
    循环网络必须按顺序逐词计算,难以并行,也难以捕捉相隔很远的两个词之间的关系。
    带来了什么变化
    完全用注意力处理整句话,所有位置同时计算。训练更快、规模能做得更大,成了此后几乎所有大模型的基础结构⁠[1]⁠。
03.1

Token:模型读的是编号 Token · 词元

1一句话

模型不直接读文字。文字先被切成一个个片段,每个片段换成词表里的一个编号,这些片段就叫 Token。

2打个比方

像活字排版:常用的字和词各有一枚现成的字模,直接取用;字盘里没有的生僻字,就只能用更小的部件拼出来。

所以 Token 不等于“字”,也不等于“词”。一个常用词可能只占一枚,一个生僻字可能要三枚。

3动手试

分词器:把一句话切成字模 手工小词表的简化分词器,编号为演示用

规则只有一条:从左到右,每次取词表里能匹配上的最长片段。词表里没有的生僻字会被拆成 UTF-8 字节(灰色),一个字要占三个 Token。

4怎么做到的

真实的词表不是手写的,而是用算法从大量文本里统计出来。常见做法是字节对编码(BPE):从单个字符或字节出发,反复把最常一起出现的一对合并成新片段,直到词表达到预定大小⁠[5]⁠。GPT-2 在字节上做 BPE,词表共有 50,257 个 Token⁠[6]⁠。

在字节上做的好处是永远不会遇到“不认识的字”:任何文字最后都能退回到字节。代价是训练语料里少见的语言和字,会被切得更碎、占用更多 Token。

做不到什么

  • 模型拿到的是 Token 编号,而不是字母或笔画,所以“这个单词里有几个 r”这类问题容易出错。
  • 同一句话,不同语言消耗的 Token 数可能差好几倍,能放进窗口的内容和按 Token 计的费用也随之不同。
  • 数字常被切成不规则的片段,这是早期模型做算术容易出错的原因之一。
03.2

Embedding:编号变成坐标 Embedding · 嵌入向量

1一句话

每个 Token 编号都对应一长串数字(向量),可以看成它在高维空间里的坐标;用法相近的词,坐标也相近。

2打个比方

像在一张地图上给每个词钉一枚图钉:“猫”和“狗”钉得很近,“猫”和“桌子”离得远。方向也有含义:从“男人”走到“女人”的那段路,和从“国王”走到“女王”的那段路几乎平行。

3动手试

词向量地图:意思相近,位置就相近 二维示意,坐标为手工摆放;真实向量有几百到上万维
国王 女王 王子 公主 男人 女人 男孩 女孩 法国 巴黎 日本 东京 中国 北京 猫 狗 老虎 狮子 香蕉 橘子 苹果 手机 电脑

点一个词,找它的邻居

或者做一道向量算术

选一个词,或点一道算式。

4怎么做到的

模型里有一张大表,每一行是一个 Token 的向量。表里的数字一开始是随机的,在训练中不断调整,最后用法相似的词会被推到相近的位置。2013 年的 word2vec 让这种表示流行起来,也展示了“国王 − 男人 + 女人 ≈ 女王”这样的向量类比⁠[2]⁠。

真实的维度很高:GPT-3 最大的模型里,每个 Token 的向量有 12,288 个数⁠[7]⁠。上面的二维地图只是示意。

在 Transformer 里,这张表只给出每个 Token 的起点。经过一层层注意力之后,同一个“苹果”在“吃苹果”和“苹果手机”里会变成不同的向量,这叫上下文相关的表示。

做不到什么

  • 单个维度通常说不出明确含义,“这个数代表性别”之类的解读只是粗略的近似。
  • 向量会把训练语料里的偏见一起学进去,比如职业和性别的刻板关联。
  • 向量相近只说明用法相近,不说明可以互换:“北京”和“上海”离得很近,但答案里不能把一个换成另一个。
03.3

注意力:每个词都向整句话提问 Self-Attention · 自注意力

1一句话

注意力让句子里的每个词都去和其他所有词比较“谁和我相关”,再按相关程度,把其他词的信息按比例混进自己的表示里。

2打个比方

像开会时准备发言:你会回想在座每个人刚才说过的话,和你要说的事关系越大,就越多地参考那个人的说法。“它”要确定自己指谁,就会重点参考“小猫”和“桌子”,再看句尾是“累”还是“高”。

这个比方只说明“按相关程度加权参考”。模型里并没有谁在“理解”谁,只有一组组数字的乘法和加法。

3动手试

一次注意力的三步:打分 → 归一化 → 加权汇总(每个词一种颜色) 打分为手工设定的示意值,不来自真实模型

行:提问的词(Query) 列:被看的词(Key)

  1. ① 打分:「它」和每个词有多相关

  2. ② 归一化(softmax):变成加起来等于 100% 的权重

  3. ③ 加权汇总:按权重把各个词的“值”混进来

4怎么做到的

每个词的向量会被三组不同的权重分别变换,得到三个新向量:查询 Q(我在找什么)、键 K(我能被怎样找到)、值 V(我实际提供的内容)。一个词的 Q 和所有词的 K 逐一做点积,得到相关度打分;打分除以 √d(d 是向量维度)后经过 softmax 变成权重;最后用这些权重把所有词的 V 加起来,就是这个词新的表示⁠[1]⁠。

模型会并行地做很多组这样的计算,叫多头注意力。有的头偏向相邻的词,有的头偏向指代关系,分工是在训练中自己形成的;演示里的“指代头”和“邻近头”是为了讲解而手工设定的。

生成文字的模型(如 GPT 系列)使用因果遮罩:每个词只能看它前面的词,因为生成时后面的词还不存在。打开演示里的“只看前文”,就能看到「它」此时还无法判断指的是谁,这个判断要留给后面的词。

做不到什么

  • 每个词都要和所有词打分,计算量随长度的平方增长:文本长度翻倍,注意力的计算量约变成四倍。
  • 注意力权重高,不等于模型“因为这个词”才得出结论。用注意力图解释模型行为需要谨慎。
  • 注意力本身不区分词的先后顺序,需要额外加入位置信息,例如原论文的正弦位置编码,或后来广泛使用的旋转位置编码 RoPE⁠[8]⁠。
03.4

上下文窗口:一次能看多长 Context Window

1一句话

上下文窗口是模型一次计算能放进来的 Token 数上限。超出的部分不会参与计算,就像从来没有出现过。

2打个比方

像排字盘的尺寸:盘子就这么大,字排满了,再往后排就得把最前面的字拿掉。对话太长时,最早说过的话会被挤出窗口。

3动手试

上下文窗口:盘子只有这么大 窗口按 Token 数截取的示意,回答为预设
50
650

小明养了一只猫,名字叫年糕。它每天早上六点叫小明起床,吃完饭就趴在窗台上晒太阳。周末小明带它去公园,它一直躲在包里。问:小明的猫叫什么?

4怎么做到的

窗口大小由模型的结构和训练方式决定。最早的 GPT 窗口是 512 个 Token⁠[9]⁠,GPT-2 扩大到 1,024⁠[6]⁠,GPT-3 是 2,048⁠[7]⁠。后来,更省显存的注意力实现(如 FlashAttention⁠[10]⁠)和新的位置编码方法,让窗口逐步扩大到几十万乃至上百万 Token,最新情况见第 09 章。

聊天软件里的“记忆”,多数并不是模型本身记住了什么,而是软件把之前的对话重新放进窗口;放不下时,就要截断、做摘要,或者到外部资料里检索(第 08 章)。

做不到什么

  • 窗口变大不等于每一处都用得好:关键信息埋在很长的上下文中间时,模型可能用不上它。
  • 窗口越长,计算量和费用越高。
  • 窗口里没有的信息,模型只能依据训练中学到的规律去补全,这正是“幻觉”的来源之一。
03.5

层层叠印:Transformer 的整体 Transformer

1一句话

Transformer 把“注意力 + 一个小型前馈网络”作为一层,叠几十到上百层;每过一层,每个词的表示都结合上下文被改写一次。

2打个比方

像多色印刷:同一张纸要过好几块印版,每过一次就多叠一层颜色,最后的画面是所有印版共同作用的结果。每一层也不会擦掉前面的结果,而是在原来的基础上叠加修改,这叫残差连接。

3动手试

顺序处理 vs 整句并行 步数示意:RNN 每层要按词数走步,Transformer 每层一步算完整句

循环网络(RNN)0 步

小猫没有跳上桌子,因为它太累了

Transformer0 步

小猫没有跳上桌子,因为它太累了

4怎么做到的

2017 年的原始 Transformer 用于翻译,分为编码器和解码器两部分,各 6 层;基础版本的向量维度是 512,注意力头有 8 个⁠[1]⁠。它最重要的改变是可以并行:之前的循环网络(包括 LSTM⁠[11]⁠)必须一个词接一个词地算,Transformer 让一整句话的所有位置同时计算,能充分利用 GPU。论文报告,大号模型在 8 块 P100 显卡上训练 3.5 天,就刷新了当时英德、英法翻译的最好成绩。

后来的 GPT 系列只保留解码器,BERT 只保留编码器⁠[12]⁠。今天的大语言模型绝大多数是“只有解码器”的结构。

做不到什么

  • 结构本身没有长期记忆:每次计算只依赖窗口里的内容和训练好的参数。
  • 层数和宽度越大,能力通常越强,但训练和运行成本也急剧上升(见第 04 章)。
  • 层层叠加的计算很难逐步解释,“模型内部到底在算什么”仍是可解释性研究的难题。

这一章留下的问题

  1. 01

    注意力的计算量随长度平方增长。能不能用更省的方式处理很长的文本,又不损失效果?

  2. 02

    注意力权重只能部分揭示模型参考了哪些词,不足以完整解释它为什么这样输出。

  3. 03

    Transformer 只是一种结构。真正让它变成“大模型”的,是之后在海量文本上做的预训练,这是下一章的内容。

本章参考文献

  1. [1] Ashish Vaswani et al.. Attention Is All You Need. NIPS 2017 (arXiv:1706.03762).提出完全基于注意力、不使用循环和卷积的Transformer架构,训练可高度并行,后来成为几乎所有大语言模型的基础结构。
  2. [2] Tomas Mikolov, Kai Chen, Greg Corrado, Jeffrey Dean. Efficient Estimation of Word Representations in Vector Space. ICLR 2013 Workshop (arXiv:1301.3781).提出CBOW和Skip-gram两种简单高效的模型(即word2vec),可在大规模语料上快速学习词向量,词向量之间的线性关系能反映部分语义和句法关系。
  3. [3] Ilya Sutskever, Oriol Vinyals, Quoc V. Le. Sequence to Sequence Learning with Neural Networks. NIPS 2014 (arXiv:1409.3215).用一个LSTM把输入序列编码成固定长度向量、再用另一个LSTM解码生成输出序列,在英法机器翻译上取得有竞争力的结果,确立了“编码器-解码器”范式。
  4. [4] Dzmitry Bahdanau, Kyunghyun Cho, Yoshua Bengio. Neural Machine Translation by Jointly Learning to Align and Translate. ICLR 2015 (arXiv:1409.0473).在编码器-解码器翻译模型中引入注意力机制,让解码器每生成一个词都能有选择地关注源句的不同位置,缓解了用固定长度向量表示长句的瓶颈。
  5. [5] Rico Sennrich, Barry Haddow, Alexandra Birch. Neural Machine Translation of Rare Words with Subword Units. ACL 2016, pp. 1715–1725 (arXiv:1508.07909).把字节对编码(BPE)压缩算法改造成子词切分方法,使神经机器翻译能用有限的词表处理罕见词和未登录词;BPE及其变体后来成为大语言模型分词器的常见做法。
  6. [6] Alec Radford, Jeffrey Wu, Rewon Child, David Luan, Dario Amodei, Ilya Sutskever. Language Models are Unsupervised Multitask Learners. OpenAI (technical report; announced in the blog post “Better language models and their implications”).在约800万个网页(WebText)上训练了最大15亿参数的GPT-2,显示语言模型无需针对任务训练也能零样本完成部分任务;OpenAI以担心被滥用为由分阶段公开了模型权重。
  7. [7] Tom B. Brown et al.. Language Models are Few-Shot Learners. NeurIPS 2020 (arXiv:2005.14165).训练了1750亿参数的GPT-3,展示只需在提示中给出少量示例(上下文学习,不更新参数)就能完成许多任务。
  8. [8] Jianlin Su et al.. RoFormer: Enhanced Transformer with Rotary Position Embedding. arXiv:2104.09864; later published in Neurocomputing, 568: 127063 (2024).提出旋转位置编码(RoPE),通过旋转查询和键向量把相对位置信息融入注意力计算,后被LLaMA等许多大语言模型采用。
  9. [9] Alec Radford, Karthik Narasimhan, Tim Salimans, Ilya Sutskever. Improving Language Understanding by Generative Pre-Training. OpenAI (technical report; announced in the blog post “Improving language understanding with unsupervised learning”).先在大量无标注文本上对Transformer解码器做生成式预训练,再针对具体任务做有监督微调,在多项自然语言理解任务上取得当时最好成绩,即后来所称的GPT-1。
  10. [10] Tri Dao et al.. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. NeurIPS 2022 (arXiv:2205.14135).通过分块计算减少GPU显存与片上SRAM之间的数据读写,在不做近似的前提下加快注意力计算并显著降低显存占用,使更长上下文的训练更加可行。
  11. [11] Sepp Hochreiter, Jürgen Schmidhuber. Long Short-Term Memory. Neural Computation, 9(8): 1735–1780 (Nov 1997).提出带门控记忆单元的循环神经网络结构LSTM,缓解了普通RNN因梯度消失而难以学习长距离依赖的问题。
  12. [12] Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL-HLT 2019, pp. 4171–4186 (arXiv:1810.04805).用掩码语言模型等目标预训练双向Transformer编码器,再微调到下游任务,在11项NLP任务上刷新纪录,推动了“预训练+微调”范式的普及。

全部文献、素材与许可见 来源与许可。