为什么要理解 Transformer?
2017 年《Attention Is All You Need》这篇论文颠覆了 NLP 领域。在它之前,机器翻译主要依赖 RNN/LSTM,存在”长距离依赖消失”和”无法并行计算”两个痛点。Transformer 通过自注意力机制同时解决了这两个问题,并成为 GPT、BERT、Claude 等所有现代 LLM 的基石。
自注意力机制(Self-Attention)
直观理解
假设有一句话:“丽芙敲代码到深夜,她真的热爱编程。” 当模型处理”她”这个字时,它需要知道”她”指的是”丽芙”而非”代码”。自注意力的作用就是让每个词都去”看”句子中的所有词,并给相关度打分。
数学原理
每个词被映射为三个向量:
- Query(查询):我要找什么?
- Key(键):我有什么?
- Value(值):我的实际内容?
这三个向量通过输入词向量乘以三个权重矩阵得到:
自注意力分数的计算:
关键点:
- :计算所有词两两之间的相似度,得到一个「注意力矩阵」
- \sqrt:缩放因子,防止点积过大导致 softmax 进入梯度消失区域
- \text:将分数转化为概率分布
- 左乘 :按注意力权重加权求和
代码实现
import torch
import torch.nn.functional as F
def self_attention(Q, K, V):
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(d_k, dtype=torch.float32))
attention_weights = F.softmax(scores, dim=-1)
return torch.matmul(attention_weights, V)
多头注意力(Multi-Head Attention)
单头注意力只能捕获一种关系模式。多头注意力让模型同时关注不同表示子空间中的信息:
class MultiHeadAttention(nn.Module):
def __init__(self, d_model=512, num_heads=8):
super().__init__()
self.d_k = d_model // num_heads
self.num_heads = 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 forward(self, x):
# x: (batch, seq_len, d_model)
batch, seq_len, _ = x.size()
Q = self.W_Q(x).view(batch, seq_len, self.num_heads, self.d_k).transpose(1, 2)
K = self.W_K(x).view(batch, seq_len, self.num_heads, self.d_k).transpose(1, 2)
V = self.W_V(x).view(batch, seq_len, self.num_heads, self.d_k).transpose(1, 2)
attn_output = self_attention(Q, K, V)
attn_output = attn_output.transpose(1, 2).contiguous().view(batch, seq_len, -1)
return self.W_O(attn_output)
位置编码
Transformer 不像 RNN 那样天然知道词的先后顺序。位置编码的任务就是给模型注入位置信息。
原始论文使用正弦位置编码:
不同频率的正弦波使得模型可以轻易学习到相对位置信息——因为任意两个位置的 PE 之间存在线性关系。
现代的 LLM(如 GPT-4)大多使用可学习的位置嵌入(Learned Positional Embedding)或 RoPE(旋转位置编码),效果更好。
残差连接与层归一化
每个子层(自注意力 / 前馈网络)的输出都会加上输入(残差连接),然后做 Layer Normalization:
残差连接让梯度可以毫不衰减地传播到底层,使得训练极深的网络成为可能——这也是 GPT-4 能有上百层的原因。
小结
| 组件 | 作用 |
|---|---|
| 自注意力 | 全局上下文建模 |
| 多头注意力 | 多角度语义捕捉 |
| 位置编码 | 注入序列顺序 |
| 残差连接 | 梯度长距离传播 |
| 层归一化 | 训练稳定性 |
理解了这些,GPT 和 BERT 的区别就一目了然了:GPT 用了因果掩码(只看上文),BERT 用了双向注意力(同时看上下文)。下一篇我们会进入 GPT 的实现细节。
