深入理解 Transformer 架构:从注意力机制到 GPT
1. 注意力机制(Attention Mechanism)
1.1 什么是注意力机制?
注意力机制的核心思想是:在处理序列数据时,模型应该”关注”与当前任务最相关的部分。
想象你在阅读一段文字时,虽然你会看到所有词,但你真正”聚焦”的只有少数几个与理解当前句子最相关的词。注意力机制正是模拟了这种人眼的注意力分配方式。
1.2 缩放点积注意力(Scaled Dot-Product Attention)
Transformer 使用的是缩放点积注意力机制。给定查询(Query)、键(Key)和值(Value)三个矩阵:
其中 是键向量的维度。为什么要除以 ?
原因:当 较大时,点积的值会变得很大,导致 softmax 函数进入饱和区域,梯度变得非常小。通过缩放,可以保持点积结果的方差稳定。
import torchimport torch.nn.functional as Fimport math
def scaled_dot_product_attention(Q, K, V, mask=None): """ Q: (batch, seq_len, d_k) K: (batch, seq_len, d_k) V: (batch, seq_len, d_v) """ d_k = Q.size(-1)
# 计算点积 scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)
# 应用掩码(用于防止看到未来信息) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9)
# softmax 归一化 attention_weights = F.softmax(scores, dim=-1)
# 加权求和 output = torch.matmul(attention_weights, V)
return output, attention_weights1.3 注意力权重示例
假设我们有句子 “The cat sat on the mat”,当模型处理 “cat” 这个词时,注意力权重可能如下分布:
| 词 Token | 注意力权重 |
|---|---|
| The | 0.12 |
| cat | 0.35 |
| sat | 0.18 |
| on | 0.08 |
| the | 0.15 |
| mat | 0.12 |
可以看到,模型在处理 “cat” 时,会给自身(0.35)和相邻的 “sat”(0.18)、“the”(0.15)较高的注意力权重,这符合语法和语义上的关联。
温度(Temperature)的影响:
- 温度越高 → 注意力分布越均匀(更”软”的注意力)
- 温度越低 → 注意力分布越尖锐(更”硬”的注意力,接近 one-hot)
1.4 为什么需要 Query、Key、Value?
这是一个非常巧妙的设计:
- Query(查询):当前位置想要查找的信息
- Key(键):每个位置的”索引”,用于匹配 Query
- Value(值):每个位置的实际内容
类比搜索引擎:
- Query 是你的搜索词
- Key 是网页的标题/关键词
- Value 是网页的实际内容
2. 多头注意力(Multi-Head Attention)
2.1 为什么需要多头?
单个注意力头只能学习一种类型的关联关系,而多头注意力让模型能够同时关注不同类型的信息。
例如,在翻译任务中,一个头可能关注语法结构,另一个头关注语义关联,还有一个头关注词汇对应关系。
2.2 多头注意力的计算
其中每个头的计算:
import torchimport torch.nn as nn
class MultiHeadAttention(nn.Module): def __init__(self, d_model, num_heads): super().__init__() assert d_model % num_heads == 0
self.d_model = d_model self.num_heads = num_heads self.d_k = d_model // num_heads
# 线性变换层 self.W_q = nn.Linear(d_model, d_model) self.W_k = nn.Linear(d_model, d_model) self.W_v = nn.Linear(d_model, d_model) self.W_o = nn.Linear(d_model, d_model)
def split_heads(self, x): """将最后一个维度分割成 num_heads 个头""" batch_size, seq_len, _ = x.size() x = x.view(batch_size, seq_len, self.num_heads, self.d_k) return x.permute(0, 2, 1, 3) # (batch, heads, seq_len, d_k)
def forward(self, Q, K, V, mask=None): batch_size = Q.size(0)
# 线性变换并分割成多个头 Q = self.split_heads(self.W_q(Q)) K = self.split_heads(self.W_k(K)) V = self.split_heads(self.W_v(V))
# 计算注意力 attn_output, _ = scaled_dot_product_attention(Q, K, V, mask)
# 合并多头 attn_output = attn_output.permute(0, 2, 1, 3).contiguous() attn_output = attn_output.view(batch_size, -1, self.d_model)
# 最终线性变换 output = self.W_o(attn_output)
return output3. 位置编码(Positional Encoding)
3.1 为什么需要位置编码?
Transformer 本身没有循环结构,无法直接获取序列中元素的位置信息。但词的顺序在语言中至关重要(“狗咬人” vs “人咬狗”)。
为了解决这个问题,Transformer 使用位置编码(Positional Encoding)来注入位置信息。
3.2 正弦和余弦位置编码
论文中使用正弦和余弦函数来生成位置编码:
import torchimport torch.nn as nnimport math
class PositionalEncoding(nn.Module): def __init__(self, d_model, max_seq_len=5000): super().__init__()
# 创建位置编码矩阵 pe = torch.zeros(max_seq_len, d_model)
# 位置向量 position = torch.arange(0, max_seq_len, dtype=torch.float).unsqueeze(1)
# 频率向量 div_term = torch.exp( torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model) )
# 奇偶位置分别使用 sin 和 cos pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term)
# 添加批次维度 pe = pe.unsqueeze(0) # (1, max_seq_len, d_model)
# 注册为不优化的缓冲区 self.register_buffer('pe', pe)
def forward(self, x): """ x: (batch_size, seq_len, d_model) """ # 将位置编码添加到输入 x = x + self.pe[:, :x.size(1), :] return x3.3 位置编码可视化
3.4 位置编码的特性
正弦/余弦位置编码具有以下优点:
- 不同位置的编码唯一:每个位置都有独特的编码
- 相对位置可推导: 可以表示为 的线性函数
- 支持任意长度的序列:可以泛化到训练时未见过的序列长度
近年来,研究者提出了多种改进的位置编码方式:
- 旋转位置编码(RoPE):LLaMA 采用,在注意力计算中融入位置信息
- 相对位置编码:直接建模 token 之间的相对距离
- ALiBi:一种不需要位置编码的方法,通过注意力分数的线性偏置实现
4. Transformer 整体架构
4.1 编码器(Encoder)
每个编码器层包含两个子层:
- 多头自注意力层:对输入序列进行自注意力计算
- 前馈神经网络(FFN):两层线性变换,中间有 ReLU 激活
每个子层周围都有残差连接和层归一化:
4.2 解码器(Decoder)
解码器在编码器的基础上增加了一个掩码多头注意力层,确保预测时只能看到当前词之前的词(不能”看到未来”)。
4.3 架构可视化
4.3 编码器-解码器架构图
┌─────────────────────────────────────────────────────────────────┐│ 完整 Transformer 架构 │├─────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────┐ ││ │ 输入嵌入 │ ││ │ + 位置编码 │ ││ └──────┬──────┘ ││ │ ││ ▼ ││ ┌─────────────────────────────────────────┐ ││ │ 编码器 (N 层) │ ││ │ ┌─────────────────────────────────────┐ │ ││ │ │ Multi-Head Self-Attention │ │ ││ │ │ Add & Norm │ │ ││ │ │ Feed Forward Network │ │ ││ │ │ Add & Norm │ │ ││ │ └─────────────────────────────────────┘ │ ││ └──────────────────┬────────────────────────┘ ││ │ ││ │ 编码器输出 ││ │ (作为 K, V) ││ ┌───────────┴───────────┐ ││ ▼ ▼ ││ ┌─────────────┐ ┌─────────────┐ ││ │ 输出嵌入 │ │ 解码器输入 │ ││ │ + 位置编码 │ │ (右移) │ ││ └──────┬──────┘ └──────┬──────┘ ││ │ │ ││ ▼ ▼ ││ ┌─────────────────────────────────────────┐ ││ │ 解码器 (N 层) │ ││ │ ┌─────────────────────────────────────┐ │ ││ │ │ Masked Self-Attention │ │ ││ │ │ Add & Norm │ │ ││ │ │ Cross-Attention (使用编码器 K/V) │ │ ││ │ │ Add & Norm │ │ ││ │ │ Feed Forward Network │ │ ││ │ │ Add & Norm │ │ ││ │ └─────────────────────────────────────┘ │ ││ └──────────────────┬────────────────────────┘ ││ │ ││ ▼ ││ ┌─────────────┐ ││ │ 线性层 │ ││ │ + Softmax │ ││ └──────┬──────┘ ││ ▼ ││ ┌─────────────┐ ││ │ 输出概率 │ ││ └─────────────┘ │└─────────────────────────────────────────────────────────────────┘图例说明:
- 编码器:处理输入序列,捕捉双向上下文信息
- 解码器:自注意力确保只看到当前词之前的词,交叉注意力使用编码器输出的 K/V
- 残差连接:每个子层周围都有 Skip Connection 和 LayerNorm
5.1 BERT:双向编码器
BERT(Bidirectional Encoder Representations from Transformers)仅使用 Transformer 的编码器部分,通过掩码语言模型(MLM)任务实现双向上下文建模。
5.2 GPT:生成式预训练
GPT 系列(GPT-2、GPT-3、GPT-4)仅使用 Transformer 的解码器部分,通过下一个词预测任务进行训练,展现了强大的文本生成能力。
5.3 T5:编码器-解码器统一
T5 将所有 NLP 任务统一建模为 Text-to-Text 任务,使用完整的编码器-解码器结构。
5.4 现代大模型架构
| 模型 | 架构 | 特点 |
|---|---|---|
| GPT-4 | 解码器 | 超大规模,RLHF 微调 |
| LLaMA | 解码器 | 开源,高效 |
| ChatGLM | 解码器 | 中文优化,对齐微调 |
| Mistral | 解码器 | Sparse MoE,高效 |
| Claude | 解码器 | Constitutional AI |
6. 核心公式总结
- 缩放点积注意力:
- 多头注意力:
- 层归一化 + 残差连接:
7. 总结
Transformer 的核心创新在于:
- 完全基于注意力机制:摒弃了 RNN 的顺序计算,实现了真正的并行化
- 多头注意力:允许模型关注不同类型的关联关系
- 位置编码:解决了序列顺序建模的问题
- 可扩展性:可以通过增加层数和维度来提升模型容量
这些设计使得 Transformer 能够高效处理长距离依赖问题,并为现代大语言模型的发展奠定了基础。
参考资料
- Vaswani, A., et al. (2017). “Attention Is All You Need.” NeurIPS.
- Devlin, J., et al. (2018). “BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding.” NAACL.
- Radford, A., et al. (2019). “Language Models are Unsupervised Multitask Learners.” OpenAI Technical Report.
- Touvron, H., et al. (2023). “LLaMA: Open and Efficient Foundation Language Models.” Meta AI.
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!

