Transformer 架构深度解析:从整体结构到训练推理
Transformer 由输入表示、自注意力、前馈网络、残差连接、层归一化和输出生成等模块组成。本文按照数据流对这些模块进行说明,并解释各模块的作用。
参考:Vaswani 等,2017,《Attention Is All You Need》。
目录
- 第一章 Transformer 的总体架构
- 1.1 为什么需要 Transformer
- 1.2 编码器—解码器的整体结构
- 1.3 数据如何流过整个模型
- 第二章 核心组件详解
- 2.1 输入表示:词嵌入与位置编码
- 2.2 自注意力机制:Q、K、V 是什么
- 2.3 多头注意力机制
- 2.4 前馈神经网络
- 2.5 残差连接与层归一化
- 2.6 掩码注意力机制
- 2.7 推理过程
- 2.8 训练过程
- 第三章 总结
- 参考文献
第一章 Transformer 的总体架构
1.1 为什么需要 Transformer
在 Transformer 出现之前,机器翻译等序列任务主要依赖 RNN、LSTM 这类循环神经网络。它们有一个共同特点:信息要一步接一步地向后传递,即处理第
t
t
t 个词时必须先算完第
t
−
1
t-1
t−1 个词。这种顺序计算带来两个问题:
Transformer 用自注意力机制解决了这两个问题:它让序列中任意两个位置的词直接建立联系,不需要一步步传递;同时整段序列可以同时送入模型并行计算。
需要提醒的是,自注意力要计算序列中所有词两两之间的关系,计算量和显存开销随序列长度的平方增长。所以 Transformer 不是"在所有场景下都更快",它的优势在于并行训练和长距离依赖建模。
1.2 编码器—解码器的整体结构
原始 Transformer 采用 Encoder–Decoder(编码器—解码器)结构,整体可以理解成两个分工明确的部分:
- 编码器(Encoder):负责理解输入序列,把源语言转换成语义丰富的上下文表示;
- 解码器(Decoder):负责根据编码器提供的上下文,逐步生成目标序列。
编码器和解码器都由若干层堆叠而成,原论文中都是 6 层。
图 1 Transformer 原始 Encoder–Decoder 总体架构

图中左侧为编码器,右侧为解码器。编码器输出作为解码器交叉注意力的输入,解码器最终通过 Linear 和 Softmax 输出 token 概率。
原始 Transformer 的关键配置
| 编码器层数 | 6 |
| 解码器层数 | 6 |
| 模型维度
d m o d e l d_{model} dmodel |
512 |
| 注意力头数
h h h |
8 |
| 每个头的维度 | 64 |
| 前馈层隐藏维度 | 2048 |
各子层在模块边界处保持
d
m
o
d
e
l
=
512
d_{model}=512
dmodel=512,因此残差连接可以直接进行相加。
编码器的每一层包含两个子模块,外加两组残差连接与层归一化(Add & Norm):
- 多头自注意力层(Multi-Head Self-Attention);
- 位置前馈神经网络(Position-wise Feed-Forward Network)。
解码器的每一层包含三个子模块,外加三组 Add & Norm:
- 带掩码的多头自注意力层:处理目标序列内部的关系,且不允许看到未来的词;
- 交叉注意力层(Cross-Attention):Q 来自解码器,K、V 来自编码器的输出,让解码器"读取"源语言的信息;
- 位置前馈神经网络。
1.3 数据如何流过整个模型
一句话概括整个数据流:
源序列经过编码器变成上下文表示(Context / Memory),解码器结合这个表示和目标前缀,一步步预测出下一个 token。
详细过程如下:
第二章 核心组件详解
2.1 输入表示:词嵌入与位置编码
2.1.1 词嵌入(Input Embedding)
神经网络不能直接处理文字。常规做法是先建一个词表,把每个 token 映射成整数 ID,再查表得到对应的稠密向量,这个过程就是词嵌入(Embedding)。
为什么不用 one-hot 编码? 原文给出了两个关键原因:

