手撕Transformer:一个完整的机器翻译实例详解

引言:当注意力成为唯一需要的东西

2017年,Google Brain团队发表了题为《Attention Is All You Need》的论文,提出了Transformer架构。这篇论文彻底改变了自然语言处理领域,成为后续BERT、GPT等大模型的基石。

与传统的RNN和LSTM不同,Transformer完全抛弃了循环结构,仅依赖注意力机制来捕捉序列中的依赖关系。这使得模型可以并行处理整个序列,大大提高了训练效率。

本文将通过一个具体的机器翻译实例------将英文句子"I love you"翻译为中文"我爱你"------来详细讲解Transformer的完整前向传播过程,并突出每一步的张量维度变化。

实例设定

项目 内容
输入序列(源语言) ["I", "love", "you"],长度 n=3n = 3n=3
输出序列(目标语言) ["我", "爱", "你"],长度 m=3m = 3m=3
模型维度 dmodel=512d_{\text{model}} = 512dmodel=512
注意力头数 h=8h = 8h=8
每个头的维度 dk=dv=dmodel/h=64d_k = d_v = d_{\text{model}} / h = 64dk=dv=dmodel/h=64
前馈网络内层维度 dff=2048d_{ff} = 2048dff=2048
词汇表大小 V=37000V = 37000V=37000(参考论文WMT英德任务)

第一阶段:输入表示(编码器端)

1. 词嵌入(Word Embedding)

每个输入词元通过一个可学习的嵌入矩阵 E∈RV×dmodelE \in \mathbb{R}^{V \times d_{\text{model}}}E∈RV×dmodel 转换为稠密向量。

Xembed=Lookup(E,["I","love","you"]) X_{\text{embed}} = \text{Lookup}(E, [\text{"I"}, \text{"love"}, \text{"you"}]) Xembed=Lookup(E,["I","love","you"])

维度变化

  • 输入:3个词元ID
  • 输出:Xembed∈R3×512X_{\text{embed}} \in \mathbb{R}^{3 \times 512}Xembed∈R3×512

每个词元被映射为一个512维的连续向量,这些向量将在训练过程中学习到语义信息。

2. 位置编码(Positional Encoding)

由于Transformer没有循环或卷积结构,它无法感知词元的顺序信息。因此,需要显式地注入位置信息。

位置编码使用正弦和余弦函数:

PE(pos,2i)=sin⁡(pos100002i/dmodel) PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) PE(pos,2i)=sin(100002i/dmodelpos)

PE(pos,2i+1)=cos⁡(pos100002i/dmodel) PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) PE(pos,2i+1)=cos(100002i/dmodelpos)

其中 pospospos 是位置索引(0, 1, 2),iii 是维度索引(0 到 255)。

操作

X=Xembed+PE X = X_{\text{embed}} + PE X=Xembed+PE

维度变化

  • Xembed∈R3×512X_{\text{embed}} \in \mathbb{R}^{3 \times 512}Xembed∈R3×512
  • PE∈R3×512PE \in \mathbb{R}^{3 \times 512}PE∈R3×512
  • 输出:X∈R3×512X \in \mathbb{R}^{3 \times 512}X∈R3×512(维度不变)

位置编码与词嵌入相加,使得每个位置的表示既包含词的语义信息,又包含其位置信息。

第二阶段:编码器处理(以第一层为例)

编码器共有 N=6N = 6N=6 层,每层结构完全相同,包含两个子层:

  1. 多头自注意力子层(Multi-Head Self-Attention)
  2. 前馈网络子层(Feed-Forward Network)

每个子层后都跟着残差连接层归一化

1. 多头自注意力子层

步骤1:线性投影生成 Q、K、V

对于输入 X∈R3×512X \in \mathbb{R}^{3 \times 512}X∈R3×512,对于每个注意力头 iii(共 h=8h = 8h=8 个),有独立的投影矩阵:

WiQ∈R512×64,WiK∈R512×64,WiV∈R512×64 W_i^Q \in \mathbb{R}^{512 \times 64}, \quad W_i^K \in \mathbb{R}^{512 \times 64}, \quad W_i^V \in \mathbb{R}^{512 \times 64} WiQ∈R512×64,WiK∈R512×64,WiV∈R512×64

