跳到主要内容

数据截至 (上游 commit c187ef3271d5)

一句话在里面怎么走 — 全书最大的缺口在这里补上

这一章讲三件事。第一件:一句话从字符变成模型能算的东西,要过四道工序。 切成小块 → 每块换成一串数 → 给每块补上「它排在第几个」→ 让每块去看别的块。 前三道书讲得不错,第四道停在了半路。

第二件,就是补那半道。 书写到「模型算出 it 指的是 pizza」就收笔了 —— 可那个「算」字里面到底做了什么乘法、什么除法,全书一个字没有。 第 5 节整节是我们补的:每个词各出三份东西,拿其中两份对一对得出分数, 压一压、归一成比例,再按比例把第三份混起来。

第三件,是把四处连起来。 「先给每个来源打分,再按分数加权混合」这一招, 你在第 04 章的图像小块上、第 08 章的图邻居上、第 09 章的时间刻度上各撞见过一次。 四处是同一件事换了对象 —— 书从不点破,我们在第 7 节连起来。

在全书链条里的位置: 这一章不换任何零件,也没有训练循环 —— 它是把前面所有章里那个反复出现、却始终没被讲透的机制,一次讲到底。

1. 顶层全景:四层楼,书画了图但只讲透了三层

书给了一张结构图,从下往上四层1这一章就照这四层走。

一句话:The man ate the pizza because it smelled delicious

┌─┴───────────────────────────────────────────────────┐
│ 第 1 层:切词 ── 切成一小块一小块,每块换成一个编号 │ 书讲了(第 2 节)
├─────────────────────────────────────────────────────┤
│ 第 2 层:词嵌入 ── 每个编号取出一串数,数与数的远近 │ 书讲了(第 2 节)
│ 就是意思与意思的远近 │
├─────────────────────────────────────────────────────┤
│ 第 3 层:位置编码 ── 再给每一块加上「它排在第几个」 │ 书讲了(第 3 节)
├─────────────────────────────────────────────────────┤
│ 第 4 层:注意力 ── 每块去看别的块,按相关程度混合 │ **书只讲了一半**
│ ↑ │ (第 4、5、6 节)
│ Q V K ← 书的图上画了这三个字母, │
│ 正文一个字没解释 │
└─────────────────────────────────────────────────────┘

图说:Q、V、K 这三个字母,书在图里画出来了,正文从头到尾没有提过一次1第 5 节整节就是在补它们。

书自己对第 4 层的定位是:它是这个模型真正的核心 —— 模型正是在这一层里学到句子的内部结构、学到哪个词跟哪个词有关系2

2. 从一串字到一串数

2.1 第一步:切成小块,每块换一个编号

这一步第 10 章已经讲过一半了,这里把它接上。 一句话先被切成一小块一小块,每块叫一个 token; 接着每个 token 被赋予一个唯一的数字编号,叫 token ID3

书把这层关系说得很好:那个编号相当于一本词典里的一条, 而这本词典建立起「人类的词」和「机器的数」之间的对应3

用户输入: PyTorch is a lot of fun
↓ 切词器
切出来的块: Py Torch is a lot of fun
↓ 查词典
编号: 37863 162709 382 261 3261 328 2827

图说:这是书里那张图的真实数字4「PyTorch」被切成了两块 —— 这就是「按比词更小的单位切」这种做法留下的痕迹。

2.2 第二步:编号换成一串数,而这串数带着意思

先看现象: 编号 37863 和 162709 之间没有任何意义 —— 它们只是词典里的行号,不是「Py 比 Torch 小」。 那么「意思」是从哪儿来的?

答案是:每个编号再去换一串数,这串数才带着意思。 书管这串数叫词嵌入, 并说它反映的是这个词的含义5。(第 06 章那个「用户 ID 换成 32 个数」是同一件事, 只是那次换的是玩家和游戏,这次换的是词。)

书拿一张二维图讲清了「意思变成距离」这件事,这个例子极好,值得走一遍6

两个维度是「有几条腿」和「身高多少米」。于是7:

身高

3 │ 大象 [4, 3]


1 │ 狗 [4, 1]
0.5 │ 蛇 [0, 0.5] 猫 [4, 0.5]
0.1 │ 蜗牛 [0, 0.1]
└──────────────────────────────→ 腿数
0 4

图说:猫和狗挨得很近,蛇和蜗牛也挨得很近,而这两组离得很远。 「意思相近」这件事,在这张图上变成了「点挨得近」 —— 这就是嵌入的全部要点6

从二维到真实的模型,只差一个数量级的想象。 书说得很直白:人能想象二维、三维空间,却想象不出一千五百多维或三千多维的空间; 可计算机毫无压力 —— 而正因为维度多,词、图像、声音的含义才装得下8

这里的判据一句话:每多一个维度,机器对这个词的含义就多把握一分8