词嵌入矩阵可以表示为:
E
∈
R
∣
V
∣
×
d
m
o
d
e
l
E \\in \\mathbb{R}^{|V| \\times d_{model}}
E∈R∣V∣×dmodel
其中
∣
V
∣
|V|
∣V∣ 是词表大小,
d
m
o
d
e
l
d_{model}
dmodel 是模型的隐藏维度。原论文中
d
m
o
d
e
l
=
512
d_{model}=512
dmodel=512。也就是说,词嵌入本质上是一张
∣
V
∣
×
512
|V| \\times 512
∣V∣×512 的大表,每个词对应一行。输入某个词的 ID 时,取对应的一行向量即可,所以从实现角度看,Input Embedding 就是一个查表操作。
这个词嵌入矩阵是训练出来的,因此最终得到的稠密向量在维度上是有相关性的,相似的词可以学习到相似的表示。另外,原论文在嵌入后还要乘以
d
m
o
d
e
l
\\sqrt{d_{model}}
dmodel
:
X
e
m
b
=
d
m
o
d
e
l
E
[
x
]
X_{emb} = \\sqrt{d_{model}}\\,E[x]
Xemb=dmodel
E[x]
这样做的目的是让嵌入向量的数值尺度与位置编码在同一量级,避免相加时位置编码被"淹没"。
2.1.2 位置编码(Positional Encoding)
自注意力有个"缺点":它本身完全不关心词的顺序。把"我爱你"和"你爱我"分别作为一个集合输入注意力层,模型看到的信息是相同的。因此必须额外告诉模型每个词在序列中的位置。
Transformer 采用固定编码(Fixed Positional Encoding),用正弦和余弦函数生成位置向量:
P
E
(
p
o
s
,
2
i
)
=
sin
(
p
o
s
10000
2
i
/
d
m
o
d
e
l
)
PE_{(pos, 2i)} = \\sin\\left(\\frac{pos}{10000^{2i / d_{model}}}\\right)
PE(pos,2i)=sin(100002i/dmodelpos)
P
E
(
p
o
s
,
2
i
+
1
)
=
cos
(
p
o
s
10000
2
i
/
d
m
o
d
e
l
)
PE_{(pos, 2i+1)} = \\cos\\left(\\frac{pos}{10000^{2i / d_{model}}}\\right)
PE(pos,2i+1)=cos(100002i/dmodelpos)
参数含义如下:
-
p
o
s
pos
pos:词在序列中的位置,即"第几个词"; -
i
i
i:向量中的维度下标; -
d
m
o
d
e
l
d_{model}
dmodel:模型维度,论文默认取 512; - 偶数维用正弦公式,奇数维用余弦公式。
这个编码有几个好性质:
- 数值被控制在
[
−
1
,
1
]
[-1, 1]
[−1,1] 之间,不会出现数值爆炸; -
i
i
i 较小时分母小、波长短(变化快),负责捕捉近距离的位置差异; -
i
i
i 较大时分母大、波长长(变化平缓),负责捕捉远距离的位置差异。