计算每个头的查询、键、值矩阵:

Qi=X⋅WiQ∈R3×64 Q_i = X \cdot W_i^Q \in \mathbb{R}^{3 \times 64} Qi=X⋅WiQ∈R3×64

Ki=X⋅WiK∈R3×64 K_i = X \cdot W_i^K \in \mathbb{R}^{3 \times 64} Ki=X⋅WiK∈R3×64

Vi=X⋅WiV∈R3×64 V_i = X \cdot W_i^V \in \mathbb{R}^{3 \times 64} Vi=X⋅WiV∈R3×64

步骤2:缩放点积注意力(每个头并行计算)

注意力计算公式为:

Attention(Qi,Ki,Vi)=softmax(QiKiTdk)Vi \text{Attention}(Q_i, K_i, V_i) = \text{softmax}\left(\frac{Q_i K_i^T}{\sqrt{d_k}}\right) V_i Attention(Qi,Ki,Vi)=softmax(dk QiKiT)Vi

关键维度变化

  • Qi∈R3×64Q_i \in \mathbb{R}^{3 \times 64}Qi∈R3×64,KiT∈R64×3K_i^T \in \mathbb{R}^{64 \times 3}KiT∈R64×3
  • QiKiT∈R3×3Q_i K_i^T \in \mathbb{R}^{3 \times 3}QiKiT∈R3×3(注意力分数矩阵,表示每个词关注其他所有词的强度)
  • dk=64=8\sqrt{d_k} = \sqrt{64} = 8dk =64 =8(缩放因子,防止点积过大)
  • softmax\text{softmax}softmax 后:R3×3\mathbb{R}^{3 \times 3}R3×3(注意力权重矩阵,每行和为1)
  • 乘以 Vi∈R3×64V_i \in \mathbb{R}^{3 \times 64}Vi∈R3×64 后:headi∈R3×64\text{head}_i \in \mathbb{R}^{3 \times 64}headi∈R3×64

注意力权重矩阵的含义

复制代码
          I    love   you
    I   [0.85, 0.10, 0.05]
 love   [0.20, 0.65, 0.15]
 you    [0.08, 0.12, 0.80]

第 iii 行第 jjj 列的值表示位置 iii 对位置 jjj 的关注程度。

步骤3:多头拼接与投影

将所有 h=8h=8h=8 个头的输出在特征维度上拼接:

Concat(head1,...,head8)∈R3×512 \text{Concat}(\text{head}_1, \dots, \text{head}_8) \in \mathbb{R}^{3 \times 512} Concat(head1,...,head8)∈R3×512

通过输出投影矩阵 WO∈R512×512W^O \in \mathbb{R}^{512 \times 512}WO∈R512×512 进行线性变换:

MultiHead(X)=Concat(head1,...,head8)⋅WO∈R3×512 \text{MultiHead}(X) = \text{Concat}(\text{head}_1, \dots, \text{head}_8) \cdot W^O \in \mathbb{R}^{3 \times 512} MultiHead(X)=Concat(head1,...,head8)⋅WO∈R3×512

步骤4:残差连接与层归一化

Z1=LayerNorm(X+MultiHead(X))∈R3×512 Z_1 = \text{LayerNorm}(X + \text{MultiHead}(X)) \in \mathbb{R}^{3 \times 512} Z1=LayerNorm(X+MultiHead(X))∈R3×512

残差连接让梯度能够直接流过,缓解深层网络的梯度消失问题;层归一化则稳定训练过程。

2. 前馈网络子层

前馈网络由两个线性变换和一个ReLU激活函数组成:

FFN(x)=max⁡(0,xW1+b1)W2+b2 \text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2 FFN(x)=max(0,xW1+b1)W2+b2

其中:

  • W1∈R512×2048W_1 \in \mathbb{R}^{512 \times 2048}W1∈R512×2048,b1∈R2048b_1 \in \mathbb{R}^{2048}b1∈R2048
  • W2∈R2048×512W_2 \in \mathbb{R}^{2048 \times 512}W2∈R2048×512,b2∈R512b_2 \in \mathbb{R}^{512}b2∈R512