判断(我们的,不是书里的):这张表和它旁边的正文对不上,我们绕开了那一个点。 正文说「人」这个概念对应 [2, 2],而紧挨着的表格里写的是 [4, 2]9两个数只有一个能对(人有两条腿,而那张图上「人」也画在 2 条腿附近), 所以上面那张图我们没有画人这个点如果错,会错在: 如果作者是想拿「人」演示「同一个概念在不同的特征体系下坐标不同」, 那这不是笔误而是有意为之 —— 但书里没有任何一句话往这个方向解释。

3. 位置编码:注意力本身看不见顺序

先看现象,书给的例子极好,一句话就说服人10:

The ball hits the boy (球砸了男孩)
The boy hits the ball (男孩砸了球)

图说:同样五个词,一个字不差,意思完全相反。 差别只在谁排在谁前面10

问题在于:上一节走完之后,模型手上是「一堆带意思的数串」,而不是「一排有先后的数串」。 两句话切出来的 token 完全一样,取出来的词嵌入也完全一样 —— 如果不额外做点什么,这两句在模型眼里一模一样。

做法:在每个词的那串数上,再加一串专门表示「它排在第几个」的数。 书的说法是:我们把一个包含 token 在输入序列中绝对或相对位置信息的向量, 加到词嵌入上11这一步叫位置编码。

具体加的是什么数,书只给了一句:靠三角函数算出来 —— 也就是中学画过的正弦、余弦 —— 那两条上下起伏、周而复始的波形曲线;这样模型才能在整个序列长度上学会并推广词的位置11再往下就没有了。

补充(不在书里):为什么偏要用三角函数,书没解释,这里补一句。 用波形的好处是每一个位置都能拿到一串各不相同的数,而且序列多长都够用 —— 不必事先给每个可能的位置各准备一份。 它还有一个附带的好处:「相隔 5 个位置」这件事,在这套编码下有稳定的表达, 于是模型学得会「往前数几个」这种关系12

判断(我们的,不是书里的):第 09 章那个输给 LSTM 的模型,少的正是这一步。 第 09 章那场三模型比武里,自注意力那一套排最后(误差 12.12%,而 LSTM 是 8.79%)。 书把败因全部归给「数据太小」,没有检查自己的实现。 而我们逐行核过那段代码:它的流程是「补一维 → 线性层摊成 48 个数 → 编码器 → 取最后一步」, 中间没有任何一步加位置13少了这一步,那个模型眼里 1949 年 1 月和 1960 年 12 月是平权的 —— 而时间序列的全部信息恰恰在顺序里。这不是「数据太小」能解释的。 书自己在这一章白纸黑字写着「位置编码是保住词序的关键手段」11, 可它没有把这两处接起来。 如果错,会错在: 如果那份数据的规律主要靠「最近几个月的水平」而不是「谁在谁之前」, 那么缺位置的影响会比我们说的小,数据量仍可能是主因。 判据是:这一处能被验证 —— 把位置那一步加回去重跑一次,误差降不降,一试便知。 而书连试都没试。

4. 自注意力:每个词去看句子里的其他词

先看现象,书给的例子同样很好14:

The man ate the pizza because it smelled delicious. (那个男人吃了披萨,因为闻起来很香。)

「it」指的是谁? 光靠语法 —— 一门语言里「词该怎么摆、句子怎么搭」的那套规矩 —— 只能推到「它指某个名词」;可这句话里有两个名词:man 和 pizza。14

书的答案是:让每个词自己去看句子里其他所有词,学出它们之间的关系; 训练数据足够多的话,模型就会认定 it 指的是 pizza 的可能性大得多14

这套机制的正式名字叫自注意力。 书给的定义只有一句: 它计算所有词与词之间在词嵌入上的相似程度15

书演示了一次,而且是真跑出来的。 它拿一个现成的语言模型跑这句话, 把最后一层里各套注意力的分数取平均画出来,结果是 —— 「it」在 pizza 上的分数明显高于 man16

书到这里就结束了。

它没有说:那个分数是怎么算出来的、为什么这么算、为什么要取平均、 「各套」是什么意思。下一节整节补这一段。

5. 那个分数是怎么算出来的(这一节是我们补的,书完全没有)

这一节整节不在书里。 书的图上画了 Q、V、K 三个字母1, 正文一次都没提过它们 —— 而它们正是上一节那个分数的全部来源。

5.1 先看现象:光有「相似度」是不够的

上一节说「计算词与词之间的相似程度」。听起来很自然,但直接这么做会撞上一堵墙。

拿「it」和「pizza」这两个词的那串数直接比一比,得到的是一个固定的相似度 —— 可我们要的不是「it 和 pizza 这两个词像不像」, 而是「在这句话里,处理到 it 的时候,pizza 该被取走多少」。

这两件事不一样。 同一个词在不同的位置扮演不同的角色:

同一个词,三种角色举例
要找什么处理到「it」时,它在找一个「能被闻到、能好吃」的东西
什么(供别人找)「pizza」对外声明自己是一样「能吃、有味道」的东西
能给出什么一旦被选中,「pizza」往外交出去的那份内容