直观理解:低维度上相邻位置的值差别很大,容易区分相邻的词;高维度上数值变化平缓,但提供了"广度",相当于给每个词一个绝对坐标。这样一来,低维负责"精确区分邻居",高维负责"整体定位",两者配合就构成了位置信息。
最终每个词的输入表示就是词嵌入与位置编码相加:
X
=
X
e
m
b
+
P
X = X_{emb} + P
X=Xemb+P
2.2 自注意力机制:Q、K、V 是什么
2.2.1 自注意力要解决什么问题
自注意力的思路是:对于当前这个词,应该从整句话中"有重点地"收集其他词的信息。某个词与当前词关系越大,它在当前词的表示中占的权重就越高。
2.2.2 Q、K、V 的含义
Q、K、V 是自注意力机制的核心。它们不是人工指定含义的向量,而是通过训练得到的三个矩阵,对输入
X
X
X 做线性变换得到的:
Q
=
X
W
Q
,
K
=
X
W
K
,
V
=
X
W
V
Q = XW^Q, \\qquad K = XW^K, \\qquad V = XW^V
Q=XWQ,K=XWK,V=XWV
三个矩阵各司其职,可以类比成一次"信息检索":
- Q(Query,查询):负责"我要找什么"。每个查询向量代表当前位置希望从别处获取的信息类型;
- K(Key,键):负责"我有什么"。每个键向量代表序列中某个位置提供的信息特征,用来和查询做匹配;
- V(Value,值):负责"真正给什么"。匹配成功后,真正被加权聚合进结果的就是值向量。
整个过程就像是"拿着查询去匹配一堆键,匹配度高的键,其对应的值就更多地进入结果"。
图中展示输入
X
X
X 经过三组投影得到
Q
Q
Q、
K
K
K、
V
V
V,再通过
Q
K
T
QK^T
QKT 计算相关性,使用 Softmax 得到权重,最后对
V
V
V 加权求和。
2.2.3 为什么要对 X 做线性变换
有人可能会问:直接用原始向量做点积判断相关性不行吗?原文用一个例子解释了这个问题:
假如输入只有"我"和"爱"两个字,用 one-hot 表示成
[
0
,
1
]
[0,1]
[0,1] 和
[
1
,
0
]
[1,0]
[1,0],两者点积直接为 0,相当于模型认为它们毫无关系。但实际上"我"和"爱"联系非常紧密。
如果直接拿原始向量算相似度,很多本应相关的词之间会因为编码方式而"失联"。所以需要通过
W
Q
、
W
K
、
W
V
W^Q、W^K、W^V
WQ、WK、WV 把输入
X
X
X 变换到新的空间,让"我"和"爱"在这种变换后具备可比较的关系,再通过点积衡量相关性——点积越大,相关性越高。
2.2.4 带掩码的自注意力的计算过程
带掩码自注意力使用的公式是:
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
=
s
o
f
t
m
a
x
(
Q
K
T
d
k
+
M
)
V
Attention(Q, K, V) = softmax\\left(\\frac{QK^T}{\\sqrt{d_k}} + M\\right)V
Attention(Q,K,V)=softmax(dk
QKT+M)V
S
c
o
r
e
s
=
Q
K
T
d
k
Scores = \\frac{QK^T}{\\sqrt{d_k}}
Scores=dk
QKT
其中
M
M
M 是可选的掩码矩阵。可以把整个计算过程看成“先算相关性,再按相关性取信息”。完整计算分五步:
Q
K
T
QK^T
QKT,得到每个查询与所有键之间的匹配分数矩阵;
d
k
\\sqrt{d_k}
dk,对分数做缩放;
M
M
M,屏蔽不允许关注的位置(后面会讲);
V
V
V 加权求和,得到当前位置新的表示。
为什么要除以
d
k
\\sqrt{d_k}
dk
? 假设各维度近似独立且方差相近,查询向量与键向量的点积会随着维度
d
k
d_k
dk 增大而产生更大的波动,方差量级约为
d
k
d_k
dk。如果直接把这些分数送入 Softmax,概率容易过度集中,函数进入饱和区,梯度变小,训练也会变得不稳定。因此,除以
d
k
\\sqrt{d_k}
dk
的本质是控制点积的尺度,而不是简单地把向量限制到
[
−
1
,
1
]
[-1,1]
[−1,1]。
为什么要做 Softmax? 归一化后分数变成概率分布,每个位置的权重之和为 1,这样才能正确地按"重要性"加权聚合
V
V
V。 
2.3 多头注意力机制
在前面的基础上,多头注意力就容易理解了。前面讲的都是"单头"注意力:整个 512 维向量在同一套 Q、K、V 下计算一种关系。但一句句子里同时存在多种关系,比如邻近关系、主谓关系、指代关系等,单头很难面面俱到。
多头注意力的做法是:把
d
m
o
d
e
l
=
512
d_{model}=512
dmodel=512 维拆成 8 个头,每个头负责 64 维,各自独立计算注意力:
h
e
a
d
i
=
A
t
t
e
n
t
i
o
n
(
Q
W
i
Q
,
K
W
i
K
,
V
W
i
V
)
head_i = Attention(QW_i^Q, KW_i^K, VW_i^V)
headi=Attention(QWiQ,KWiK,VWiV)
每个头都拥有自己独立的
W
i
Q
、
W
i
K
、
W
i
V
W_i^Q、W_i^K、W_i^V
WiQ、WiK、WiV,因此可以在不同的子空间里学习不同种类的依赖关系。
计算完之后,把 8 个头的输出拼接起来,再乘一个输出矩阵
W
O
W^O
WO:
M
u
l
t
i
H
e
a
d
(
Q
,
K
,
V
)
=
C
o
n
c
a
t
(
h
e
a
d
1
,
.
.
.
,
h
e
a
d
h
)
W
O
MultiHead(Q, K, V) = Concat(head_1, …, head_h)\\,W^O
MultiHead(Q,K,V)=Concat(head1,…,headh)WO
不同注意力头在不同子空间中提取关系,随后通过 Concat 和输出投影重新融合。
为什么要乘
W
O
W^O
WO? 这其实是在问:拼接后的向量为什么还要再做一次线性变换?原因是:拼接只解决了"把多条线索放在一起",但没有决定"每条线索该占多大分量"。目前各头的信息顺序是"定死"的,乘上
W
O
W^O
WO 后,模型可以自己学习谁更重要、如何组合这些视角。用原文的一句总结就是:
多头注意力的本质是"学习如何把多条线索重新组合成最有用的信息"。 
2.4 前馈神经网络
每个编码器层和解码器层里,注意力之后都会接一个前馈神经网络(Feed-Forward Network)。它由三部分构成:输入层、隐藏层、输出层。
F
F
N
(
x
)
=
m
a
x
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x) = max(0, xW_1 + b_1)\\,W_2 + b_2
FFN(x)=max(0,xW1+b1)W2+b2
原论文使用 ReLU 作为激活函数,输入输出维度为 512,中间隐藏层维度为 2048。