维度变化

  • 输入 Z1∈R3×512Z_1 \in \mathbb{R}^{3 \times 512}Z1∈R3×512
  • Z1⋅W1∈R3×2048Z_1 \cdot W_1 \in \mathbb{R}^{3 \times 2048}Z1⋅W1∈R3×2048(升维到2048)
  • ReLU激活后:R3×2048\mathbb{R}^{3 \times 2048}R3×2048(维度不变)
  • ⋅W2∈R3×512\cdot W_2 \in \mathbb{R}^{3 \times 512}⋅W2∈R3×512(降维回512)

残差连接与层归一化

EncoderOutput1=LayerNorm(Z1+FFN(Z1))∈R3×512 \text{EncoderOutput}_1 = \text{LayerNorm}(Z_1 + \text{FFN}(Z_1)) \in \mathbb{R}^{3 \times 512} EncoderOutput1=LayerNorm(Z1+FFN(Z1))∈R3×512

3. 堆叠编码器层

将 EncoderOutput1\text{EncoderOutput}_1EncoderOutput1 作为第二层的输入,重复上述过程 N=6N=6N=6 次。

最终编码器输出:

EncoderOutput∈R3×512 \text{EncoderOutput} \in \mathbb{R}^{3 \times 512} EncoderOutput∈R3×512

每个输入词元被编码为一个包含整个序列上下文信息的512维向量。

第三阶段:解码器处理(自回归生成)

解码器在训练时和推理时的流程不同。此处以**推理时生成第一个词"我"**为例。

解码器同样有 N=6N=6N=6 层,每层包含三个子层:

  1. 掩码多头自注意力(Masked Multi-Head Self-Attention)
  2. 编码器-解码器多头注意力(Cross-Attention)
  3. 前馈网络

1. 初始输入

解码器输入以起始符 <s> 开始,当前输出序列为 ["<s>"],长度 mcurrent=1m_{\text{current}} = 1mcurrent=1。

经过输出嵌入和位置编码后:

Y∈R1×512 Y \in \mathbb{R}^{1 \times 512} Y∈R1×512

2. 解码器第一层(以生成第一个词为例)

子层1:掩码多头自注意力

与编码器自注意力类似,但使用**因果掩码(Causal Mask)**防止看到未来位置。

对于输入 Y∈R1×512Y \in \mathbb{R}^{1 \times 512}Y∈R1×512,每个头生成:

Qi,Ki,Vi∈R1×64 Q_i, K_i, V_i \in \mathbb{R}^{1 \times 64} Qi,Ki,Vi∈R1×64

计算注意力分数:

Scores=QiKiTdk∈R1×1 \text{Scores} = \frac{Q_i K_i^T}{\sqrt{d_k}} \in \mathbb{R}^{1 \times 1} Scores=dk QiKiT∈R1×1

由于只有一个词,它只能关注自身(因果掩码在此处无影响)。

残差连接与层归一化

D1=LayerNorm(Y+MaskedMultiHead(Y))∈R1×512 D_1 = \text{LayerNorm}(Y + \text{MaskedMultiHead}(Y)) \in \mathbb{R}^{1 \times 512} D1=LayerNorm(Y+MaskedMultiHead(Y))∈R1×512

子层2:编码器-解码器注意力(交叉注意力)

这是解码器的核心组件,它让解码器能够"查看"编码器的输出。

Query 来自解码器的上一子层,KeyValue 来自编码器输出。

对于每个头:

  • Qi=D1⋅WiQ∈R1×64Q_i = D_1 \cdot W_i^Q \in \mathbb{R}^{1 \times 64}Qi=D1⋅WiQ∈R1×64
  • Ki=EncoderOutput⋅WiK∈R3×64K_i = \text{EncoderOutput} \cdot W_i^K \in \mathbb{R}^{3 \times 64}Ki=EncoderOutput⋅WiK∈R3×64
  • Vi=EncoderOutput⋅WiV∈R3×64V_i = \text{EncoderOutput} \cdot W_i^V \in \mathbb{R}^{3 \times 64}Vi=EncoderOutput⋅WiV∈R3×64