所以做法是:同一个词,分出三份不同的数,一份管一件事。

5.2 三份数怎么来的:同一串数,乘三套不同的权重

每个词进来时只有一串数(第 2 节那串词嵌入,加上第 3 节那份位置)。 拿它去乘三套各不相同的权重,就得到三份17:

这一份干什么用通用的叫法
「我在找什么」拿它去和别人的第二份对分查询(Query,Q)
「我是什么」给别人来对分用键(Key,K)
「我能给什么」被选中后真正交出去的内容值(Value,V)

三套权重都是训出来的 —— 也就是第 01 章那个循环里被一点点挪动的那种数17

「自注意力」里那个「自」字,到这里才讲得清: Q、K、V 三份全部来自同一句话自己。 如果 Q 来自一句话、K 和 V 来自另一句话(比如翻译时拿译文去查原文), 那就是普通的注意力,不叫自注意力18

5.3 四步算出那个分数

下面这四步就是上一节那个「分数」的全部内容19:

① 对分 ── 拿「我在找什么」和每个词的「我是什么」做点积
(点积:两串数对应位置相乘,再全部加起来 —— 第 06 章见过)
→ 得到一串大小不一的数

② 压一压 ── 每个数都除以「一串数里有几个数」的平方根
→ 把数值拉回温和的范围

③ 归一 ── 过一次 softmax,把这串数变成加起来等于 1 的比例
(softmax:第 01 章讲过,把一串数压成一组和为 1 的比例)

④ 混合 ── 按这组比例,把每个词的「我能给什么」加权相加
→ 这就是当前这个词的新表示

图说:四步走完,「it」那个位置里就掺进了大半份「pizza」。 第 8 节的主走查会把这四步各带一组具体的数走一遍。

第 ② 步为什么不能省,这是最容易被跳过、也最值得讲的一步。

点积的结果会随着「一串数有多长」一起变大。 真实模型里一串数有几百个, 点积出来动辄几十上百;而 softmax 这一步对数值大小极其敏感 —— 数一大,比例就会几乎全部堆到第一名头上,其余全成 0。

全堆到一个位置上有什么坏处? 第 01 章说过,训练靠的是「误差往哪个方向变」这个信号; 而比例一旦变成 1 和 0,这个信号就几乎没有了,这一层学不动。 除以平方根,就是把数值拉回一个 softmax 还分得开的范围20。 第 8 节第 ⑦ 步会把「除」和「不除」的结果并排算出来给你看。

6. 多头:并排跑好几套,各管一种关系

先看现象。 上一节算出来的是一组比例。可词与词之间的关系不止一种。

书讲得很清楚:真实的模型里不止一个注意力模块 —— 一个这样的模块通常被叫作一个;而多头注意力里每个头关注词与词之间不同的方面, 比如一个头盯动词和名词的关系,另一个头盯形容词和名词的关系21

做法:第 5 节那四步,并排跑好几套,每套有自己的三套权重;算完把各套的结果拼起来。 (「拼起来」这一步书没说,是我们补的。)

这解释了第 4 节那个演示里一个没被解释的动作: 书为什么要取平均? 因为那一层里有好几个头,每个头给出一张自己的分数表 —— 把它们平均起来,才得到一张「总体上谁看谁」的图16

这一招你在第 08 章见过。 那一章的图网络用了 8 套注意力, 每套各学一组邻居权重、最后拼起来 —— 动作完全一样,只是打分的对象是邻居而不是词。

7. 同一招,你已经见过三次了

这一节是我们连的,书从不点破。

「先给每个来源打一个分,再按分数把它们加权混合」这一个动作, 在这本书里出现了四次,每次换一个对象、换一个名字。

在哪一章谁在打分打给谁书里管它叫什么
第 04 章图像里的一个小方块同一张图里的其他小方块视觉 Transformer22
第 08 章图里的一个节点它的邻居图注意力网络23
第 09 章时间序列里的一个时刻同一个窗口里的其他时刻自注意力24
第 11 章一句话里的一个词同一句话里的其他词自注意力15

四行的机制完全相同,差别只有两处:

  1. 打分的对象换了 —— 小方块 / 邻居 / 时刻 / 词;
  2. 第 08 章那一行有一处硬约束:它只跟直接邻居打分,不跟图里所有节点打分 (这一条第 08 章的判断块里说过)。

为什么这件事值得单列一节: 因为你以后遇到任何一种新数据 —— 分子里的原子、代码里的函数、一份表格里的列 —— 只要能说清「谁该看谁」, 这一招就能直接搬过去。 而书把它拆成四章讲了四遍,从不说它们是同一件事。

判断(我们的,不是书里的):书不点破这一点,是这本书结构上最可惜的一处。 四章各讲一遍,读者要么以为是四种不同的技术,要么隐约觉得像、但不敢确定。 而点破它的成本只有一段话。 如果错,会错在: 如果作者的教学策略是「先各自学熟,再自己发现共性」, 那这是有意留白而不是遗漏 —— 但全书从头到尾没有任何一处回头做这个总结, 包括最后一章的全书小结。