输入和输出保持模型维度不变,中间层先扩展表示空间,再通过非线性激活完成特征加工。
前馈网络也可以分两步理解:
隐藏层维度更大,配合 ReLU 的非线性,让网络具备逼近任意函数的能力。一句话概括前馈网络的作用:
把自注意力收集来的上下文信息,深度加工成更高层次的语义特征。
注意力与前馈网络的分工可以这样记:注意力负责"从其他位置收集信息",前馈网络负责"在当前位置加工信息"。
2.5 残差连接与层归一化
2.5.1 层归一化(Layer Normalization)
层归一化在特征维度上,对每个样本分别做归一化,公式如下:
x
^
=
x
−
μ
σ
2
+
ϵ
,
y
=
γ
x
^
+
β
\\hat{x} = \\frac{x – \\mu}{\\sqrt{\\sigma^2 + \\epsilon}}, \\qquad y = \\gamma\\hat{x} + \\beta
x^=σ2+ϵ
x−μ,y=γx^+β
其中
μ
\\mu
μ、
σ
2
\\sigma^2
σ2 是该样本在该层向量的均值与方差,
γ
\\gamma
γ、
β
\\beta
β 是可学习的缩放和偏移参数。
为什么要做层归一化? 训练过程中,各层表示的数值尺度会不断变化。LayerNorm 通过对每个 token 的特征维度进行标准化,让后续子层接收到更稳定的输入,从而降低优化难度。早期文献常用 Internal Covariate Shift(内部协变量偏移)解释归一化的动机,但现代研究认为,归一化带来的平滑优化、梯度稳定等作用同样重要,不能只用“内部协变量偏移”一个观点概括。 原因一:
原因二: 
为什么要对"自注意力的输出"归一化? 自注意力内部做了 Softmax 和加权求和,其输出分布依然随输入变化而变化。归一化它,可以让后续前馈网络接到的输入分布更稳定,防止某一层的数值异常传导到整条链路。 
为什么引入
γ
\\gamma
γ 和
β
\\beta
β? 归一化会改变原始向量的尺度和偏移。为了避免这种变换限制模型的表达能力,LayerNorm 增加了可学习的缩放与平移参数:
γ
\\gamma
γ 可以放大或缩小不同维度,
β
\\beta
β 可以整体调整表示的位置。更准确地说,它们不是简单地“恢复全部绝对信息”,而是让模型在稳定数值范围的同时,仍能学习合适的表示尺度。
2.5.2 残差连接(Residual Connection)
每个子层的输出都采用"原始输入 + 子层输出"的形式:
y
=
x
+
S
u
b
l
a
y
e
r
(
x
)
y = x + Sublayer(x)
y=x+Sublayer(x)
可以理解为:
Add = 全局依赖信息(子层学习到的结果)+ 原始词义信息(输入本身)
为什么要加残差连接? 核心目的是解决梯度消失问题。反向传播时,梯度要从最后一层一层地传回第一层,每经过一层,梯度就要乘以这一层的权重。如果权重小于 1,多层相乘后梯度会指数级衰减,传到前面几层时几乎变成 0,前面的参数就再也学不到东西了。
残差连接让原始信息和梯度都能绕过中间复杂的非线性变换,获得更直接的传播路径,相当于给梯度开了一条"高速公路"。它显著降低了深层网络的优化难度,但并不意味着只要加入残差就一定不会出现梯度消失;实际训练效果还与归一化位置、初始化和学习率等因素有关。 
输入一条路径经过子层变换,另一条路径直接跳过子层,二者在末端相加,为信息和梯度提供更短的传播路径。
2.6 掩码注意力机制
掩码(Mask)的本质是:在计算注意力分数时,把不允许被关注的位置的分数设为一个极小的值(数学上相当于
−
∞
-\\infty
−∞),这样经过 Softmax 之后这些位置的权重趋近于 0,模型就不会把注意力分给它们。
Transformer 里有两种掩码,作用完全不同:
填充掩码(Padding Mask):模型训练时要一次处理一个批次的多条序列,而句子长短不一。为了让它们能组成规则的矩阵并行计算,较短的句子会用特殊填充符(如 [PAD])补齐到相同长度。填充掩码的作用就是把 [PAD] 位置的注意力分数也设为
−
∞
-\\infty
−∞,防止模型把注意力分配到这些没有任何语义的填充符上。
因果掩码(Causal Mask):用在解码器的自注意力中。解码器在预测第
t
t
t 个词时,只能看到第
t
t
t 个词以及它之前的词,不能提前"偷看"后面的答案。因果掩码就是把当前位置之后的分数全部屏蔽,保证"用已知的信息预测未知的信息"。
图 6 填充掩码与因果掩码的作用