注意力计算

Scores=QiKiTdk∈R1×3 \text{Scores} = \frac{Q_i K_i^T}{\sqrt{d_k}} \in \mathbb{R}^{1 \times 3} Scores=dk QiKiT∈R1×3

这个 1×31 \times 31×3 的向量表示当前解码器位置对编码器3个位置的关注程度。

Attentioni=softmax(Scores)⋅Vi∈R1×64 \text{Attention}_i = \text{softmax}(\text{Scores}) \cdot V_i \in \mathbb{R}^{1 \times 64} Attentioni=softmax(Scores)⋅Vi∈R1×64

多头拼接与投影

CrossAttention=Concat(Attention1,...,Attention8)⋅WO∈R1×512 \text{CrossAttention} = \text{Concat}(\text{Attention}_1, \dots, \text{Attention}_8) \cdot W^O \in \mathbb{R}^{1 \times 512} CrossAttention=Concat(Attention1,...,Attention8)⋅WO∈R1×512

残差连接与层归一化

D2=LayerNorm(D1+CrossAttention)∈R1×512 D_2 = \text{LayerNorm}(D_1 + \text{CrossAttention}) \in \mathbb{R}^{1 \times 512} D2=LayerNorm(D1+CrossAttention)∈R1×512

子层3:前馈网络

与编码器相同:

FFN(D2)∈R1×512 \text{FFN}(D_2) \in \mathbb{R}^{1 \times 512} FFN(D2)∈R1×512

DecoderOutput1=LayerNorm(D2+FFN(D2))∈R1×512 \text{DecoderOutput}_1 = \text{LayerNorm}(D_2 + \text{FFN}(D_2)) \in \mathbb{R}^{1 \times 512} DecoderOutput1=LayerNorm(D2+FFN(D2))∈R1×512

3. 堆叠解码器层

经过 N=6N=6N=6 层解码器后,得到当前解码器输出:

DecoderOutput∈R1×512 \text{DecoderOutput} \in \mathbb{R}^{1 \times 512} DecoderOutput∈R1×512

第四阶段:输出生成

1. 线性投影与Softmax

通过一个可学习的线性层 Wlinear∈R512×VW_{\text{linear}} \in \mathbb{R}^{512 \times V}Wlinear∈R512×V 将解码器输出映射到词汇表空间:

Logits=DecoderOutput⋅Wlinear∈R1×37000 \text{Logits} = \text{DecoderOutput} \cdot W_{\text{linear}} \in \mathbb{R}^{1 \times 37000} Logits=DecoderOutput⋅Wlinear∈R1×37000

应用Softmax得到概率分布:

Probabilities=softmax(Logits)∈R1×37000 \text{Probabilities} = \text{softmax}(\text{Logits}) \in \mathbb{R}^{1 \times 37000} Probabilities=softmax(Logits)∈R1×37000

选择概率最高的词元作为输出:

y^=arg⁡max⁡Probabilities \hat{y} = \arg\max \text{Probabilities} y^=argmaxProbabilities

假设输出为"我"。

2. 迭代生成

将生成的"我"追加到输出序列,现在序列为 ["<s>", "我"],mcurrent=2m_{\text{current}} = 2mcurrent=2。

重复整个第三阶段和第四阶段:

  • 解码器输入为两个词元的嵌入 Y∈R2×512Y \in \mathbb{R}^{2 \times 512}Y∈R2×512
  • 在掩码自注意力中,QKTQK^TQKT 是一个 R2×2\mathbb{R}^{2 \times 2}R2×2 的矩阵

因果掩码示例 (m=2m=2m=2):

M=[0−∞00] M = \begin{bmatrix} 0 & -\infty \\ 0 & 0 \end{bmatrix} M=[00−∞0]

  • 第一行(对应 <s>):只能关注自己
  • 第二行(对应"我"):可以关注 <s> 和自己,不能关注未来位置

最终生成第二个词"爱",以此类推,直到生成结束符 <eos>

核心维度总结表