8. 主走查:一句话,走到「it」这一步

这条走查的句子是书自己的,四层结构也是书自己的; 而第 ⑥ 到 ⑨ 步的那些数是我们为演示编的,不是真实数值。 编的是数,不是步骤 —— 步骤和真实模型一模一样。

第 ① 步,输入。 那句话:

The man ate the pizza because it smelled delicious

第 ② 步,切成小块、每块换一个编号。 这句话都是常见词,所以基本一词一块3。 (对照:第 10 章那个「PyTorch」就被切成了两块。)

第 ③ 步,每个编号取出一串数(词嵌入)。 真实模型里这串数有一千五百多个或三千多个8;为了能手算,下面缩到 4 个。

第 ④ 步,给每一块加上位置。 这一步做完,「the」这个词在第 1 个位置和第 4 个位置 拿到的就不再是同一串数了11

第 ⑤ 步,每个词各出三份。 拿第 ④ 步那串数乘三套训出来的权重, 得到「我在找什么」「我是什么」「我能给什么」三份17

第 ⑥ 步,摆出这次要用的数。 我们只盯三个词:man、ate、pizza; 正在被处理的位置是 it。

「我在找什么」(Q)「我是什么」(K)「我能给什么」(V)
it(正在处理)[1, 0, 2, 0]
man[0.5, 2, 0.5, 1][1, 3, 0, 2]
ate[1, 1, 0.5, 0][0, 2, 1, 0]
pizza[2, 0.5, 1.5, 1][3, 0, 2, 1]

这几组数是为演示编的,不是真实数值。

第 ⑦ 步,对分并压一压。 拿 it 的 Q 和每个词的 K 做点积(对应位置相乘再全加起来):

it · man = 1×0.5 + 0×2 + 2×0.5 + 0×1 = 0.5 + 1.0 = 1.5
it · ate = 1×1 + 0×1 + 2×0.5 + 0×0 = 1.0 + 1.0 = 2.0
it · pizza = 1×2 + 0×0.5 + 2×1.5 + 0×1 = 2.0 + 3.0 = 5.0

一串数里有 4 个数,所以除以 √4 = 2:

man 1.5 ÷ 2 = 0.75 ate 2.0 ÷ 2 = 1.00 pizza 5.0 ÷ 2 = 2.50

第 ⑧ 步,归一成比例。 对这三个数做 softmax(先各算一次以 e 为底的乘方,再各除以三者之和):

0.75 → 2.12 1.00 → 2.72 2.50 → 12.18 合计 17.02

man = 2.12 ÷ 17.02 = 0.12
ate = 2.72 ÷ 17.02 = 0.16
pizza = 12.18 ÷ 17.02 = 0.72 三者相加 = 1.00

这里当场验一下第 5.3 节说的「不压一压会怎样」 —— 拿没除过的 1.5 / 2.0 / 5.0 直接做 softmax:

man 0.03 ate 0.05 pizza 0.93

对照着看:压过之后 pizza 是 0.72,不压是 0.93。 不压的话,另外两个词几乎被彻底挤掉 —— 而「另外两个词各占多少」正是训练时要调的东西。 挤到 0.03 和 0.05,这一层就几乎学不动了。

第 ⑨ 步,按比例混合。 拿这三个比例去乘各自的「我能给什么」,逐位相加:

第 1 位: 0.72×3 + 0.16×0 + 0.12×1 = 2.16 + 0 + 0.12 = 2.28
第 2 位: 0.72×0 + 0.16×2 + 0.12×3 = 0 + 0.32 + 0.36 = 0.68
第 3 位: 0.72×2 + 0.16×1 + 0.12×0 = 1.44 + 0.16 + 0 = 1.60
第 4 位: 0.72×1 + 0.16×0 + 0.12×2 = 0.72 + 0 + 0.24 = 0.96

「it」这一步的新表示 = [2.28, 0.68, 1.60, 0.96]

读一下这个结果 —— 这是整章的落点。 把它和 pizza 的「我能给什么」[3, 0, 2, 1] 并排看,形状明显更像 pizza; 再和 man 的 [1, 3, 0, 2] 比一比,第 2 位差得最远(0.68 对 3)。

「it」这个位置里,已经掺进了七成的「pizza」 —— 这就是模型后面接的词 会像在说披萨、而不像在说那个男人的物理原因。

第 ⑩ 步,多头。 上面这九步,并排跑好几套,每套各有自己的三套权重,最后拼起来21

第 ⑪ 步,印证。 书拿真实模型跑了同一句话,把最后一层各套的分数取平均画出来 —— 「it」在 pizza 上的分数明显高于 man16我们编的 0.72 对 0.12,和书里那张图给出的方向一致;数是编的,结论是书里的。

9. 书里的立场与证据

