Transformer 架构是怎么工作的?自注意力、位置编码和残差连接详解
Transformer 是 2017 年 Google 在《Attention is All You Need》里提出的架构,用纯注意力机制替代了 RNN 和 CNN 做序列建模。它是 BERT、GPT 以及所有现代大语言模型的基础。
核心思想:注意力替代递归
RNN 处理序列要一步一步来——看第 3 个词之前必须先处理第 1 和第 2 个词。这导致两个问题:无法并行训练,长距离依赖会衰减(梯度消失)。
Transformer 的解决方案是:让每个位置直接和所有其他位置交互,一步到位。不需要逐步递归,训练时所有位置可以并行计算——GPU 最擅长这种矩阵运算。
自注意力:序列中的每个词和所有词交互
对序列中的每个词,自注意力计算它和其他所有词的相关性(注意力权重),然后按权重聚合信息。具体来说:每个词生成三个向量——Query(我在找什么)、Key(我能提供什么)、Value(我的实际内容)。Query 和所有 Key 做点积得到相关性分数,softmax 归一化后对 Value 加权求和。
Attention(Q, K, V) = softmax(QK^T / √d_k) V
除以 √d_k 是缩放,防止点积太大导致 softmax 输出接近 one-hot(梯度几乎为零)。这个缩放因子是"Scaled Dot-Product Attention"里"Scaled"的由来。
多头注意力:同时学多种关系
一个注意力头只能学一种关联模式。但语言中有语法关系、语义关系、位置关系等多种层次。多头注意力让每个头独立学习不同的模式——8 个头就学 8 种不同的"怎么看句子"的方式,最后拼接起来。
实验上,多头注意力的效果显著优于单头。但头数不是越多越好,通常和模型维度一起调。GPT-3 用了 96 个头,但那是因为模型维度是 12288——每个头的维度是 128,和原始论文一致。
位置编码:没有递归,怎么知道词的顺序
自注意力本身是排列不变的——打乱输入顺序,输出只是对应的排列,值不变。但"猫吃鱼"和"鱼吃猫"意思完全不同,模型必须知道词的顺序。
Transformer 用正弦/余弦函数生成位置编码,和词嵌入相加。为什么用三角函数?因为它有相对位置的性质:PE(pos+k) 可以用 PE(pos) 的线性变换表示,这让模型更容易学习相对位置关系。
后来的模型用了可学习的位置编码(BERT、GPT 都是),直接让模型自己学一组位置向量。RoPE(旋转位置编码)是更新的方案,被 LLaMA 等模型采用,能更好地泛化到训练时没见过的序列长度。
残差连接和层归一化
每个 Transformer 层的输出 = LayerNorm(x + Sublayer(x)),其中 Sublayer 是注意力或前馈网络。残差连接(+x)让梯度可以直接回传,避免深层网络梯度消失。层归一化(LayerNorm)稳定训练,防止每层的输出分布漂移。
注意归一化的位置:原始 Transformer 是 Post-LN(先 Sublayer 再 LN),后来发现 Pre-LN(先 LN 再 Sublayer)训练更稳定,GPT 和大多数现代模型都用 Pre-LN。
编码器-解码器结构
原始 Transformer 用于机器翻译,包含编码器和解码器:
- 编码器:双向自注意力 + 前馈网络,理解源语言
- 解码器:单向自注意力(遮住未来信息)+ 交叉注意力(看编码器输出)+ 前馈网络,生成目标语言
但后来的发展证明不需要两者都用:BERT 只用编码器(理解任务),GPT 只用解码器(生成任务),T5 保留了完整的编码器-解码器。2024 年的趋势是纯解码器架构一统天下——解码器通过指令微调也能做理解任务,何必维护两个模块?
前馈网络:注意力的补充
每层还有一个两层的前馈网络:FFN(x) = W2·ReLU(W1·x)。FFN 的隐藏维度通常是模型维度的 4 倍(如 d_model=768 时 FFN 维度=3072)。
自注意力负责词和词之间的关系,FFN 负责每个位置内部的非线性变换。可以理解为:注意力做信息路由(把相关信息拉过来),FFN 做信息加工(把拉过来的信息消化掉)。研究表明 FFN 层存储了大部分的"知识"(事实记忆),而注意力层更多在做"逻辑"(关系推理)。