步骤 关键输入 关键操作/矩阵 输出维度 说明
输入嵌入 词元ID (n=3) 嵌入矩阵 E∈RV×512E \in \mathbb{R}^{V \times 512}E∈RV×512 R3×512\mathbb{R}^{3 \times 512}R3×512 将词转换为向量
位置编码 Xembed∈R3×512X_{\text{embed}} \in \mathbb{R}^{3 \times 512}Xembed∈R3×512 正弦函数 PE(pos)PE(pos)PE(pos) R3×512\mathbb{R}^{3 \times 512}R3×512 加入顺序信息
Q/K/V投影 X∈R3×512X \in \mathbb{R}^{3 \times 512}X∈R3×512 WiQ,WiK,WiV∈R512×64W_i^Q, W_i^K, W_i^V \in \mathbb{R}^{512 \times 64}WiQ,WiK,WiV∈R512×64 Qi,Ki,Vi∈R3×64Q_i, K_i, V_i \in \mathbb{R}^{3 \times 64}Qi,Ki,Vi∈R3×64 每个注意力头
注意力权重 Qi∈R3×64Q_i \in \mathbb{R}^{3 \times 64}Qi∈R3×64, KiT∈R64×3K_i^T \in \mathbb{R}^{64 \times 3}KiT∈R64×3 QiKiTQ_i K_i^TQiKiT R3×3\mathbb{R}^{3 \times 3}R3×3 词与词之间的相关性矩阵
注意力输出 权重 R3×3\mathbb{R}^{3 \times 3}R3×3, Vi∈R3×64V_i \in \mathbb{R}^{3 \times 64}Vi∈R3×64 softmax(...)⋅Vi\text{softmax}(...) \cdot V_isoftmax(...)⋅Vi headi∈R3×64\text{head}_i \in \mathbb{R}^{3 \times 64}headi∈R3×64 加权求和的值
多头拼接 8个 headi∈R3×64\text{head}_i \in \mathbb{R}^{3 \times 64}headi∈R3×64 拼接 Concat R3×512\mathbb{R}^{3 \times 512}R3×512 合并所有头的信息
前馈网络 Z∈R3×512Z \in \mathbb{R}^{3 \times 512}Z∈R3×512 W1∈R512×2048W_1 \in \mathbb{R}^{512 \times 2048}W1∈R512×2048, W2∈R2048×512W_2 \in \mathbb{R}^{2048 \times 512}W2∈R2048×512 R3×512\mathbb{R}^{3 \times 512}R3×512 逐位置非线性变换
交叉注意力Q D∈Rm×512D \in \mathbb{R}^{m \times 512}D∈Rm×512 (m=1) WiQ∈R512×64W_i^Q \in \mathbb{R}^{512 \times 64}WiQ∈R512×64 Q∈R1×64Q \in \mathbb{R}^{1 \times 64}Q∈R1×64 来自解码器
交叉注意力K/V EncoderOutput∈R3×512\text{EncoderOutput} \in \mathbb{R}^{3 \times 512}EncoderOutput∈R3×512 WiK,WiV∈R512×64W_i^K, W_i^V \in \mathbb{R}^{512 \times 64}WiK,WiV∈R512×64 K,V∈R3×64K, V \in \mathbb{R}^{3 \times 64}K,V∈R3×64 来自编码器
交叉注意力权重 Q∈R1×64Q \in \mathbb{R}^{1 \times 64}Q∈R1×64, KT∈R64×3K^T \in \mathbb{R}^{64 \times 3}KT∈R64×3 QKTQ K^TQKT R1×3\mathbb{R}^{1 \times 3}R1×3 解码器词关注所有编码器词
输出投影 DecoderOutput∈Rm×512\text{DecoderOutput} \in \mathbb{R}^{m \times 512}DecoderOutput∈Rm×512 Wlinear∈R512×VW_{\text{linear}} \in \mathbb{R}^{512 \times V}Wlinear∈R512×V Rm×V\mathbb{R}^{m \times V}Rm×V 映射到词汇表概率

流程核心要点

维度主线

dmodel=512d_{\text{model}} = 512dmodel=512 是贯穿始终的主维度;nnn(源序列长度)和 mmm(目标序列长度)是动态变化的序列长度维度。

注意力本质