书里给了证据的:

  • 「PyTorch」被切成两块、以及那七个编号 —— 拿一个真实的切词器跑出来的4;
  • 「it」在真实模型里更看向 pizza —— 拿一个现成的语言模型跑出来的,有图为证16;
  • 「球砸了男孩 / 男孩砸了球」 —— 这个例子本身就是证明,不需要额外数据。

作者的经验判断(书里没给证据):

  • 「一个头盯动名词、另一个头盯形容词和名词」 —— 举例说明,不是实测结论21;
  • 「维度越多,机器对含义的把握越好」 —— 定性说法,没有对照8

书里没交代来历的(全书零文献,这一章尤其严重):

  • 这套结构出自哪一篇 —— 一字未提,我们补在了脚注里25;
  • 位置编码为什么用三角函数 —— 只说了「用」,没说为什么(见第 3 节的补充块)。

书里对不上的: 那张二维图的坐标和正文差一个数 —— 见第 2.2 节末的判断块。

书里干脆没讲的: Q、K、V —— 图上画了,正文零命中。第 5 节整节是我们补的。

10. 边界与局限

这本书对的地方先说清: 这一章的前三层讲得相当好 —— 四层结构图给得清楚,「球砸男孩」那个例子是我们见过最省事的位置编码引子, 二维那张腿数-身高图也把「意思变成距离」讲得极其直观。「it」那次真实演示更是加分项。

但有三处要当心:

  1. 最关键的一层只讲了一半 —— 书号称「深潜」,可全书没有一个字解释那个分数怎么算。 一个读者读完这一章,能复述「它会去看别的词」,但复述不出任何一步计算。 第 5 节和第 8 节的第 ⑥–⑨ 步,整块是我们补的;
  2. 二维那张图正文和表格对不上 —— 见第 2.2 节末的判断块;
  3. 第 09 章那笔债这里才还上 —— 见第 3 节末的判断块。

这一章没覆盖的(全书零命中,不是这一章漏了):

  • 注意力之外的那些层。 真实结构里每个注意力模块后面还跟着一小段前馈网络, 而且每一层都带着「把这一层的输出加回输入」的接线和一次归一 —— 这些书一个字没有;
  • 编码器和解码器的分工。 书画的图只有一摞,没有讲这套结构原本是「一边读、一边写」的两半;
  • 生成的时候怎么防止偷看后文。 写作类模型必须挡住「还没写出来的词」,这件事零命中;
  • 上下文一长,计算量怎么涨。 每个词都要和每个词对分,这件事的代价随长度平方增长 —— 这正是第 10 章那个「窗口越大越贵越慢」的根子,而书两处都没接起来;
  • 公式一个字都没有。 这一章所有的算式在原书里是图片,提取出来是空的 —— 第 5、8 节那些式子全部是我们按机制补写的。

11. 可带走的

主走查一行写完: 「The man ate the pizza because it smelled delicious」→ 切成 token、换编号 → 每个编号取出一串数(词嵌入)→ 每串加上位置 → 每个词乘三套权重得到 Q / K / V → it 的 Q 和各词的 K 做点积(man 1.5、ate 2.0、pizza 5.0) → 各除以 √4 = 2 → softmax 得 0.12 / 0.16 / 0.72 → 按比例混各词的 V → it 的新表示 [2.28, 0.68, 1.60, 0.96],形状最像 pizza

  1. 一句话进模型要过四道工序:切词 → 词嵌入 → 位置编码 → 注意力;
  2. token ID 只是词典行号,不带意思;意思在它换出来的那串数里;
  3. 嵌入的全部要点是「意思相近 = 点挨得近」 —— 猫和狗在腿数-身高图上紧挨着;
  4. 真实模型的那串数有一千五百多个或三千多个 —— 人想象不出,机器算得动;
  5. 注意力本身看不见顺序,所以要另外把位置加进去 ——「球砸男孩」和「男孩砸球」;
  6. 第 09 章那个输给 LSTM 的模型,少的就是这一步(书归因于数据太小,没检查实现);
  7. 自注意力就是让每个词去看同一句话里的其他词,「自」字指的是三份数都来自同一句话;
  8. 每个词各出三份:「我在找什么」(Q)、「我是什么」(K)、「我能给什么」(V);
  9. 三份是同一串数乘三套训出来的权重得到的 —— 不是三样不同的东西;
  10. 分数四步走:点积 → 除以维度的平方根 → softmax → 按比例混 V;
  11. 除以平方根不是装饰:不除的话 pizza 会独占 0.93,把别的词挤到 0.03,这一层学不动;
  12. 多头就是并排跑好几套、各管一种关系,最后拼起来 —— 和第 08 章那 8 套是同一件事;
  13. 书那次演示要「取平均」,正是因为有好几个头,每个头各给一张分数表;
  14. 「先打分再加权混合」这一招,第 04、08、09、11 章各出现过一次 —— 对象分别是图像小块、图邻居、时刻、词;
  15. 书从头到尾没讲那个分数怎么算 —— 图上画了 Q、V、K,正文零命中;
  16. 每个词和每个词都要对一次分,所以代价随句子长度平方增长 —— 这就是上下文窗口越大越贵越慢的根子(书没接这一句)。

