《Attention Is All You Need》论文深度拆解:从数学原理到 Transformer 工程实现
这篇论文是现代大语言模型技术体系中最值得深入研究的基础论文之一。它提出的 Transformer 架构,改变了自然语言处理的发展方向,并成为后来 GPT、BERT 以及众多大语言模型架构的重要基础。
如果只是了解 Attention、Multi-Head Attention、Positional Encoding 等概念,很容易出现一种情况:每个模块都知道是什么,却不清楚为什么需要它们、它们之间如何协作,以及这些设计究竟解决了什么问题。
因此,我会以你上传的论文原文为主要依据,按照以下思路展开:
- 研究背景与核心问题:Transformer 为什么会出现?它究竟解决了什么问题?
- 整体架构:Encoder、Decoder 分别承担什么职责?
- 核心数学原理:从 Q、K、V 开始,逐步推导 Scaled Dot-Product Attention。
- Multi-Head Attention:为什么需要多个注意力头?它们如何协作?
- 位置编码:没有 RNN 和 CNN,模型如何理解词语顺序?
- 完整网络结构:残差连接、Layer Normalization、FFN、Mask 分别发挥什么作用?
- 训练机制与实验结果:论文如何证明 Transformer 的有效性?
- 局限性与后续演进:从原始 Transformer 到现代 GPT,哪些设计被保留、修改或舍弃?
- 动手实现:通过代码和张量维度变化,真正理解模型如何运行。
分析时,我会区分三类内容:论文明确提出的结论、根据数学原理展开的解释,以及结合现代大模型发展的延伸分析,避免把今天的技术倒推成论文当年的结论。
一、论文究竟讲了什么?
1.1 论文基本信息
论文名称:Attention Is All You Need
- 作者:Ashish Vaswani 等人
- 发表会议:NIPS 2017,即今天的 NeurIPS
- 论文编号:arXiv:1706.03762
- 核心贡献:提出完全基于 Attention、摆脱循环网络和卷积网络的序列转换架构 Transformer。
你上传的论文第 1 页明确提出:Transformer 完全依赖 Attention 机制,不再使用传统的循环结构和卷积结构;实验表明,它在机器翻译任务中取得了更好的效果,同时具有更强的并行训练能力和更短的训练时间。Attention Is All You Need(2)
论文原文:arXiv: Attention Is All You Need
1.2 这篇论文真正解决的是什么问题?
先暂时忘掉 Transformer 的所有术语。
假设我们要让计算机翻译下面这句话:
The animal didn’t cross the street because it was too tired.
要正确理解这句话,模型必须知道:
animal是什么?street是什么?it指代什么?tired描述的是谁?- 前面出现的词语,如何影响后面词语的含义?
这不是简单的单词替换问题,而是一个需要建模序列内部依赖关系的问题。
在 Transformer 出现之前,循环神经网络(RNN)、长短期记忆网络(LSTM)等模型,是解决这类问题的主流技术路线之一。
但它们存在一个重要的工程问题:处理一个序列时,后一个位置的计算通常依赖前一个位置的计算结果。
例如,模型按顺序处理:
1 | The → animal → didn't → cross → the → street → ... |
要处理下一个位置,通常需要先获得前一个位置的隐藏状态。
这导致训练时难以同时计算序列中所有位置的表示。
论文第 2 页明确指出,循环模型沿序列位置展开计算,其固有的顺序依赖限制了单个训练样本内部的并行化能力。Attention Is All You Need(2)
传统 RNN 的问题
假设输入有 100 个 Token。
传统 RNN 的计算大致如下:
1 | Token 1 |
即使 GPU 可以同时执行大量矩阵运算,这种依赖关系仍然限制了计算顺序。
当然,RNN 并不是完全无法并行:不同样本可以并行,部分计算也可以优化。但同一个样本内部的时间步存在依赖链。
问题在于,序列越长,这种依赖关系就越明显。
Transformer 的解决思路
Transformer 换了一种方式:
不再要求模型必须按顺序处理输入中的每一个 Token,而是让每个 Token 直接与其他 Token 建立信息交互。
例如:
1 | The ─────────┐ |
上图表达的是信息交互的概念,而不是实际的 Attention 权重。
在 Self-Attention 中,每个位置都可以根据当前任务需要,从其他位置获取信息。
于是,模型可以直接建立两个相距很远的 Token 之间的联系,而不必像传统 RNN 那样,通过逐步传递隐藏状态来传播信息。
这就是 Transformer 的第一个关键思想:
用 Attention 建立全局依赖,用矩阵运算实现高效并行。
不过,这里有一个重要细节:
Transformer 并不是完全消除了所有顺序计算。原始论文中的 Decoder 在生成目标序列时仍然采用自回归方式,需要逐 Token 生成;主要的并行化优势体现在训练阶段,以及 Encoder 内部对整个输入序列的处理上。
理解这一点,才能正确认识 Transformer 的优势和边界。
二、Transformer 的整体架构
理解 Transformer,最重要的是先建立整体结构,再深入每个模块。
论文第 3 节给出了原始 Transformer 的完整架构。它采用经典的 Encoder-Decoder 结构:Encoder 将输入序列编码为一组上下文表示,Decoder 根据这些表示逐步生成输出序列。Attention Is All You Need(2)
2.1 原始 Transformer 的结构图
原始 Transformer 可以简化为:
1 | 输入文本 |
这里需要注意:图中的 Decoder 是原始机器翻译 Transformer 的 Decoder,而不是所有现代大语言模型都采用的结构。
2.2 Encoder 和 Decoder 分别做什么?
Encoder:理解输入序列
假设输入:
1 | The cat sat on the mat. |
经过 Embedding 后,每个 Token 被转换为一个向量。
Encoder 通过多层 Self-Attention 和 Feed-Forward Network,让每个 Token 的表示逐渐融入上下文信息。
例如:
1 | 输入 Token:cat |
这只是帮助理解的示意,并不意味着每一层都严格对应某种固定的语义功能。
最终,Encoder 输出一组向量:
[
Z=(z_1,z_2,\ldots,z_n)
]
每个 (z_i) 都对应输入序列中的一个位置。
Decoder:根据已有信息生成输出
假设目标是将英文翻译成中文。
Encoder 负责处理英文输入,Decoder 则负责逐步生成中文译文。
例如:
1 | 第 1 步:生成「猫」 |
实际翻译当然会根据完整的输入语境决定每一步输出什么。
在生成每个 Token 时,Decoder 会利用两类信息:
- 已经生成的目标序列。
- Encoder 对源语言输入的编码结果。
因此,原始 Decoder 中存在两种不同的 Attention:
- Masked Self-Attention:关注当前已经允许访问的目标序列位置。
- Cross-Attention:关注 Encoder 输出的源序列表示。
2.3 为什么要区分这两种 Attention?
假设 Decoder 正在生成第三个 Token。
此时,假设已经生成:
1 | 猫 坐 |
Decoder 可以利用:
1 | 猫 |
但不能利用第四、第五个 Token 的真实答案,因为它们尚未生成。
这就是 Masked Self-Attention 的作用。
与此同时,Decoder 可以查看完整的 Encoder 输出,因为源语言输入在生成开始前就已经存在。
因此:
| 模块 | Query 来源 | Key、Value 来源 | 主要作用 |
|---|---|---|---|
| Encoder Self-Attention | Encoder 当前层输入 | 同一组 Encoder 输入 | 建模输入序列内部的关系 |
| Decoder Masked Self-Attention | Decoder 当前层输入 | 同一组 Decoder 输入 | 建模已生成目标序列的关系 |
| Cross-Attention | Decoder 当前层输入 | Encoder 最终输出 | 将源序列信息引入生成过程 |
这个表非常重要,因为它直接决定了后面 Q、K、V 的具体来源。
2.4 原始模型的关键配置
论文第 3 节采用了以下基础配置:Encoder 和 Decoder 各包含 6 层,每层模型维度为 512,Multi-Head Attention 使用 8 个注意力头。每个头的 Key 和 Value 维度均为 64。Attention Is All You Need(2) Attention Is All You Need(2)
| 参数 | 原始 Transformer Base |
|---|---|
| Encoder 层数 | 6 |
| Decoder 层数 | 6 |
| 模型维度 (d_{\text{model}}) | 512 |
| Attention Head 数量 | 8 |
| 每个 Head 的 Key 维度 (d_k) | 64 |
| 每个 Head 的 Value 维度 (d_v) | 64 |
| FFN 中间层维度 (d_{ff}) | 2048 |
需要明确:这些数字是原始论文中的配置,并不是 Transformer 架构的固定限制。
现代大语言模型可以使用不同的层数、隐藏维度、注意力头数和 FFN 结构。
三、深入理解 Attention:Q、K、V 到底是什么?
这是整篇论文最核心的部分。
如果只能选择一个模块深入研究,应该选择 Attention。
因为只有理解 Attention 的计算过程,才能真正理解 Transformer 如何让一个 Token 利用其他 Token 的信息。
3.1 先从一个直观例子开始
考虑下面这句话:
The animal didn’t cross the street because it was tired.
假设模型正在处理 it。
模型需要判断:为了更好地表示 it,应该从上下文中的哪些 Token 获取信息?
可能与以下词语建立较强的联系:
1 | animal |
注意,这只是用于说明的假设,不代表原论文在这句话上测得了这些具体权重。
模型需要一种机制,完成三个步骤:
- 判断哪些位置值得关注。
- 计算每个位置的重要程度。
- 按照这些权重整合其他位置的信息。
Attention 就是为此设计的。
3.2 Query、Key、Value 的直觉解释
可以用信息检索系统来理解。
假设有一个数据库:
1 | Key Value |
当你提出一个查询时:
- Query(Q):当前需要什么信息。
- Key(K):每条信息用于匹配查询的特征。
- Value(V):真正需要提取的信息内容。
模型比较 Query 和各个 Key,计算相关程度,然后对 Value 进行加权组合。
这里的类比只是帮助建立直觉。神经网络中的 Q、K、V 并不是人工定义的标签,而是通过可训练的线性变换得到的向量。
一个简单例子
假设有三个 Token:
1 | animal |
当前要计算 it 的上下文表示。
我们可以想象它生成一个 Query:
1 | Q_it = [表示当前需要的信息的特征] |
其他 Token 则有各自的 Key:
1 | K_animal |
模型计算:
[
s_{\text{it},j}=Q_{\text{it}}K_j^\top
]
得到每个位置的相关性分数。
随后,通过 Softmax 将分数转换为权重:
[
\alpha_{\text{it},j}
\frac{\exp(s_{\text{it},j})}
{\sum_k \exp(s_{\text{it},k})}
]
最后,利用这些权重对 Value 加权求和:
[
z_{\text{it}}=\sum_j \alpha_{\text{it},j}V_j
]
于是,it 的新表示就融入了其他 Token 的信息。
核心理解:Attention 并不是简单地给每个词打分,而是根据当前 Query 动态地选择和整合其他位置的信息。
3.3 从数学角度推导 Attention
论文提出的 Scaled Dot-Product Attention,其公式是:
[
\boxed{
\operatorname{Attention}(Q,K,V)
\operatorname{softmax}
\left(
\frac{QK^\top}{\sqrt{d_k}}
\right)V
}
]
这是理解 Transformer 必须掌握的公式。论文第 4 页正式给出了这一表达式。Attention Is All You Need(2)
我们逐步拆解。
第一步:计算 Query 和 Key 的点积
[
S=QK^\top
]
假设输入序列有 3 个 Token,每个向量维度为 2。
为了方便理解,先假设:
[
Q=
\begin{bmatrix}
1&0\
0&1\
1&1
\end{bmatrix}
]
[
K=
\begin{bmatrix}
1&0\
0&1\
1&1
\end{bmatrix}
]
那么:
[
K^\top=
\begin{bmatrix}
1&0&1\
0&1&1
\end{bmatrix}
]
因此:
[
S=QK^\top
\begin{bmatrix}
1&0&1\
0&1&1\
1&1&2
\end{bmatrix}
]
矩阵中每个元素表示一个 Query 与一个 Key 的点积。
例如:
[
S_{1,3}=1\times1+0\times1=1
]
表示第一个 Query 与第三个 Key 的点积为 1。
这一步相当于为每一对 Token 计算一个匹配分数。
如果输入序列有 (n) 个 Token,就会得到一个 (n\times n) 的分数矩阵。
第二步:为什么要除以 (\sqrt{d_k})?
这是公式中最容易被忽略、但非常重要的设计。
原始点积为:
[
q\cdot k=\sum_{i=1}^{d_k}q_i k_i
]
假设 (q) 和 (k) 的各个分量相互独立、均值为 0、方差为 1。
那么:
[
\operatorname{Var}(q\cdot k)=d_k
]
也就是说,随着向量维度增加,点积的方差也会增加。
当点积的绝对值很大时,Softmax 的输出容易变得极端。
例如:
[
\operatorname{softmax}([1,2,3])
\approx [0.09,0.24,0.67]
]
而:
[
\operatorname{softmax}([10,20,30])
\approx [0,0,1]
]
第二种情况下,Softmax 几乎将全部权重集中在一个位置上。
这种过度集中的分布可能导致梯度变小,不利于训练。
因此,论文引入缩放因子:
[
\boxed{\frac{1}{\sqrt{d_k}}}
]
将点积除以 (\sqrt{d_k}),以控制分数的尺度。
例如,原始模型中:
[
d_k=64
]
因此:
[
\sqrt{d_k}=8
]
Attention 分数会先除以 8,再进入 Softmax。
这里有个值得深入理解的细节:
缩放并不是为了让每个分数都变小,而是为了让分数的尺度在不同向量维度下更适合 Softmax 和梯度优化。
实际训练中的分布未必满足上述独立、单位方差的理想假设,因此这是一种设计动机,而不是对任意网络状态都严格成立的保证。
第三步:Softmax 将分数转换成权重
计算:
[
A=
\operatorname{softmax}
\left(
\frac{QK^\top}{\sqrt{d_k}}
\right)
]
Softmax 默认沿每个 Query 对应的 Key 维度计算。
也就是说,对矩阵的每一行分别归一化。
得到:
[
A_{ij}\geq 0
]
并且:
[
\sum_j A_{ij}=1
]
在没有 Mask 的情况下,每一行的权重和为 1。
因此,每个 Query 都会得到一组针对所有 Key 的注意力权重。
例如:
[
A_1=[0.2,0.3,0.5]
]
意味着第一个 Query 对应的三个位置,其权重分别为 0.2、0.3 和 0.5。
但需要注意:权重只能直接表示模型在这一步计算中分配的信息混合比例,不能简单等同于人类意义上的重要性或因果解释。
第四步:利用权重整合 Value
最终计算:
[
O=AV
]
假设:
[
A_1=[0.2,0.3,0.5]
]
对应三个 Value:
[
V_1=[1,0]
]
[
V_2=[0,1]
]
[
V_3=[1,1]
]
那么第一个输出向量就是:
[
O_1=0.2V_1+0.3V_2+0.5V_3
]
展开:
[
O_1
0.2[1,0]+0.3[0,1]+0.5[1,1]
]
因此:
[
\boxed{O_1=[0.7,0.8]}
]
这个结果就是三个 Value 按照注意力权重混合之后的向量。
在实际 Transformer 中,Value 是通过可学习的线性变换获得的,而不是人工定义的语义标签。
将整个过程串起来
1 | 输入向量 |
到这里,Attention 的数学核心就已经完整了:匹配、归一化、加权聚合。
接下来需要回答一个更关键的问题:为什么要有三个不同的向量 Q、K、V,而不是直接对输入向量做点积?
3.4 为什么 Q、K、V 需要分别学习?
假设输入矩阵为:
[
X\in\mathbb{R}^{n\times d_{\text{model}}}
]
Transformer 使用三个可学习的投影矩阵:
[
W_Q,\quad W_K,\quad W_V
]
分别得到:
[
Q=XW_Q
]
[
K=XW_K
]
[
V=XW_V
]
对于单头 Attention,可以将三个矩阵的形状理解为:
[
W_Q\in\mathbb{R}^{d_{\text{model}}\times d_k}
]
[
W_K\in\mathbb{R}^{d_{\text{model}}\times d_k}
]
[
W_V\in\mathbb{R}^{d_{\text{model}}\times d_v}
]
那么:
[
Q\in\mathbb{R}^{n\times d_k}
]
[
K\in\mathbb{R}^{n\times d_k}
]
[
V\in\mathbb{R}^{n\times d_v}
]
为什么要分别投影?
因为模型需要学习两类不同的能力:
- 匹配能力:哪些 Token 之间应该建立联系。
- 信息表达能力:建立联系之后,应该从其他 Token 中提取什么信息。
Q 和 K 决定注意力权重,而 V 决定加权聚合的内容。
如果只使用原始输入向量计算相似度,模型在如何匹配以及传递什么信息方面就会受到更多限制。
通过学习不同的投影矩阵,模型能够在训练过程中调整这两个方面。
需要注意,这并不意味着 Q 只负责一种语义、K 只负责另一种语义、V 只负责第三种语义。它们是功能上的区分,不是人为规定的语义分类。
四、Multi-Head Attention:为什么不能只用一个注意力头?
理解单头 Attention 后,第二个问题就出现了:
既然一个 Attention 已经可以计算任意两个 Token 之间的关联,为什么论文还要设计 Multi-Head Attention?
原论文第 4~5 页指出,多个注意力头可以让模型同时关注不同表示子空间中的信息,而单头 Attention 的信息聚合可能限制模型同时表达多种关系的能力。Attention Is All You Need(2)
4.1 单头 Attention 的局限
假设有一句话:
The cat chased the mouse because it was hungry.
模型需要同时处理不同类型的信息,例如:
it与前面名词之间的关系。- 动词与主语之间的关系。
- 动词与宾语之间的关系。
- 其他与语义理解有关的关系。
如果只有一个注意力头,所有这些信息都要通过同一组注意力权重进行聚合。
当然,单头 Attention 并非只能学习一种关系;它也可以学到复杂的关联。
但多个头能够提供更丰富的并行表示方式。
4.2 多头机制的核心思路
假设输入向量维度为 512。
Transformer Base 使用 8 个注意力头,每个头的 Key 和 Value 维度都是 64。
因此,每个头可以独立执行 Attention:
[
head_i=
\operatorname{Attention}
\left(
XW_i^Q,
XW_i^K,
XW_i^V
\right)
]
其中:
[
i=1,2,\ldots,8
]
每个头都有自己的参数矩阵。
最终,将所有头的输出拼接:
[
H=\operatorname{Concat}
(head_1,head_2,\ldots,head_8)
]
因为每个头的输出维度为 64,所以:
[
H\in\mathbb{R}^{n\times512}
]
然后进行一次输出投影:
[
\boxed{
\operatorname{MultiHead}(Q,K,V)
\operatorname{Concat}(head_1,\ldots,head_h)W^O
}
]
其中:
[
W^O\in\mathbb{R}^{512\times512}
]
在原始 Transformer Base 中,8 个头各有 64 维输出,拼接后仍为 512 维,因此能够与残差连接所需的模型维度保持一致。
4.3 多头 Attention 的计算过程
1 | 输入 X |
需要特别注意:这并不是把 512 维向量机械切成 8 份,然后每份独立处理。
实际计算中,每个头都有自己学习得到的 Q、K、V 投影矩阵,因此每个头可以学习不同的表示子空间。
4.4 多头机制的真正价值
可以从三个角度理解。
第一,多个头可以学习不同的注意力分布。
不同头可能对不同位置分配不同权重。
第二,多个头可以在不同表示子空间中处理信息。
不同头的 Q、K、V 投影参数各不相同,因此它们处理的特征不必相同。
第三,多个头的结果可以组合。
Concat 和输出投影允许模型综合不同头提取的信息。
不过,不能简单地认为每个 Head 都对应一个清晰、独立的人类语义任务。
论文附录中的可视化确实观察到,一些注意力头呈现出与句法结构、远距离依赖或指代消解有关的行为;但这不意味着所有注意力头都具备固定、可解释的分工。
4.5 为什么每个 Head 的维度要缩小?
论文选择:
[
h=8
]
[
d_k=d_v=\frac{d_{\text{model}}}{h}=64
]
如果每个头都使用完整的 512 维,那么 8 个头会带来更高的投影计算成本。
缩小每个头的维度,使得多个头的总体计算量与相近规模的单头 Attention 保持在相似量级。
这并不意味着所有现代架构都必须采用这种配置,但它体现了 Transformer 的一个重要设计思想:
通过多个低维表示子空间并行计算,而不是让单个注意力操作承担全部表示任务。
五、Self-Attention、Cross-Attention 与 Mask
理解 Q、K、V 之后,就可以进一步理解原始 Transformer 中三种关键的注意力计算。
5.1 Self-Attention:自己与自己序列中的所有位置交互
在 Encoder 中:
[
Q=XW_Q,\qquad K=XW_K,\qquad V=XW_V
]
三者都来自同一组输入表示 (X)。
这里的“Self”不是指 Token 只关注自己,而是指 Query、Key、Value 来源于同一个序列表示。
一个 Token 可以关注自身,也可以关注其他 Token。
例如:
1 | 输入: |
通过这样的计算,cat 对应的表示能够融入其他位置的信息。
Encoder 中的 Self-Attention 不需要阻止一个位置访问后面的输入 Token,因为输入句子整体已经可用。
5.2 Cross-Attention:让 Decoder 查询 Encoder
Cross-Attention 的计算不同。
设:
- (H) 是 Decoder 当前层的输入。
- (Z) 是 Encoder 的输出。
那么:
[
Q=HW_Q
]
[
K=ZW_K
]
[
V=ZW_V
]
可以看到:
- Query 来自 Decoder。
- Key 和 Value 来自 Encoder。
因此,Cross-Attention 可以理解为:
Decoder 根据当前的生成状态,向 Encoder 的输出表示中查询相关信息。
这和 Self-Attention 的区别不在于公式,而在于 Q、K、V 的来源。
它们都可以使用同样的 Scaled Dot-Product Attention 计算。
5.3 Masked Self-Attention:为什么需要掩码?
考虑目标序列:
1 | 我 喜欢 学习 AI |
在自回归生成时:
- 生成第一个 Token 时,不能查看未来 Token。
- 生成第二个 Token 时,可以利用第一个 Token。
- 生成第三个 Token 时,可以利用前两个 Token。
因此,Decoder 的 Self-Attention 必须限制未来信息的流入。
常用方法是构造一个因果 Mask。
对于长度为 4 的序列,可以用矩阵表示允许访问的位置:
[
M=
\begin{bmatrix}
1&0&0&0\
1&1&0&0\
1&1&1&0\
1&1&1&1
\end{bmatrix}
]
其中:
- 1 表示允许关注。
- 0 表示禁止关注。
实际计算中,不是直接把这个 0/1 矩阵乘到注意力分数上,而是把禁止访问的位置设置为负无穷,再执行 Softmax。
可以写成:
[
A=
\operatorname{softmax}
\left(
\frac{QK^\top}{\sqrt{d_k}}+B
\right)
]
其中:
[
B_{ij}=
\begin{cases}
0,&j\leq i\
-\infty,&j>i
\end{cases}
]
因此:
[
\operatorname{softmax}(-\infty)=0
]
未来位置的注意力权重就变为零。
这就是 Causal Attention 的数学基础。
一个容易混淆的细节
训练时,原始 Transformer 的 Decoder 可以将完整的目标序列一次性输入网络,并行计算各个位置的预测。
这是因为因果 Mask 阻止了每个位置读取未来的目标 Token。
因此:
- 训练时,可以并行计算不同目标位置的输出。
- 推理时,如果使用自回归生成,下一步 Token 仍然依赖前一步已经生成的结果。
这正是 Transformer 能够同时兼顾自回归生成与高效训练的关键设计之一。
论文第 5 页明确说明,Decoder 使用 Mask 阻止当前位置的信息流向之前的位置所不允许访问的未来位置,从而维持自回归生成性质。Attention Is All You Need(2)
六、位置编码:没有 RNN,模型如何知道词语顺序?
这是 Transformer 架构中另一个必须理解的问题。
前面提到,Self-Attention 能够让任意两个 Token 直接交互。
但是,如果模型只看 Token 的向量,不提供位置相关信息,那么它如何区分:
1 | 猫追老鼠 |
与:
1 | 老鼠追猫 |
两者包含相同的 Token,但顺序不同,含义也不同。
6.1 为什么 Self-Attention 本身不理解顺序?
假设有三个输入向量:
[
X=
\begin{bmatrix}
x_1\
x_2\
x_3
\end{bmatrix}
]
将它们的顺序打乱后:
[
X’=
\begin{bmatrix}
x_3\
x_1\
x_2
\end{bmatrix}
]
如果模型没有其他位置信息,那么 Self-Attention 的运算本身不会自动知道哪个 Token 原本位于句首、句中或句尾。
更严格地说,在不引入位置编码、位置相关 Mask 或其他顺序信号时,Self-Attention 对输入位置的置换具有等变性:输入位置被重新排列,输出也会以相同方式重新排列。
因此,Transformer 需要额外的位置机制。
6.2 原始论文采用什么方法?
论文使用正弦和余弦函数构造 Positional Encoding。
对于位置 (pos) 和维度索引 (i):
[
PE(pos,2i)
\sin
\left(
\frac{pos}{10000^{2i/d_{\text{model}}}}
\right)
]
[
PE(pos,2i+1)
\cos
\left(
\frac{pos}{10000^{2i/d_{\text{model}}}}
\right)
]
其中:
- (pos):Token 在序列中的位置。
- (i):向量维度的索引。
- (d_{\text{model}}):模型的隐藏维度。
这些公式来自论文第 6 页。Attention Is All You Need(2)
原始 Transformer Base 中:
[
d_{\text{model}}=512
]
因此,每个位置都会获得一个 512 维的位置向量。
这个向量不是随机噪声,而是根据位置通过确定性公式计算出来的。
6.3 为什么同时使用 Sin 和 Cos?
因为不同维度使用不同频率的正弦或余弦函数。
低频维度随位置变化较慢,高频维度随位置变化较快。
组合起来,不同位置就会获得不同的向量模式。
可以想象:
1 | 位置 0 → [0, 1, 0, 1, ...] |
这里的向量仅作示意,实际维度为 512。
论文选择这种方法的一个原因是:不同位置之间的关系能够通过正弦、余弦函数的性质表达,并且作者认为,这可能有助于模型学习相对位置关系。
论文还比较了固定位置编码与学习式位置 Embedding,实验中两者表现几乎相同。Attention Is All You Need(2)
6.4 位置编码如何进入模型?
原始 Transformer 不是将位置向量直接拼接到 Token Embedding 后面,而是将它们相加:
[
\boxed{
X=E+PE
}
]
其中:
- (E):Token Embedding。
- (PE):Positional Encoding。
二者维度相同,因此可以直接相加。
例如:
[
E\in\mathbb{R}^{n\times512}
]
[
PE\in\mathbb{R}^{n\times512}
]
于是:
[
X\in\mathbb{R}^{n\times512}
]
这样,模型在后续层中处理的向量既包含 Token 的表示,也融入了位置信息。
6.5 必须区分:位置编码不等于位置 Embedding
这两个术语经常被混用,但它们不完全相同。
| 机制 | 原始 Transformer 的正弦位置编码 | 学习式绝对位置 Embedding |
|---|---|---|
| 位置向量如何获得 | 根据固定公式计算 | 通过训练学习 |
| 是否包含可训练的位置参数 | 否 | 是 |
| 是否直接提供位置信息 | 是 | 是 |
| 超出训练位置范围时的行为 | 公式可以继续计算 | 原始位置表通常没有直接覆盖新位置的参数 |
需要强调:固定公式可以计算更远的位置,并不意味着模型就一定能可靠地处理任意长的上下文。
现代大语言模型还发展出了 RoPE、ALiBi 等其他位置处理方案;它们属于后续技术演进,而不是原论文使用的方法。
七、Feed-Forward Network:为什么 Attention 后面还要接一个网络?
到目前为止,我们已经理解了 Attention 的作用:
每个 Token 根据相关性,从其他 Token 中提取信息。
但 Attention 本身主要通过加权聚合 Value 来整合信息。
Transformer 还需要一个模块,进一步对每个位置的表示进行非线性变换。
这就是 Feed-Forward Network,简称 FFN。
7.1 原始 FFN 的数学表达式
论文第 5 页给出的公式是:
[
\boxed{
FFN(x)=
\max(0,xW_1+b_1)W_2+b_2
}
]
其中:
[
d_{\text{model}}=512
]
[
d_{ff}=2048
]
因此:
[
W_1\in\mathbb{R}^{512\times2048}
]
[
W_2\in\mathbb{R}^{2048\times512}
]
第一层将向量从 512 维扩展到 2048 维,经过 ReLU 激活后,再投影回 512 维。Attention Is All You Need(2)
7.2 FFN 与 Attention 的区别
可以把 Transformer 的每一层理解成两个阶段:
阶段一:信息交互
Attention 让不同 Token 之间交换信息。
1 | Token 1 ──┐ |
阶段二:位置内部的非线性变换
FFN 对每个位置分别进行处理。
1 | Token 1 的表示 ──→ FFN ──→ 新表示 |
原始论文明确指出,FFN 在每个位置分别、独立地应用,并且同一层中的不同位置共享相同的 FFN 参数。不同 Transformer 层之间则拥有不同的参数。Attention Is All You Need(2)
7.3 为什么需要先扩展维度?
以 512 → 2048 → 512 为例。
第一层执行:
[
h=\operatorname{ReLU}(xW_1+b_1)
]
得到:
[
h\in\mathbb{R}^{2048}
]
第二层执行:
[
y=hW_2+b_2
]
重新映射为:
[
y\in\mathbb{R}^{512}
]
通过这种扩展、非线性变换和压缩,网络可以学习比单一线性映射更丰富的特征变换。
从工程角度看,FFN 也是 Transformer 中重要的参数和计算来源。
现代大语言模型中的 FFN 往往进一步发展为 SwiGLU 等结构,维度配置也可能不同。
但其核心思想仍然可以追溯到原始 Transformer:
Attention 负责 Token 之间的信息交互,FFN 负责在每个位置上进一步变换表示。
八、残差连接与 Layer Normalization
原始 Transformer 每个子层都使用残差连接和 Layer Normalization。
论文采用的形式为:
[
\boxed{
LayerNorm(x+Sublayer(x))
}
]
也就是先将子层输入与子层输出相加,再进行 Layer Normalization。Attention Is All You Need(2)
8.1 为什么需要残差连接?
假设某一层的输入是:
[
x
]
经过 Attention 或 FFN 后,得到:
[
F(x)
]
如果直接使用:
[
y=F(x)
]
那么原始输入信息只能通过网络学习的变换继续传递。
残差连接则使用:
[
\boxed{y=x+F(x)}
]
它为输入信息提供了一条直接传递的路径。
这能够帮助深层网络优化,也让子层可以学习对输入表示的增量调整。
从直觉上说:
1 | 原始信息 x ──────────────────┐ |
模型不必每一层都从头重新构造完整表示,而是可以在已有表示的基础上进行修正。
8.2 Layer Normalization 的作用
Layer Normalization 对单个样本的特征维度进行归一化。
给定一个向量 (x),可以先计算均值:
[
\mu=\frac{1}{d}\sum_{i=1}^{d}x_i
]
再计算方差:
[
\sigma^2=
\frac{1}{d}
\sum_{i=1}^{d}(x_i-\mu)^2
]
然后:
[
\hat{x}_i=
\frac{x_i-\mu}{\sqrt{\sigma^2+\epsilon}}
]
最后使用可学习的缩放和偏移参数:
[
y_i=\gamma_i\hat{x}_i+\beta_i
]
其中 (\epsilon) 用于提高数值稳定性。
在原始 Transformer 的配置中,LayerNorm 位于残差相加之后。
需要区分两个概念:
- 残差连接提供信息和梯度的直接通路。
- LayerNorm 对特征进行归一化,以帮助稳定训练。
二者作用不同,因此不能简单地互相替代。
8.3 一个重要的现代架构差异
原始论文使用的是:
[
LayerNorm(x+F(x))
]
这通常称为 Post-LN。
许多现代大语言模型采用 Pre-LN 或其他归一化变体,例如先归一化,再进入子层:
[
y=x+F(LayerNorm(x))
]
这不是原始论文的公式,而是后续架构演进中的重要变化。
如果你准备自己实现 Transformer,需要特别注意这两种结构并不等价,不能只因为它们都包含残差连接和 LayerNorm,就认为可以随意互换。
九、把所有模块组合起来:一层 Transformer 究竟如何运行?
前面分别讲解了 Attention、FFN、位置编码、残差连接和 LayerNorm。现在把它们组合起来,观察数据在网络中的完整流动。
这是从理解理论走向阅读源码、实现模型的关键一步。
9.1 Encoder 单层的完整计算过程
假设输入矩阵:
[
X\in\mathbb{R}^{n\times512}
]
其中 (n) 是 Token 数量。
原始 Transformer Encoder 的一层可以写成:
第一步:Multi-Head Self-Attention
[
A=\operatorname{MHA}(X,X,X)
]
三个输入都来自同一个矩阵 (X)。
然后进行残差连接和 LayerNorm:
[
H=\operatorname{LayerNorm}(X+A)
]
如果考虑论文中的 Dropout,则更准确地写为:
[
H=\operatorname{LayerNorm}
\left(X+\operatorname{Dropout}(A)\right)
]
第二步:Feed-Forward Network
[
F=\operatorname{FFN}(H)
]
然后:
[
Y=\operatorname{LayerNorm}
\left(H+\operatorname{Dropout}(F)\right)
]
因此,Encoder 单层可以概括为:
[
\boxed{
H=\operatorname{LN}(X+\operatorname{Dropout}(\operatorname{MHA}(X,X,X)))
}
]
[
\boxed{
Y=\operatorname{LN}(H+\operatorname{Dropout}(\operatorname{FFN}(H)))
}
]
这里的 LN 是 LayerNorm。
注意,以上公式对应原始论文的 Post-LN 结构。实际训练时,Dropout 只在启用训练模式时生效。
9.2 Decoder 单层的完整计算过程
Decoder 比 Encoder 多一个 Cross-Attention 子层。
假设:
- (X):Decoder 当前层的输入。
- (Z):Encoder 的输出。
计算过程如下。
第一步:Masked Self-Attention。
[
H_1=
\operatorname{LN}
\left(
X+\operatorname{Dropout}
\left(
\operatorname{MHA}_{masked}(X,X,X)
\right)
\right)
]
第二步:Cross-Attention。
[
H_2=
\operatorname{LN}
\left(
H_1+\operatorname{Dropout}
\left(
\operatorname{MHA}(H_1,Z,Z)
\right)
\right)
]
第三步:FFN。
[
Y=
\operatorname{LN}
\left(
H_2+\operatorname{Dropout}
\left(
\operatorname{FFN}(H_2)
\right)
\right)
]
可以看到,Decoder 的三种子层各司其职:
| 子层 | 解决的问题 |
|---|---|
| Masked Self-Attention | 已生成的目标 Token 之间如何交互 |
| Cross-Attention | 当前生成状态需要从源序列中获取什么信息 |
| FFN | 如何进一步变换融合后的表示 |
9.3 为什么 Transformer 要堆叠多层?
原始论文将 Encoder 和 Decoder 各堆叠 6 层。
每一层都可以重新计算注意力权重,并进一步变换 Token 表示。
可以将其抽象为:
1 | 输入 Embedding |
这并不意味着每一层都对应某个固定的认知阶段。
更准确地说,随着层数增加,模型可以反复进行信息交互和非线性变换,从而学习更复杂的表示。
理解 Transformer 的关键,不是孤立记住每个模块,而是理解这些模块如何反复作用于同一组 Token 表示。
十、从计算复杂度理解 Transformer 为什么更高效
原论文不仅提出了新架构,还系统比较了 Self-Attention、RNN 和 CNN 的计算复杂度。
这部分是理解 Transformer 工程优势的重要内容。
论文第 6 页的表格从三个角度进行比较:
- 每层的计算复杂度。
- 最少需要执行多少个顺序计算步骤。
- 任意两个位置之间的最长信息传递路径。Attention Is All You Need(2)
10.1 Self-Attention 的复杂度
假设:
- 序列长度为 (n)。
- 表示维度为 (d)。
Attention 的主要计算是:
[
QK^\top
]
其中:
[
Q\in\mathbb{R}^{n\times d}
]
[
K^\top\in\mathbb{R}^{d\times n}
]
矩阵乘法的计算复杂度为:
[
O(n^2d)
]
接着计算:
[
AV
]
其复杂度也是:
[
O(n^2d)
]
因此,单层全局 Self-Attention 的主要复杂度为:
[
\boxed{O(n^2d)}
]
另外,Q、K、V 的投影还需要约 (O(nd^2)) 的计算。
所以,更完整地考虑投影后,单层 Multi-Head Attention 的计算复杂度通常可以概括为:
[
O(nd^2+n^2d)
]
这里忽略了常数因子。
10.2 为什么长上下文会成为问题?
因为 Attention 分数矩阵的大小为:
[
n\times n
]
当序列长度增加时,矩阵元素数量以平方级增长。
例如:
| 序列长度 (n) | Attention 分数矩阵元素数 |
|---|---|
| 128 | 16,384 |
| 512 | 262,144 |
| 1,024 | 1,048,576 |
| 2,048 | 4,194,304 |
| 4,096 | 16,777,216 |
| 8,192 | 67,108,864 |
序列长度从 1,024 增加到 8,192,是原来的 8 倍,但分数矩阵的元素数量增加到 64 倍。
这就是全局 Attention 的重要代价。
实际显存消耗还与 Batch Size、注意力头数、数据精度、反向传播和具体实现有关,不能仅凭矩阵元素数量直接得出整个模型的显存需求。
10.3 与 RNN 相比,Transformer 的优势是什么?
原论文给出的复杂度比较如下。
| 指标 | Self-Attention | Recurrent |
|---|---|---|
| 每层主要复杂度 | (O(n^2d)) | (O(nd^2)) |
| 最少顺序计算步骤 | (O(1)) | (O(n)) |
| 任意两位置的最大路径长度 | (O(1)) | (O(n)) |
这些复杂度描述的是特定计算模型下的理论特征,并不意味着 Self-Attention 在所有序列长度和硬件环境下都比 RNN 更快。
论文还指出,当序列长度 (n) 小于表示维度 (d) 时,Self-Attention 的主要计算在相应假设下可能比循环层更有利。Attention Is All You Need(2)
什么叫最大路径长度?
这是一个容易忽略、但非常有价值的概念。
假设句子开头的 Token 要影响句尾的 Token。
在 RNN 中,信息可能需要经过多个循环步骤:
1 | Token 1 → Token 2 → Token 3 → ... → Token n |
在 Self-Attention 中,两个位置可以在一层 Attention 内直接建立信息交互:
1 | Token 1 ─────────→ Token n |
因此,单层全局 Self-Attention 中,两个位置之间的最大路径长度是常数级。
这为模型学习长距离依赖提供了更直接的信息通路。
不过,路径更短不意味着模型必然能正确理解长距离关系。模型仍然需要通过训练学习适当的注意力分布和表示。
10.4 为什么现代模型仍然需要优化 Attention?
因为原始 Transformer 的全局 Attention 虽然提高了并行能力,但它的计算和内存成本仍然会随着序列长度快速增长。
后来出现的优化包括:
- FlashAttention:通过更高效的分块计算和内存访问方式,减少 Attention 的中间数据读写。
- Sliding Window Attention:限制每个 Token 能直接关注的局部范围。
- Sparse Attention:只计算部分位置之间的注意力。
- KV Cache:在自回归推理中缓存历史 Key 和 Value,避免重复计算。
- Grouped-Query Attention:在多个 Query 头之间共享 Key、Value 头,降低 KV Cache 的内存开销。
这些都是后续发展,不能与原论文的原始设计混为一谈。
尤其需要注意:FlashAttention 主要优化计算实现和内存访问,并没有把标准全局 Attention 的理论计算复杂度从平方级改成线性级。
十一、论文的训练方法与实验结果
理解架构之后,还需要回答一个问题:
Transformer 为什么被认为是有效的?
论文给出的证据不仅是提出了一套新的结构,还包括与已有模型的实验对比,以及对不同组件的消融实验。
11.1 训练数据
论文使用了 WMT 2014 机器翻译任务。
英文到德文:
- 约 450 万对句子。
- 使用 Byte-Pair Encoding。
- 共享词表约 37,000 个 Token。
英文到法文:
- 约 3,600 万个句子。
- 使用约 32,000 个 WordPiece Token 的词表。
训练批次按照近似序列长度组织,每批大约包含 25,000 个源语言 Token 和 25,000 个目标语言 Token。Attention Is All You Need(2)
这里有一个值得注意的工程思想:
按序列长度分组,可以减少 Batch 内 Padding 带来的无效计算。
例如:
1 | Batch A: |
相较于将极短句子与极长句子混在同一批次中,这种方式通常更容易控制 Padding 开销。
11.2 优化器与学习率调度
论文使用 Adam 优化器,参数为:
[
\beta_1=0.9
]
[
\beta_2=0.98
]
[
\epsilon=10^{-9}
]
同时采用了特定的学习率调度:
[
\boxed{
lrate=
d_{\text{model}}^{-0.5}
\cdot
\min
\left(
step^{-0.5},
step\cdot warmup^{-1.5}
\right)
}
]
其中:
[
warmup_steps=4000
]
公式来自论文第 7 页。Attention Is All You Need(2)
这个调度分为两个阶段。
阶段一:Warmup
在训练初期:
[
lrate\propto step
]
学习率逐渐增大。
阶段二:衰减
Warmup 结束后:
[
lrate\propto step^{-0.5}
]
学习率按照训练步数的平方根倒数逐渐衰减。
为什么要这么设计?
深层网络在训练初期的参数状态可能尚不稳定。先逐步增加学习率,再逐渐降低学习率,是一种兼顾训练稳定性与后期优化的策略。
需要注意,这个具体公式是原论文的训练方案,不是所有现代 Transformer 都必须使用的学习率调度。
11.3 训练时间
论文报告:
| 配置 | GPU | 训练步数 | 训练时间 |
|---|---|---|---|
| Transformer Base | 8 张 NVIDIA P100 | 100,000 | 约 12 小时 |
| Transformer Big | 8 张 NVIDIA P100 | 300,000 | 约 3.5 天 |
原论文在第 7 页给出了这些训练设置。Attention Is All You Need(2)
这些结果反映的是 2017 年特定硬件、数据集、模型配置和训练方案下的表现,不应该直接与今天的大模型训练成本进行比较。
11.4 机器翻译结果
论文在 WMT 2014 英德翻译任务中报告:
- Transformer Base:BLEU 27.3。
- Transformer Big:BLEU 28.4。
在英法翻译任务中:
- Transformer Big:BLEU 41.8。
论文认为,这些结果优于当时已有的相关模型,且具有显著的训练效率优势。Attention Is All You Need(2)
BLEU 是一种常用的机器翻译评价指标,通过比较机器译文与参考译文之间的 n-gram 匹配情况来评估翻译质量。
但 BLEU 并不是对翻译质量的完美衡量标准。
这组实验的重要意义,在于它证明了:完全基于 Attention 的序列转换架构,不仅在理论上具有并行化优势,而且能够在真实的机器翻译任务中取得有竞争力的效果。
11.5 消融实验告诉我们什么?
论文还改变了模型的一些配置,观察性能变化。
例如:
- 将注意力头数量从多个减少为单个,模型效果有所下降。
- 将 Key 的维度降低,模型效果也有所下降。
- 增大模型规模,通常可以提升性能。
- Dropout 对减少过拟合有帮助。
- 使用学习式位置 Embedding 替代正弦位置编码,效果接近。
这些结论来自论文第 9 页的模型变体实验。Attention Is All You Need(2)
这里需要掌握一个重要的科研阅读方法:
不要只看最终模型的分数,还要看论文通过什么实验,证明哪些设计可能是有效的。
消融实验可以帮助判断模型的哪些部分对结果有贡献,但其结论仍受实验配置、数据集和参数选择的限制。
十二、原始 Transformer 与现代 GPT 有什么区别?
这是理解这篇论文最重要的延伸问题之一。
很多人学习 Transformer 时,会把原始 Transformer、GPT、BERT 以及现代大语言模型都看成同一种架构。
实际上,它们存在重要差异。
12.1 三种典型架构
| 特征 | 原始 Transformer | BERT 类模型 | GPT 类模型 |
|---|---|---|---|
| 基本结构 | Encoder + Decoder | Encoder-only | Decoder-only |
| 主要注意力形式 | Encoder 双向 Self-Attention;Decoder 因果 Mask + Cross-Attention | 通常使用双向 Self-Attention | 通常使用因果 Self-Attention |
| 典型训练目标 | 条件序列生成,例如机器翻译 | 掩码语言建模等 | 自回归下一 Token 预测 |
| 典型用途 | 机器翻译、序列转换 | 文本理解、分类、抽取等 | 文本生成、对话、代码生成等 |
这里的“通常”很重要:不同模型可能使用不同的训练目标或结构变体。
12.2 GPT 为什么不需要原始 Transformer 的 Encoder?
原始 Transformer 的任务是:
[
\text{源语言}\rightarrow\text{目标语言}
]
因此,它需要:
- Encoder 处理源语言。
- Decoder 生成目标语言。
- Cross-Attention 将源语言信息传递给 Decoder。
GPT 类模型的核心任务则是根据已有上下文预测下一个 Token:
[
P(x_t\mid x_1,x_2,\ldots,x_{t-1})
]
例如:
1 | 输入: |
生成下一个 Token 后,再把它加入上下文:
1 | 人工智能的发展正在改变 |
然后继续预测。
这种任务本身不需要一个独立的源序列 Encoder,因此可以采用 Decoder-only 架构。
在典型 GPT 模型中,输入 Token 经过 Embedding 和位置处理后,进入多层 Transformer Block。每个 Block 通过因果 Self-Attention 和 FFN 等组件更新表示,最终预测下一个 Token 的概率分布。
这里要注意:现代 GPT Block 往往采用 Pre-LN、不同的位置机制、不同的 FFN 结构和高效 Attention 实现,并不等同于原论文的原始 Block。
12.3 为什么现代 LLM 通常采用 Decoder-only?
一个重要原因是,自回归语言建模可以统一成一个简单目标:
[
\boxed{
\mathcal{L}
-\sum_{t=1}^{T}
\log P(x_t\mid x_{<t})
}
]
其中:
- (x_t):当前位置的目标 Token。
- (x_{<t}):之前的 Token。
- (P(x_t\mid x_{<t})):模型预测当前位置 Token 的概率。
训练时,模型可以输入完整的文本序列,通过 Causal Mask 并行计算不同位置的预测。
例如:
1 | 输入序列: |
实际实现中,通常会将输入序列整体右移形成预测目标,并使用一次前向传播计算多个位置的损失。
这使得训练过程能够高效利用 GPU。
但推理时,如果采用逐 Token 自回归生成,仍然需要依赖前一步的生成结果。
12.4 原论文中哪些思想被现代 LLM 保留了?
很多现代大语言模型虽然已经不再使用原始 Encoder-Decoder 结构,但仍然保留了 Transformer 的核心思想:
- 通过 Attention 实现 Token 之间的信息交互。
- 使用多头机制进行并行表示学习。
- 通过残差连接支持深层网络训练。
- 使用 FFN 等模块进行非线性特征变换。
- 通过位置机制引入序列顺序信息。
- 利用大规模数据训练模型参数。
而以下内容在后续发展中出现了很多变化:
- Encoder-Decoder、Encoder-only、Decoder-only 的结构选择。
- Post-LN 与 Pre-LN 等归一化方式。
- 正弦位置编码与 RoPE 等位置机制。
- ReLU FFN 与 SwiGLU 等前馈结构。
- 标准 Multi-Head Attention 与 Grouped-Query Attention。
- 原始 Attention 的直接计算与 FlashAttention 等优化实现。
因此,学习原始论文时,需要区分两个层面:
第一层:理解原始 Transformer 的完整设计。
第二层:理解现代大语言模型为什么在此基础上做出了各种改进。
如果直接从现代 GPT 源码入手,很容易把大量不同年代、不同目的的设计混在一起,反而难以理解最初的原理。
十三、这篇论文有哪些局限?
经典论文并不意味着其方案在所有场景下都是最优的。
如果想真正理解 Transformer,就需要同时理解它的优势与代价。
13.1 全局 Attention 的二次复杂度
对于长度为 (n) 的序列,全局 Attention 的主要计算复杂度为:
[
O(n^2d)
]
当上下文长度非常大时,计算与内存成本会快速增长。
这是后续大量高效 Attention 研究的重要动机。
13.2 自回归生成仍然具有顺序依赖
虽然训练阶段可以并行处理多个位置,但 GPT 类模型在推理时通常仍然逐 Token 生成。
例如:
1 | 生成 Token 1 |
因此,Transformer 并没有彻底消除生成过程中的顺序依赖。
KV Cache 等技术能够减少重复计算,但不能消除下一 Token 对前面生成结果的依赖。
13.3 位置编码不能自动保证长上下文泛化
原论文选择正弦位置编码,一个原因是它可以在训练位置范围之外继续计算。
但这并不代表模型必然能够可靠地利用任意长度的上下文。
长上下文能力还受到训练数据、模型规模、位置机制、注意力实现和训练目标等多方面因素影响。
13.4 Attention 权重不等于完整的解释
原论文观察到,一些注意力头呈现出与句法关系、长距离依赖和指代消解有关的模式。
这为理解模型行为提供了有价值的线索。
但是,不能据此认为:
只要观察 Attention 权重,就可以完全解释模型为什么得出某个结论。
模型的最终输出还受到多层表示变换、残差连接、FFN 和输出投影等多种因素影响。
13.5 论文并没有解决今天所有的大模型问题
这篇论文提出的是一种序列建模架构,而不是一个完整的大语言模型训练与应用方案。
它并未直接解决今天大模型工程中的全部问题,例如:
- 超大规模分布式训练。
- 指令微调与偏好对齐。
- 检索增强生成。
- 工具调用与 Agent 编排。
- 长上下文高效推理。
- 多模态模型训练。
- 模型安全与可靠性。
这些方向需要在 Transformer 基础上继续学习其他论文与技术。
十四、如何真正掌握这篇论文:推荐的学习与实验路线
如果你的目标不只是看懂论文,而是希望能够深入研究大模型、实现 Transformer,并将其应用到 AI 工程中,我建议采用以下学习路线。
重点不是背诵公式,而是能够从输入开始,独立解释每个模块的作用,推导关键张量的形状,并通过实验验证理解。
阶段一:数学基础与张量运算
目标:真正理解 Attention 公式,而不是只会抄写。
需要掌握:
- 向量、矩阵与矩阵乘法。
- 转置、广播与张量维度。
- 点积与向量相似性。
- Softmax 的计算方式。
- 导数、梯度与链式法则的基本概念。
- 神经网络中的线性层与反向传播。
建议动手完成:
- 使用 NumPy 实现 Softmax。
- 手动计算 (QK^\top)。
- 手动计算缩放后的 Attention 分数。
- 实现 (AV) 的加权聚合。
- 对比不同 (d_k) 下缩放前后的分数分布。
验收标准:
给定任意小型 Q、K、V 矩阵,能够手算并通过代码验证 Attention 的完整输出。
阶段二:从零实现 Scaled Dot-Product Attention
使用 PyTorch 实现:
1 | import math |
这个实现展示了最基本的计算过程。
其中:
q @ k.transpose(-2, -1)计算匹配分数。- 除以 (\sqrt{d_k}) 进行缩放。
- Mask 将禁止访问的位置设置为负无穷。
- Softmax 得到注意力权重。
- 与 V 相乘,得到加权聚合结果。
注意:这个示例假设每一行至少存在一个允许访问的位置。实际工程中还需要正确处理 Padding Mask、全屏蔽行以及不同形状的 Mask。
验收标准:
- 能解释每一步的数学意义。
- 能解释
transpose(-2, -1)为什么必要。 - 能解释为什么 Softmax 通常沿最后一个维度计算。
- 能验证因果 Mask 下,未来位置的权重为零。
阶段三:实现 Multi-Head Attention
在阶段二的基础上,增加:
- Q、K、V 的可学习线性投影。
- Head 维度拆分。
- 每个 Head 的独立 Attention。
- 多头结果的拼接。
- 输出线性投影。
例如:
1 | 输入: |
其中:
- (B):Batch Size。
- (T):序列长度。
- 512:模型维度。
- 8:注意力头数。
- 64:每个 Head 的维度。
验收标准:
能够独立实现 Multi-Head Attention,并解释每一次 reshape、transpose 和 contiguous 的作用。
阶段四:实现完整 Encoder Block
逐步加入:
- Multi-Head Self-Attention。
- 残差连接。
- LayerNorm。
- Feed-Forward Network。
- Dropout。
重点观察:
1 | 输入形状: |
验收标准:
不依赖现成 Transformer Block,能够自己实现一个与原论文结构一致的 Encoder Layer。
阶段五:实现 Decoder 与因果 Mask
继续实现:
- Masked Self-Attention。
- Cross-Attention。
- FFN。
- 残差连接与 LayerNorm。
- 输出投影和 Softmax。
重点验证两个性质:
性质一:因果性
改变未来位置的输入,不应该影响前面位置的预测结果。
性质二:Cross-Attention 的数据来源
Query 来自 Decoder,Key 和 Value 来自 Encoder。
验收标准:
给定源序列和目标序列,能够解释 Decoder 中三种子层的计算路径,并验证因果 Mask 正确。
阶段六:训练一个小型 Transformer
不建议一开始就尝试复现原论文的完整训练规模。
可以先选择一个小型机器翻译数据集,或者构造简单的序列转换任务。
建议按以下顺序推进:
- 训练一个小型 Encoder-Decoder Transformer。
- 观察训练损失和验证损失。
- 对比有无位置编码的差异。
- 对比单头与多头 Attention。
- 对比不同模型深度。
- 检查因果 Mask 是否正确。
- 尝试在小型语料上训练一个 Decoder-only 模型。
验收标准:
模型能够完成一个可验证的序列任务,并且你能够解释训练目标、Attention Mask、输出概率分布和推理过程。
十五、进一步阅读:从 Transformer 基础走向现代大模型
掌握原始 Transformer 后,可以沿着以下路线继续学习。
| 学习方向 | 需要解决的问题 | 推荐学习内容 |
|---|---|---|
| 自回归语言模型 | 如何通过预测下一个 Token 学习语言 | GPT 系列的早期论文 |
| 预训练语言模型 | 如何通过大规模预训练学习通用表示 | BERT |
| 计算与内存优化 | 如何更高效地执行 Attention | FlashAttention |
| 位置编码演进 | 如何表示相对位置与扩展上下文 | RoPE 相关论文 |
| 参数效率 | 如何减少推理时的 KV Cache 开销 | Multi-Query Attention、Grouped-Query Attention |
| 模型训练 | 如何训练更大规模的神经网络 | Scaling Laws、分布式训练 |
| 大模型应用 | 如何让模型使用外部知识和工具 | RAG、Function Calling、AI Agent |
其中,建议优先学习 GPT、BERT 和 FlashAttention。
原因是这三个方向分别对应:
- 模型架构如何适配不同任务。
- 预训练目标如何影响模型行为。
- Transformer 如何在现代硬件上高效运行。
学习它们时,应当始终回到原始 Transformer 的三个核心问题:
- 信息如何在 Token 之间传递?
- 模型如何表示序列位置?
- 网络如何通过多层变换学习复杂表示?
只要能够持续用这三个问题分析后续技术,就不容易陷入只记住各种架构名称、却不理解设计动机的状态。
十六、最终总结:这篇论文最值得掌握的 8 个知识点
如果需要将整篇论文压缩为一份知识清单,我建议重点掌握以下内容。
| 序号 | 核心知识点 | 必须达到的理解程度 |
|---|---|---|
| 1 | Transformer 的研究动机 | 理解 RNN 顺序计算的限制,以及 Attention 的并行化优势 |
| 2 | Scaled Dot-Product Attention | 能够推导公式,并解释缩放因子的作用 |
| 3 | Q、K、V | 理解匹配、权重与信息聚合的关系 |
| 4 | Multi-Head Attention | 能够解释多头机制,并独立实现张量维度变换 |
| 5 | Positional Encoding | 理解 Self-Attention 为什么需要额外的顺序信息 |
| 6 | Masked Self-Attention | 理解因果 Mask,以及训练和推理的区别 |
| 7 | FFN、残差连接、LayerNorm | 理解单层 Transformer 的完整计算过程 |
| 8 | Encoder-Decoder 与 Decoder-only | 理解原始 Transformer 和现代 GPT 类模型的结构差异 |
其中,最值得反复推导的是:
[
\boxed{
\operatorname{Attention}(Q,K,V)
\operatorname{softmax}
\left(
\frac{QK^\top}{\sqrt{d_k}}
\right)V
}
]
以及:
[
\boxed{
\operatorname{MultiHead}(Q,K,V)
\operatorname{Concat}(head_1,\ldots,head_h)W^O
}
]
第一条公式解释了 Token 如何根据上下文动态聚合信息。
第二条公式解释了模型如何通过多个注意力头,在不同表示子空间中并行处理信息。
再结合位置编码、FFN、残差连接和 LayerNorm,就可以建立起原始 Transformer 的完整计算图。
我最建议的下一步,不是继续阅读更多论文,而是亲手实现一个最小 Transformer。 从矩阵乘法开始,逐步实现 Attention、Multi-Head Attention、Encoder、Decoder,再对照原论文检查每个张量的形状和计算结果。
当你能够独立实现这些模块,并解释每个设计的动机和代价时,你才真正掌握了这篇论文的核心,而不仅仅是记住了 Transformer 的术语。