填充掩码屏蔽无意义的 [PAD] 位置,因果掩码屏蔽当前位置之后的未来 token。被屏蔽位置经过 Softmax 后的权重接近 0。
一句话解释掩码的意义:过滤掉无效信息(填充符)和未来信息(未生成的词)。至于为什么要填充:是为了让长度不一的序列在 GPU 上能够组成张量并行计算。
2.7 推理过程
先明确一点:Transformer 论文中编码器是 6 层,一个 token 要依次经过 6 次编码器的处理,解码过程同理。推理阶段和训练阶段最大的区别在于:推理时没有真实答案可看。
推理的整体流程是:
在工程实现中,解码器通常还会缓存历史 token 的 Key 和 Value,避免每一步都重复计算整个前缀,这就是推理阶段常说的 KV Cache。
图 7 Transformer 推理阶段的自回归生成过程

编码器只需运行一次;解码器根据当前已生成的前缀,循环预测下一个 token,直到生成结束符。
一句话总结推理过程:
把"训练时解码器的输入(真实标签)“换成"自己上一秒生成的词”,一个一个往外蹦,直到吐出结束符。
2.8 训练过程
训练阶段采用教师强制(Teacher Forcing):不依赖模型自己生成的词,而是直接把真实的目标序列右移一位后送入解码器,让模型并行预测每一个位置的下一个 token。
核心流程就是标准的深度学习训练循环:
Transformer 训练 = 前向传播(编码器 → 解码器 → 输出概率)→ 计算 Loss(对比预测与真实标签)→ 反向传播(梯度从输出层传回每一层)→ 更新参数(所有
W
W
W 矩阵和偏置),循环往复直到 Loss 收敛。
训练与推理的关键差异:
| 解码器输入 | 真实目标序列(右移一位) | 自己生成的前缀 |
| 是否并行 | 可整段并行 | 必须逐词自回归 |
| 掩码 | 因果掩码防止偷看答案 | 同样的因果掩码 |
| 效率 | 高(一次前向算出整句概率) | 低(每生成一个词算一次) |

训练不断经历“预测—计算损失—反向传播—更新参数”的循环。
第三章 总结
如果把 Transformer 看成一条信息加工流水线,它的每个模块都在回答一个明确的问题。
Transformer 整体可以沿着"输入 → 加工 → 输出"这条主线来理解:
几个值得反复体会的"一句话":
- 多头注意力的本质是"学习如何把多条线索重新组合成最有用的信息";
- 注意力负责收集信息,前馈网络负责加工信息;
- Add = 全局依赖信息 + 原始词义信息,残差是梯度的"高速公路";
- 推理过程 = 把训练时的真实标签换成自己上一步生成的词,一个一个往外蹦。
掌握这些核心组件的职责与数据流,再看 BERT、GPT 等后续模型时,就会发现它们都是在 Transformer 这个骨架上做的延伸和改造。