12. 原文地图

主题原书章原文位置
四层结构与图上的 Q V KChapter 9text/11-ch09-chapter-9.txt:1187(搜「basic structure of a transformer」) · text/11-ch09-chapter-9.txt:1193(搜「Q V K」)
注意力是模型的真正核心Chapter 9text/11-ch09-chapter-9.txt:1214(搜「This is the actual core of」)
切词与 token IDChapter 9text/11-ch09-chapter-9.txt:1220(搜「breaking down of text into smaller units」) · text/11-ch09-chapter-9.txt:1224(搜「token ID」) · text/11-ch09-chapter-9.txt:1231(搜「37863」)
词嵌入与二维例子Chapter 9text/11-ch09-chapter-9.txt:1206(搜「word embeddings」) · text/11-ch09-chapter-9.txt:1274(搜「number of legs」) · text/11-ch09-chapter-9.txt:1303(搜「similar concepts are closer」)
高维空间人想象不出Chapter 9text/11-ch09-chapter-9.txt:1300(搜「1536- or 3072-dimensional」)
勘误 那张表与正文对不上Chapter 9text/11-ch09-chapter-9.txt:1307(搜「human is defined by [2, 2]」) · text/11-ch09-chapter-9.txt:1316(搜「Human [4, 2]」)
位置编码Chapter 9text/11-ch09-chapter-9.txt:1208(搜「The ball hits the boy」) · text/11-ch09-chapter-9.txt:1333(搜「crucial technique for preserving the order」)
自注意力与 it 指谁Chapter 9text/11-ch09-chapter-9.txt:1342(搜「similarity of word embeddings」) · text/11-ch09-chapter-9.txt:1344(搜「focus only on the word it」)
真实模型上的演示Chapter 9text/11-ch09-chapter-9.txt:1368(搜「bert-base-uncased」) · text/11-ch09-chapter-9.txt:1395(搜「avg_attention」) · text/11-ch09-chapter-9.txt:1404(搜「most likely refers to pizza」)
多头Chapter 9text/11-ch09-chapter-9.txt:1406(搜「attention head」)
第 09 章那个缺位置的模型Chapter 8text/10-ch08-chapter-8.txt:644(搜「x = self.embedding(x)」) · text/10-ch08-chapter-8.txt:693(搜「RMSE: 0.11」)

