这篇是给“只有初中数学基础,但想硬啃《Attention Is All You Need》原论文”的读者写的。
先说结论:
这篇论文的数学主线,不是神秘公式,而是五个朴素动作:把词变成数字表格、用乘法加法算相似度、把分数变成比例、按比例加权平均、再把这套动作堆很多层。
如果你已经被这些词劝退:
- vector
- matrix
- dot product
- softmax
- residual connection
- layer normalization
- positional encoding
- multi-head attention
- cross entropy
- learning rate schedule
不要急。它们看着像一串大学数学黑话,但读这篇论文不需要先补完整线性代数。你只需要先会:
- 加减乘除
- 表格
- 百分比
- 平均数
- 坐标点
- 简单函数
我会按论文顺序拆。每遇到一个公式,先讲它在论文里解决什么问题,再用小数字手算,最后把小数字换回论文符号。
论文到底想解决什么
《Attention Is All You Need》是 2017 年 Vaswani 等人的论文。它提出 Transformer:一种不用 RNN、也不用卷积,主要靠 attention 做序列转换的架构。
当时论文主要任务是机器翻译:
输入:I love apples.
输出:我 爱 苹果 。
这类问题叫 sequence transduction,可以先理解成:
把一个序列变成另一个序列。
旧架构常用 RNN。RNN 像一个人从左到右读句子:
第 1 个词 -> 第 2 个词 -> 第 3 个词 -> ...
它的问题是慢,因为后一步依赖前一步。第 100 个词想知道第 1 个词的信息,要经过很长的传话链。
Transformer 的野心是:
让每个词直接看见其他词,不再一个一个排队传话。
这就是 attention 的核心价值。
读论文前的最小数学地基
1. 向量:一行数字
向量不要想复杂。先把它当成一行数字:
[2, 5, 1]
一个词进入模型后,会被表示成很多数字。论文里 base Transformer 的每个 token 向量长度是:
d_model = 512
这表示每个词不是一个数字,而是 512 个数字。
小白可以先想成:
"apple" -> [0.2, -1.1, 0.7, ... 共 512 个数]
这些数字不是人工写的,是训练学出来的。
2. 矩阵:很多行数字组成的表格
矩阵就是数字表格:
[
[1, 2],
[3, 4],
[5, 6]
]
如果一句话有 3 个 token,每个 token 用 2 个数字表示,就能写成:
X =
[
[1, 0], # token 1
[0, 1], # token 2
[1, 1] # token 3
]
论文里常见的 Q、K、V 都可以先看成这种表格。
3. 点积:对应相乘,再相加
点积是 attention 里最重要的小动作。
两个向量:
a = [1, 2]
b = [3, 4]
点积就是:
a · b = 1×3 + 2×4 = 11
它可以用来粗略衡量“两个方向像不像”。结果越大,通常表示越匹配。
attention 里会用:
Query · Key
来算“我想找的东西”和“你贴出来的标签”有多匹配。
4. 加权平均:按比例混合内容
普通平均是每个人权重一样:
(10 + 20 + 30) / 3 = 20
加权平均是每个人贡献不同:
0.6×10 + 0.3×20 + 0.1×30 = 15
attention 最后的输出,本质上就是:
根据相关程度,按比例混合一堆 Value。
5. softmax:把分数变成比例
attention 会先算出一串分数:
[2, 1, -1]
这些还不是比例。比例必须满足:
每个数 >= 0
加起来 = 1
softmax 就是把任意分数变成比例。大致三步:
- 先把每个分数变成正数。
- 全部加起来。
- 每个数除以总和。
论文里 attention 的“看哪里”,就是由 softmax 决定的。
如果你想单独补这一块,可以读本站这篇:《Masked Softmax 到底在 mask 什么》。
论文第 3 节:Transformer 总架构
论文说,大多数序列转换模型都有 encoder-decoder 结构。
先翻译成人话:
- encoder:读懂输入句子。
- decoder:根据读懂的内容,一个词一个词生成输出句子。
论文符号写成:
(x1, ..., xn) -> z = (z1, ..., zn)
意思是:
输入 token 序列 x
经过 encoder
变成一串连续向量 z
然后 decoder 根据 z 生成:
(y1, ..., ym)
也就是输出 token。
这就是机器翻译:
英文 token -> encoder -> 理解后的向量序列 -> decoder -> 中文 token
自回归:一次只生成下一个词
论文说 decoder 是 auto-regressive。
人话:
生成第 i 个词时,只能看已经生成出来的前面词,不能偷看未来答案。
比如要生成:
我 爱 苹果
生成“爱”时,decoder 可以看“我”,但不能提前看“苹果”。
这就是后面 masked attention 的原因。
Encoder layer:两块积木
论文里的 encoder 由 N = 6 个相同层堆起来。每层有两块:
1. multi-head self-attention
2. position-wise feed-forward network
可以画成:
flowchart LR
X["输入 hidden states"] --> A["Multi-Head Self-Attention"]
A --> B["Add & LayerNorm"]
B --> C["Feed-Forward Network"]
C --> D["Add & LayerNorm"]
D --> Y["输出 hidden states"]
这里还有两个辅助动作:
- residual connection
- layer normalization
论文公式是:
拆开看:
x 原来的输入
Sublayer(x) 经过 attention 或 FFN 算出来的新信息
x + Sublayer(x) 原信息 + 新信息
LayerNorm(...) 把数值整理到更稳定的范围
residual connection:别把旧信息丢掉
x + Sublayer(x) 就是 residual connection。
人话:
每一层不要从零重写 token,而是在原来的表示上加一段改动。
这像改作文:不是把整篇删掉重写,而是在原稿上修改。
为什么有用?因为深层网络很容易训练困难。残差连接给信息留了一条直路,让模型更容易把前面层的信息传到后面。
LayerNorm:把每个 token 的数字整理一下
LayerNorm 可以先理解成:
把一行数字拉回比较稳定的范围。
比如某个 token 的向量是:
[100, 102, 98]
数值整体太大。另一个 token 是:
[0.01, 0.02, -0.01]
数值整体很小。网络层层相乘相加时,如果数值忽大忽小,训练会不稳定。
LayerNorm 做的事是:对每个 token 自己那一行数字,减去均值、除以波动大小,再学一个缩放和平移。你先不用会公式,只要知道它在维持数值稳定。
Decoder layer:三块积木
decoder 每层比 encoder 多一块。
1. masked multi-head self-attention
2. encoder-decoder attention
3. position-wise feed-forward network
画成:
flowchart LR
Y0["已生成的输出 token"] --> M["Masked Self-Attention"]
M --> E["Encoder-Decoder Attention"]
Z["encoder 输出 z"] --> E
E --> F["Feed-Forward Network"]
F --> Y1["下一层 decoder 表示"]
第一块 masked self-attention 只看已经生成的输出。
第二块 encoder-decoder attention 会看 encoder 输出,也就是输入句子的理解结果。
这两种 attention 的数学形式一样,差别在 Q/K/V 来自哪里。后面会讲。
论文第 3.2 节:Attention 是什么
论文对 attention 的定义很漂亮:
一个 attention 函数把 query 和一组 key-value pairs 映射到一个 output。
翻译成图书馆:
Query:我想找什么
Key:每本书贴出来的标签
Value:书里的真正内容
Output:我按相关程度读完几本书后得到的新理解
对应到 Transformer:
- Query:当前 token 想找什么信息。
- Key:其他 token 暴露给别人匹配的标签。
- Value:其他 token 真正能贡献的内容。
如果想更细补 QKV,可以读本站这篇:《QKV 投影到底在投什么》。
Scaled Dot-Product Attention:论文最核心公式
论文公式是:
这是整篇论文最关键的公式。先不要怕,我们按四步拆:
1. QK^T
用 Query 和 Key 算匹配分数
2. 除以 sqrt(d_k)
把分数缩小一点,避免太大
3. softmax
把分数变成权重比例
4. 乘 V
按权重混合真正内容
用小数字手算一遍
假设当前 token 的 Query 是:
q = [1, 2]
有三个历史 token 的 Key:
k1 = [1, 0]
k2 = [0, 1]
k3 = [1, 1]
先算点积:
q · k1 = 1×1 + 2×0 = 1
q · k2 = 1×0 + 2×1 = 2
q · k3 = 1×1 + 2×1 = 3
得到分数:
[1, 2, 3]
因为向量长度 d_k = 2,论文会除以:
缩放后约等于:
[0.71, 1.41, 2.12]
再 softmax,得到一组大致权重:
[0.14, 0.28, 0.58]
意思是:
第 1 个 token 看 14%
第 2 个 token 看 28%
第 3 个 token 看 58%
现在假设三个 token 的 Value 是:
v1 = [10, 0]
v2 = [0, 20]
v3 = [10, 10]
按权重加权平均:
output
= 0.14×[10, 0] + 0.28×[0, 20] + 0.58×[10, 10]
= [1.4, 0] + [0, 5.6] + [5.8, 5.8]
= [7.2, 11.4]
这就是 attention 输出。
一句话:
attention 不是复制某一个词,而是按相关程度混合一堆词的信息。
QK^T 到底是什么
如果一共有很多 Query 和很多 Key,论文不会一个一个写点积,而是把它们打包成矩阵。
假设:
Q =
[
q1,
q2,
q3
]
K =
[
k1,
k2,
k3
]
那么:
QK^T
就是一张分数表:
| k1 | k2 | k3 | |
|---|---|---|---|
| q1 | q1·k1 | q1·k2 | q1·k3 |
| q2 | q2·k1 | q2·k2 | q2·k3 |
| q3 | q3·k1 | q3·k2 | q3·k3 |
每一行表示:
某个 token 在看所有 token 时,给每个 token 打多少分。
softmax 通常对每一行做。于是每一行都变成一组加起来等于 1 的注意力权重。
为什么要除以 sqrt(d_k)
论文说,如果 d_k 很大,点积会变大,把 softmax 推到梯度很小的区域。所以要除以:
小白先用这个直觉理解:
点积是很多个“小乘法结果”的总和。维度越多,加起来越容易变大。
比如 2 维点积:
1×1 + 1×1 = 2
8 维点积:
1×1 + 1×1 + ... 共 8 项 = 8
项数越多,分数越容易变大。softmax 遇到很大的分数,会变得特别偏心:
softmax([20, 1, 0]) ≈ [几乎 1, 几乎 0, 几乎 0]
这样模型早早只盯一个位置,训练时也不容易调整。
除以 sqrt(d_k) 就像给分数降温,让 softmax 不要太尖。
在论文 base 模型里:
d_model = 512
h = 8
d_k = 64
sqrt(d_k) = 8
所以每个 head 的 QK 点积会除以 8。
Multi-Head Attention:为什么要多头
论文公式是:
其中:
翻译成人话:
不要只用一个角度看句子。先把 Q/K/V 投影成多个小空间,每个空间各算一次 attention,再把结果拼起来混合。
论文 base 模型数字是:
d_model = 512
h = 8
d_k = d_v = 512 / 8 = 64
也就是:
原来每个 token 512 个数字
分成 8 个 head
每个 head 看 64 个数字
为什么这有用?
一个 head 可能更擅长看附近词。另一个 head 可能更擅长看主谓关系。另一个 head 可能更擅长看指代关系。当然,真实 head 不一定能被人类干净命名,但多头至少给模型提供了多个并行观察角度。
如果只有一个 head,attention 输出是一次加权平均,很多信息会被混在一起。multi-head 让模型可以同时做多种加权平均。
最后的 Concat(... )W^O 做两件事:
Concat:把 8 个 head 的结果拼回 512 维。W^O:再用一个矩阵重新混合,让多头结果回到通用 hidden 空间。
这一块可以接着读本站:《Out 投影到底在输出什么》。
Transformer 里三种 attention
论文第 3.2.3 说 Transformer 用了三种 multi-head attention。
1. Encoder self-attention
encoder 里,Q/K/V 都来自输入句子上一层的表示。
英文句子内部互相看
比如翻译这句:
The animal didn't cross the street because it was tired.
it 要看前面的词,判断指的是 animal 还是 street。encoder self-attention 就负责这种输入内部的信息交互。
2. Decoder masked self-attention
decoder 里,生成中文时,已经生成的中文 token 之间互相看。
但它不能看未来。
比如正在生成第 3 个词:
我 爱 ?
它可以看“我”“爱”,不能偷看后面的标准答案。
论文做法是:在 softmax 前,把非法位置设成 -∞。
为什么 -∞ 有用?因为 softmax 后它的权重会变成 0。
未来 token 的分数 = -∞
softmax 后权重 = 0
这就是 mask。
3. Encoder-decoder attention
decoder 生成中文时,还要看英文输入。
这时:
- Query 来自 decoder。
- Key 和 Value 来自 encoder 输出。
人话:
我现在要生成一个中文词。
我拿当前中文上下文当问题 Q。
去英文句子理解结果里找相关信息 K/V。
这就是翻译里的“对齐”直觉:生成某个中文词时,去看输入英文里相关的位置。
Position-wise FFN:每个位置单独过两层小网络
论文公式:
拆成四步:
1. xW1 + b1
先做一次线性变换
2. max(0, ...)
ReLU:负数变 0,正数保留
3. 再乘 W2
再做一次线性变换
4. + b2
加偏置
ReLU 是什么
ReLU 就是:
max(0, x)
例子:
| 输入 | ReLU 输出 |
|---|---|
| -3 | 0 |
| -1 | 0 |
| 0 | 0 |
| 2 | 2 |
| 5 | 5 |
它给网络加入非线性。没有 ReLU,很多层线性变换叠起来,本质上仍然像一层线性变换,表达力会弱。
为什么叫 position-wise
因为 FFN 对每个位置单独做同一套计算。
attention 负责:
token 之间互相交流
FFN 负责:
每个 token 自己内部的 512 个特征再加工
论文里的维度:
d_model = 512
d_ff = 2048
也就是:
512 -> 2048 -> 512
先把表示放大到 2048 维加工,再压回 512 维。
Embedding 和最后的 softmax
论文第 3.4 讲 embeddings and softmax。
embedding:把 token 编号变成向量
模型不能直接读文字。它先把文字切成 token,再把 token 变成向量。
"apple" -> token id 3912 -> embedding 向量 [0.2, -1.1, ...]
论文里输入 token 和输出 token 都映射到:
d_model = 512
最后的 softmax:把 decoder 输出变成下一个词概率
decoder 最后一层输出的仍然是向量,不是词。
要预测下一个 token,需要:
decoder hidden
-> 线性变换
-> 每个词表 token 一个分数 logits
-> softmax
-> 概率分布
比如词表只有 5 个词:
| token | logit | softmax 后概率 |
|---|---|---|
| 我 | 1.2 | 0.18 |
| 爱 | 0.3 | 0.07 |
| 苹果 | 3.0 | 0.68 |
| 电脑 | 0.5 | 0.09 |
| 。 | -1.0 | 0.01 |
模型会根据这个分布生成下一个 token。
论文还提到 embedding 权重和 pre-softmax 线性变换共享权重,并在 embedding 层乘以:
小白先记成:
输入查词表和输出猜词表,用的是同一张词向量表的两种方向;乘以根号维度是为了让数值尺度更合适。
Positional Encoding:没有 RNN 后,顺序从哪里来
RNN 天然知道顺序,因为它从左到右读。
Transformer 一次让所有 token 互相看。这样很并行,但问题来了:
如果不额外告诉它位置,它怎么知道哪个词在第 1 个,哪个词在第 10 个?
论文解决方法:给每个 token 的 embedding 加上 positional encoding。
token embedding + position encoding
embedding 表示“这个词是什么”。position encoding 表示“这个词在哪个位置”。
论文的 sin/cos 公式
论文使用:
看不懂没关系。先拆符号:
pos:token 在句子里的位置。i:向量里的第几个维度。sin、cos:可以理解成周期性波浪。10000^{...}:让不同维度的波浪频率不同。
为什么要很多频率?
因为只用一种波浪,很快会重复。不同频率叠在一起,就像给每个位置发一个复杂的座位编号。
位置 1 有一串波纹数字。位置 2 有另一串。位置 100 也有一串。
论文选择 sin/cos 的一个原因是:模型可能更容易学到相对位置。
人话:
如果两个词相隔 3 个位置,不管它们出现在句首还是句尾,这个“相隔 3”的关系都应该容易被模型识别。
论文也实验了 learned positional embedding,效果几乎一样;最后选择 sinusoidal,是因为它可能更容易外推到训练时没见过的更长序列。
如果你想补 sin/cos 和位置编码的直觉,可以读本站:《欧拉公式:旋转如何藏进 LLM 的 RoPE 位置编码》。
论文第 4 节:为什么 self-attention
论文比较了 self-attention、RNN、卷积。这里数学重点是复杂度和路径长度。
n 和 d 是什么
论文表格里:
n:序列长度,也就是 token 数。d:每个 token 的向量维度。
比如:
n = 100 句子有 100 个 token
d = 512 每个 token 有 512 个数字
Self-attention 的复杂度
self-attention 要让每个 token 看每个 token。
如果有 n 个 token,就有大约:
n × n
对关系。
所以论文写:
小白读法:
序列越长,attention 的关系表按平方增长。
100 个 token 是 10,000 对关系。1000 个 token 是 1,000,000 对关系。
这就是后来长上下文模型很贵的根本原因之一。
但 self-attention 很并行
RNN 必须从左到右一步步走:
第 1 步 -> 第 2 步 -> 第 3 步 -> ...
论文说 RNN 的 sequential operations 是:
self-attention 一层里,所有 token 的关系可以同时算,所以 sequential operations 是:
小白读法:
attention 计算总量不一定最小,但它非常适合 GPU 一起算。
path length:远距离信息要传几手
论文还比较 maximum path length。
这个词很关键。
假设第 1 个词的信息要影响第 100 个词。
在 RNN 里,它要一站一站传:
1 -> 2 -> 3 -> ... -> 100
路径长度大约是 n。
在 self-attention 里,第 100 个词可以直接看第 1 个词:
1 -> 100
路径长度是常数。
这就是论文为什么强调 self-attention 擅长 long-range dependencies。
人话:
长距离关系在 Transformer 里不需要层层传话,可以直接连线。
论文第 5 节:训练里的数学
BPE:把词切成更小单位
论文使用 byte-pair encoding 或 word-piece vocabulary。
小白理解:
模型不是直接用完整单词,而是把文字切成更小的 token。
好处是词表不会无限大,罕见词也能由小片段拼出来。
Adam:自动调参数的优化器
训练就是不断调整权重,让模型更会预测下一个 token。
普通梯度下降像这样:
参数 = 参数 - 学习率 × 梯度
Adam 是更聪明的版本。它会参考:
- 梯度最近的平均方向。
- 梯度波动大小。
- 一个很小的 epsilon 防止除零。
论文参数:
β1 = 0.9
β2 = 0.98
ε = 10^-9
不用背。知道它们是 Adam 的控制旋钮就够。
学习率 schedule:先热身,再慢慢降
论文学习率公式:
看着吓人,其实是两段策略:
前 4000 步:学习率逐渐升高
4000 步之后:学习率慢慢降低
为什么要 warmup?
训练刚开始,参数还很乱。如果学习率一上来太大,模型可能乱跳。先小步热身,等模型进入状态后再放大步子。
为什么后面降低?
后期接近好区域,步子太大容易错过细节,所以慢慢减小。
论文用:
warmup_steps = 4000
Dropout:训练时故意随机关掉一点
dropout 是防过拟合的方法。
人话:
训练时随机让一部分通道暂时失效,逼模型不要太依赖某几个特征。
论文在多个地方使用 dropout:
- sub-layer 输出加回 residual 前。
- embedding 和 positional encoding 相加后。
base model 使用:
Pdrop = 0.1
也就是大约 10% 随机关掉。
Label smoothing:别让模型太自信
普通训练会告诉模型:
正确词概率应该是 1
其他词概率应该是 0
label smoothing 会把它软化一点。
比如词表只有 5 个词,正确答案是“苹果”。
硬标签:
[0, 0, 1, 0, 0]
软一点:
[0.025, 0.025, 0.9, 0.025, 0.025]
论文使用:
ε_ls = 0.1
这会让模型别把全部概率压到一个词上。论文说它会伤害 perplexity,因为模型被训练得更不绝对自信,但能改善 accuracy 和 BLEU。
如果你想补交叉熵、PPL,可以读本站:《困惑度 PPL 到底是什么》。
论文第 6 节:结果里的数学
BLEU:翻译质量分数
BLEU 是机器翻译常用指标。粗略理解:
模型翻译和参考翻译有多少 n-gram 重合,同时惩罚太短的翻译。
论文报告:
- English-to-German:Transformer big 达到 28.4 BLEU。
- English-to-French:Transformer big 达到 41.8 BLEU。
这里不要把 BLEU 理解成“百分制理解能力”。它只是翻译任务上的一种自动评价指标。
FLOPs:训练花了多少计算
FLOPs 表示浮点运算次数。
论文比较了模型质量和训练成本。核心想表达:
Transformer 不只是效果好,还能更并行、更快训练。
base model 训练 100,000 steps,大约 12 小时。big model 训练 300,000 steps,大约 3.5 天,硬件是 8 张 NVIDIA P100。
PPL:模型有多意外
Table 3 里还有 PPL,也就是 perplexity。
直觉:
PPL 越低,模型对正确 token 越不意外。
但论文也提醒 label smoothing 会让模型更不自信,所以 PPL 可能变差,而 BLEU 反而变好。
这说明:
一个数学指标不等于全部能力。
Table 3:模型变体给我们的数学启发
论文做了 ablation,也就是改某个部件,看效果怎么变。
head 数不是越多越好
论文试了不同 head 数。单 head 比较差,但 head 太多也会下降。
原因可以这样理解:
d_model 固定时,head 越多,每个 head 分到的维度越少。
如果每个 head 太窄,它单独判断相似度的能力会变弱。
所以多头 attention 是平衡:
观察角度要多,但每个角度也要有足够表达空间。
d_k 太小会伤质量
论文观察到 reducing attention key size d_k hurts model quality。
人话:
Key 空间太小,模型就不容易判断“谁和谁匹配”。
这说明 compatibility function 不是简单小技巧,而是 attention 的核心。
大模型更好,但 dropout 很重要
论文里更大的 d_model、d_ff 通常效果更好。
但如果没有合适 dropout,容易过拟合。
这给小白一个朴素判断:
容量、数据、正则化要一起看。模型变大不是单独发生的好事。
sinusoidal 和 learned position 差不多
论文把 sin/cos position encoding 换成 learned positional embedding,结果接近。
这说明:
当时 Transformer 成功的核心,不是某一个位置编码公式,而是 attention-only 架构整体。
不过 sin/cos 位置编码有外推长度的潜在优势,所以论文采用了它。
从头到尾看,论文涉及哪些数学
现在把论文里的数学按模块收拢成清单。
| 论文位置 | 数学概念 | 小白读法 |
|---|---|---|
| encoder-decoder | 序列到序列函数 | 输入一串 token,输出另一串 token |
| embedding | 查表、向量 | token id 变成一行数字 |
| Q/K/V projection | 矩阵乘法 | 把同一份 hidden 变成三种角色 |
| dot product | 乘法再相加 | 算 Query 和 Key 有多匹配 |
| scaling | 除以根号维度 | 防止分数太大 |
| softmax | 分数转比例 | 决定看各个 token 的权重 |
| weighted sum | 加权平均 | 按权重混合 Value |
| multi-head | 多组投影并行 | 多个角度同时看句子 |
| concat + output projection | 拼接和再混合 | 把多头结果混回 hidden |
| mask | 禁止未来信息 | 生成时不能偷看答案 |
| residual | 原输入加新变化 | 保留旧信息,方便训练深层网络 |
| LayerNorm | 标准化 | 控制数值范围 |
| FFN | 两层线性 + ReLU | 每个 token 内部再加工 |
| positional encoding | sin/cos 波纹编号 | 告诉模型 token 位置 |
| Big-O | 粗略成本 | attention 长度平方增长,但并行好 |
| Adam | 优化器 | 自动调权重 |
| warmup schedule | 学习率变化 | 先热身,再减速 |
| dropout | 随机失活 | 防止死记硬背 |
| label smoothing | 软标签 | 别让模型过度自信 |
| BLEU/PPL/FLOPs | 指标 | 质量、困惑度、计算成本 |
真正啃论文时怎么读
建议按这个顺序读原文。
第一次读:只抓结构
先跳过公式细节,只看:
encoder
decoder
self-attention
encoder-decoder attention
FFN
positional encoding
training
results
目标是知道论文在搭一台什么机器。
第二次读:只攻公式 1
公式 1:
必须啃下来。
如果这行懂了,论文一半就通了。
第三次读:攻 multi-head
公式:
要能说出:
W_i^Q / W_i^K / W_i^V 是第 i 个 head 的投影矩阵
每个 head 先变换 Q/K/V
再单独算 attention
最后拼起来
第四次读:攻位置编码和复杂度表
位置编码不用背公式推导。你要懂:
没有 RNN/卷积,就必须额外注入顺序
sin/cos 给每个位置一串可外推的波纹编号
复杂度表要懂:
self-attention: token 两两连接,所以 n²
RNN: 一步步传,所以顺序长度 n
self-attention path length 短,长距离依赖更容易
第五次读:看实验,不神化指标
Table 2 看效果和成本。
Table 3 看组件变化。
记住:
论文不是只说“attention 好”,而是说 attention-only 架构在翻译任务上效果好、并行性强、训练快,而且 ablation 支持多头、key 维度、dropout、模型规模这些设计选择。
这篇论文和现在大模型的关系
今天很多大语言模型是 decoder-only Transformer,而原论文是 encoder-decoder Transformer,用于翻译。
所以不要把原论文里的每个结构直接等同于现代 LLM。
但核心数学仍然是同一套:
token -> embedding
hidden -> Q/K/V
QK^T -> softmax -> V
multi-head
residual
norm
FFN
logits -> softmax
cross entropy training
现代模型会改很多细节:
- 用 decoder-only。
- 用 causal mask。
- 用 RMSNorm 或 pre-norm。
- 用 RoPE 替代原始 sin/cos 加法位置编码。
- 用 SwiGLU 等 FFN 变体。
- 用 GQA/MQA 改 KV head。
- 用 FlashAttention 优化计算。
但如果你读懂这篇论文的数学主线,后面看这些变体就不是从零开始。
读完要能回答的 12 个问题
- token 为什么要先变成 embedding 向量?
- Q、K、V 分别是什么角色?
- 点积为什么能当相似度分数?
QK^T为什么是一张分数表?- attention 为什么要 softmax?
- softmax 后为什么要乘 V?
- 为什么要除以
sqrt(d_k)? - multi-head 比 single-head 多了什么?
- decoder 为什么需要 mask?
- residual connection 为什么是
x + Sublayer(x)? - positional encoding 解决什么问题?
- self-attention 的
n²成本和O(1)路径长度分别是什么意思?
这 12 个问题能答出来,就可以回去读原论文。读不懂的部分,不再是“完全陌生”,而是某个局部概念还要补。
最后一句
《Attention Is All You Need》的数学,不是为了把人挡在门外。
它真正说的是:
把每个词变成向量,让词和词之间直接打分,再按分数混合信息;把这件事并行做很多次、堆很多层,就能替代过去一步步传话的序列模型。
这就是 Transformer 的第一性原理。
你不需要一开始就懂所有证明和工程优化。先把这条链背后的加减乘除吃透:
向量
-> 点积
-> softmax
-> 加权平均
-> 多头
-> 残差和归一化
-> 逐 token FFN
-> 下一词概率
再回头看论文,公式就不再是一堵墙,而是一张机器说明书。