通过 QKTQK^TQKT 计算出一个 序列长度 × 序列长度 的权重矩阵,实现词与词之间的全局交互。这个矩阵是Transformer能够捕捉长距离依赖的关键。

并行与顺序的区别

阶段 并行性 原因
训练时编码器 完全并行 无依赖关系
训练时解码器 并行(带掩码) 使用Teacher Forcing,未来位置被掩码
推理时编码器 完全并行 输入已知
推理时解码器 自回归(顺序) 每个词依赖之前生成的词

信息流动

  1. 编码器 :将源序列编码为上下文向量 EncoderOutput∈R3×512\text{EncoderOutput} \in \mathbb{R}^{3 \times 512}EncoderOutput∈R3×512
  2. 解码器:通过交叉注意力动态地从这些向量中检索信息,结合自身的自注意力,生成目标序列

CrossAttention(Qdec,Kenc,Venc)=softmax(QdecKencTdk)Venc \text{CrossAttention}(Q_{\text{dec}}, K_{\text{enc}}, V_{\text{enc}}) = \text{softmax}\left(\frac{Q_{\text{dec}} K_{\text{enc}}^T}{\sqrt{d_k}}\right) V_{\text{enc}} CrossAttention(Qdec,Kenc,Venc)=softmax(dk QdecKencT)Venc

总结:Transformer的成功秘诀

通过这个完整的矩阵演算,我们可以总结出Transformer成功的几个关键因素:

三大核心创新

  1. 多头自注意力:让每个词都能直接与序列中所有其他词交互,完美捕捉长距离依赖
  2. 位置编码:弥补纯注意力架构对位置信息的缺失
  3. 残差连接 + 层归一化:使得深度网络的训练成为可能

维度设计的智慧

参数 设计理由
dmodel=512d_{\text{model}} = 512dmodel=512 512 足够大的表示容量
dff=2048d_{ff} = 2048dff=2048 2048 4倍的扩展,提供充分的非线性变换能力
h=8h = 8h=8, dk=64d_k = 64dk=64 8头,64维 多头并行,每个头关注不同的特征子空间

最终结论

Transformer的成功在于它用统一的注意力机制替代了复杂的循环结构,使得模型能够:

  • 并行处理整个序列,训练速度快
  • 捕捉任意距离的依赖关系
  • 自动学习词对齐,无需显式标注
  • 易于扩展为大规模预训练模型

这就是为什么《Attention Is All You Need》能成为深度学习领域的里程碑论文------它不仅改变了机器翻译,更开启了大语言模型的新时代。

参考文献

  1. Vaswani, A., et al. "Attention Is All You Need." NeurIPS 2017.
  2. The Illustrated Transformer. Jay Alammar.
  3. 从矩阵维度理解Transformer. CSDN博客.

本文首发于CSDN博客,欢迎转发讨论。如果觉得有帮助,请点赞支持!

相关推荐
阿_旭2 小时前
【深度学习实战】Mask R-CNN肺部分割全流程:从数据到模型的完整指南
深度学习·r语言·cnn
极光代码工作室3 小时前
基于机器学习的垃圾短信识别系统
人工智能·python·深度学习·机器学习
卡梅德生物科技小能手3 小时前
深度解析CD66b (癌胚抗原相关细胞粘附分子8):中性粒细胞的关键调控靶点
经验分享·深度学习·生活
bryant_meng3 小时前
【Reading Notes】(8.9)Favorite Articles from 2025 September
人工智能·深度学习·llm·资讯
思绪无限3 小时前
YOLOv5至YOLOv12升级:PCB板缺陷检测系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·yolov12·yolo全家桶·pcb板缺陷检测
快乐得小萝卜3 小时前
Xfeat部署系列-1-暴力匹配加速!
人工智能·深度学习
高洁013 小时前
工业AI部署:模型量化与边缘设备部署实战
人工智能·深度学习·机器学习·数据挖掘·transformer
泰恒3 小时前
ChatGPT发展历程
人工智能·深度学习·yolo·机器学习·计算机视觉
Omics Pro3 小时前
斯坦福:强化学习生物约束型虚拟细胞建模
人工智能·深度学习·算法·机器学习·计算机视觉·数据挖掘·数据分析