Footnotes

  1. 出处:「Chapter 9」第 1186-1203 段(text/11-ch09-chapter-9.txt:1187,搜「basic structure of a transformer」与 text/11-ch09-chapter-9.txt:1193,搜「Q V K」)。原文:图 9.12 展示了 transformer 模型的基本结构,它由若干必须理解好的基础构件组成;最底层是传给模型的文本,例子里是「PyTorch is fun」这句话,文本先被切词。那张图从下往上依次是 Token → Token-ID → Word Embeddings → Positional Encoding → Attention,而 Attention 那一层的上方画着 Q、V、K 三个字母。全书正文没有任何一处解释这三个字母。 2 3

  2. 出处:「Chapter 9」第 1214-1217 段(text/11-ch09-chapter-9.txt:1214,搜「This is the actual core of」)。原文:下一步,数据被送入一个叫注意力的模块;这是模型真正的核心,因为模型正是在这里学到句子的内部结构、学到哪个词与哪个词相关。

  3. 出处:「Chapter 9」第 1219-1226 段(text/11-ch09-chapter-9.txt:1220,搜「breaking down of text into smaller units」与 text/11-ch09-chapter-9.txt:1224,搜「token ID」)。原文:切词就是把文本拆成更小的、称为 token 的单位;随后每个 token 被赋予一个唯一的数值,即 token ID —— 它相当于词典里的一条,而这本词典建立起人类词汇与所赋数值之间的映射。 2 3

  4. 出处:「Chapter 9」第 1231-1245 段(text/11-ch09-chapter-9.txt:1231,搜「37863」)。原文那张图里,「PyTorch is a lot of fun」被切成 Py / Torch / is / a / lot / of / fun,编号依次是 37863、162709、382、261、3261、328、2827;正文说这里用的是 GPT-4o 与 GPT-4o mini 的切词器,并且从「PyTorch 被切成 Py 和 Torch」这一点能看出它用的是子词切分。 2

  5. 出处:「Chapter 9」第 1205-1207 段(text/11-ch09-chapter-9.txt:1206,搜「word embeddings」)与第 1326-1327 段(text/11-ch09-chapter-9.txt:1326,搜「process of translating human texts into vectors」)。原文:这些词经过一个初始的网络模块,得出词嵌入 —— 这些词嵌入是反映每个词含义的向量;把人类文本翻译成向量的这个过程就叫嵌入,而且既可以表示单个词,也可以表示整段文本。

  6. 出处:「Chapter 9」第 1274-1277 段(text/11-ch09-chapter-9.txt:1274,搜「number of legs」)与第 1300-1304 段(text/11-ch09-chapter-9.txt:1303,搜「similar concepts are closer」)。原文:图 9.14 是一个很简单的例子,把一些生物按「腿数」和「体型高度」两个维度摆在一张二维图上;用这种方式表示信息,我们就了解到世界以及词的语义 —— 比如猫和狗在这两项特征上相当相似。关键之处在于:相似的概念之间比差异很大的概念之间靠得更近。 2

  7. 出处:「Chapter 9」第 1306-1324 段的表 9.1(text/11-ch09-chapter-9.txt:1312,搜「Dog [4, 1]」)。原文那张表给出的坐标:Dog [4, 1]、Cat [4, 0.5]、Elephant [4, 3]、Snake [0, 0.5]、Snail [0, 0.1]。「人」那一行两处对不上,见正文的判断块,我们没有采用。

  8. 出处:「Chapter 9」第 1298-1305 段(text/11-ch09-chapter-9.txt:1300,搜「1536- or 3072-dimensional」)。原文:我们人类能想象二维空间里的一个点,也能想象三维;但我们想象不出 1536 维或 3072 维的空间,而计算机可以轻松做到 —— 这很有用,因为词、图像、声音或任何其他信息的语义含义都可以在更高的维度里被表示;每多一个维度,计算机算法对一个词含义的把握就更好一分。 2 3 4

  9. 出处:「Chapter 9」第 1306-1307 段(text/11-ch09-chapter-9.txt:1307,搜「human is defined by [2, 2]」)与第 1316 段(text/11-ch09-chapter-9.txt:1316,搜「Human [4, 2]」)。正文说「在我们表 9.1 的例子里,狗被定义为 [4, 1],猫被定义为 [4, 0.5],人被定义为 [2, 2]」,而同一页的表 9.1 里 Human 那一行写的是 [4, 2];另外图 9.14 里「人」画在 2 条腿附近。

  10. 出处:「Chapter 9」第 1208-1213 段(text/11-ch09-chapter-9.txt:1208,搜「The ball hits the boy」)。原文:下一步是位置编码 —— 设想「The ball hits the boy」这句话,再设想「The boy hits the ball」;这说明词的顺序是有作用的:两句话用的是同样的词,但由于词的位置不同,意思完全不同;有了位置编码,模型才拿到「哪个词在哪个位置」这个信息。 2

  11. 出处:「Chapter 9」第 1332-1337 段(text/11-ch09-chapter-9.txt:1333,搜「crucial technique for preserving the order」)。原文:位置编码是保住词序的关键手段;实践中我们往词嵌入上加一个向量,这个向量含有该 token 在输入序列中绝对或相对位置的信息;数学实现上用的是正弦、余弦这类三角函数,好让模型能在整个序列长度上泛化并学到词的位置。书对位置编码的全部内容就是这一段。 2 3 4

  12. 补充(不在书里,依据我们的 ai-book-reference 书架):书只说用了三角函数,没说为什么。依据: book=dive-into-deep-learning §12-attention 事实=该章讲位置编码时给出两条理由 —— 低位变化快、高位变化慢的连续波形,比二进制表示省空间;而且它有一条关键的代数性质:任意固定的位置偏移都能用一个固定的线性变换表示,于是模型学得到相对位置关系。

  13. 出处:「Chapter 8」第 642-647 段(text/10-ch08-chapter-8.txt:644,搜「x = self.embedding(x)」)与第 689-697 段(text/10-ch08-chapter-8.txt:693,搜「RMSE: 0.11」)。那段 forward 的完整流程是 unsqueeze(-1) → 线性嵌入 → 编码器 → 取最后一个时间步 → 线性层,中间没有任何一步给不同时间位置加上可区分的信息;那个模型的成绩是 RMSE 0.11 / MAPE 12.12%,而同一份数据上 LSTM 是 0.08 / 8.79%(text/10-ch08-chapter-8.txt:461,搜「RMSE: 0.08」)。书对败因的全部解释是「模型复杂度要配得上数据复杂度」(text/10-ch08-chapter-8.txt:988,搜「the more the model complexity should match」)。

  14. 出处:「Chapter 9」第 1343-1347 段(text/11-ch09-chapter-9.txt:1344,搜「focus only on the word it」)。原文:图 9.15 用「The man ate the pizza because it smelled delicious」这句话演示这个过程;如果只盯着 it 这个词,它指的是什么?凭一点基本的语言知识,你可以教算法说它指某个名词 —— 但这里它可能指 man 也可能指 pizza;这正是自注意力登场的地方,它让模型「理解」词与词之间的关系,如果在足够多的数据上训练过,就应当能清楚 it 指 pizza 的可能性大得多。 2 3

  15. 出处:「Chapter 9」第 1340-1342 段(text/11-ch09-chapter-9.txt:1342,搜「similarity of word embeddings」)。原文:我们这里用自注意力这个例子来解释注意力 —— 它计算所有词与其自身之间在词嵌入上的相似度。这是书对「分数怎么来」给出的全部内容:一个「相似度」的名字,没有任何算式或步骤。 2

  16. 出处:「Chapter 9」第 1387-1404 段(text/11-ch09-chapter-9.txt:1395,搜「avg_attention」与 text/11-ch09-chapter-9.txt:1404,搜「most likely refers to pizza」)。原文:从模型结果里取出注意力权重,取最后一层、再对各头求平均得到平均注意力;图 9.16 展示了模型结果,图上的数字是基于词 it 的注意力权重 —— 由此可以清楚看出 it 最可能指的是 pizza。用的模型和切词器是 bert-base-uncased(text/11-ch09-chapter-9.txt:1368,搜「bert-base-uncased」)。 2 3 4

  17. 补充(不在书里,依据我们的 ai-book-reference 书架):Q/K/V 三份数从哪儿来、各管什么,原书完全没有。依据: book=happy-llm §02-attention 事实=该章把注意力的三个核心变量定为 Query(查询)、Key(键)、Value(值),并用查字典打比方:Query 是「我想查什么」,Key 是库里用来匹配的那一侧,Value 是匹配上之后取出来的内容;普通字典要求键完全相等,注意力不要求,它给每个键算一个相似度分数,再按分数把所有值加权平均。另参 book=dive-into-deep-learning §12-attention 事实=该章把注意力概括为「一个可微分的数据库查询」:给一堆键值对和一个查询,用查询与每个键的匹配度当权重,对值做加权平均。 2 3

  18. 补充(不在书里,依据我们的 ai-book-reference 书架):书用了「自注意力」这个名字,但没有解释「自」字对应什么条件。依据: book=dive-into-deep-learning §12-attention 事实=该章明确定义自注意力为「查询、键、值全部来自同一个序列」,以此与查询和键值来自不同序列的那一类注意力区分开。

  19. 补充(不在书里,依据我们的 ai-book-reference 书架):这四步在原书里一步都没有。依据: book=happy-llm §02-attention 事实=该章把注意力的完整算式拆成四步 —— 用点积算查询与每个键的相似度、把结果除以维度的平方根、过 softmax 变成加起来等于 1 的比例、再拿这组比例对各个值做加权求和。另参 book=building-large-language-models-from-scratch §06-attention-core 事实=该章按同一顺序逐步实现了这四步。

  20. 补充(不在书里,依据我们的 ai-book-reference 书架):为什么要除以维度的平方根,原书零命中。依据: book=happy-llm §02-attention 事实=该章给出的理由是:维度较大时点积的数值也会很大,而数值一大 softmax 就会被推到极端 —— 几乎全部比例集中到一个位置上、其余全成 0,梯度随之变小、模型学不动;把点积结果除以维度的平方根,就是把数值拉回一个温和的范围。另参 book=dive-into-deep-learning §12-attention 事实=该章从方差角度给出同一条理由。

  21. 出处:「Chapter 9」第 1405-1408 段(text/11-ch09-chapter-9.txt:1406,搜「attention head」)。原文:在真实的 transformer 里不止一个注意力模块(这样一个模块通常被称为一个注意力头),而是有多头注意力 —— 其中每个头关注词与词之间联系的不同方面,比如一个头可能关注动词与名词之间的关系,另一个头可能关注形容词与名词之间的关系。「各头的结果最后拼起来」这一句书里没有,是我们补的。 2 3

  22. 出处:「Chapter 4」第 184-222 段(text/06-ch04-chapter-4.txt:200,搜「patches」)。原文讲的是把图像切成图像块、做嵌入、再加位置嵌入,然后送进 transformer 编码器,并说细节留到第 9 章。

  23. 出处:「Chapter 7」第 484-489 段(text/09-ch07-chapter-7.txt:486,搜「learns an individual weighting」)。原文:这种层为每个节点的每一个邻居学出一个各自的权重,更相关的邻居权重更高、对新的节点表示贡献更多。

  24. 出处:「Chapter 8」第 165-171 段(text/10-ch08-chapter-8.txt:166,搜「reads the entire time series all at once」)。原文:设想 transformer 一次性读完整条时间序列,然后为每个数据点判断其他所有数据点对它的含义有多重要,并为每个数据点算出一组权重。

  25. 补充(不在书里):这套结构出自哪一篇,全书一字未提。来源:《Attention Is All You Need》(Vaswani 等八人,2017-06-12)https://arxiv.org/abs/1706.03762(查阅于 2026-08-25)。这一条与查阅日期取自我们书架上已核对过原文页面的记录: shelf=ai-book-reference/hands-on-large-language-models#01-two-branches.md 事实=该章第 313 行给出了这篇论文的标题、八位作者、2017-06-12 的提交日期与 arXiv 编号,并注明打开原文页面核对过。