Transformer 自注意力
改变 AI 历史的架构 — GPT、BERT、ViT 都建立在它之上
- 自注意力机制让每个位置都能直接关注序列中所有其他位置
- 多头注意力从不同子空间捕获不同类型的依赖关系
- 位置编码弥补了 Transformer 缺乏序列顺序感知的缺陷
- Mamba 用选择性状态空间模型实现了线性复杂度的序列建模
什么是自注意力?
自注意力(Self-Attention)的核心思想:让序列中的每个元素都能"看到"其他所有元素,并根据相关性分配不同的关注度。
比如句子 "The cat sat on the mat because it was tired",当模型处理 "it" 这个词时,自注意力能让它特别关注 "cat",从而理解 "it" 指的是猫。
🔑 三个关键角色:Q、K、V
每个输入词都会生成三个向量,就像图书馆找书的比喻:
Q 和 K 点积 → 得到注意力分数 → Softmax 归一化 → 加权求和 V → 输出
Excel 手推自注意力
用3个词的简单例子,完整推导自注意力的每一步。
📋 输入:三个词的嵌入向量
句子 "我 爱 AI",假设嵌入维度 d=2(简化演示):
| 词 | 嵌入向量 X |
|---|---|
| 我 | [1, 0] |
| 爱 | [0, 1] |
| AI | [1, 1] |
矩阵形式 X (3×2) = [[1,0], [0,1], [1,1]]
Step 2a:生成 Q、K、V
通过三个权重矩阵将输入映射为 Q、K、V(维度 d=2):
为简化演示,Wq=Wk=Wv=I(单位矩阵),所以 Q=X, K=X, V=X。实际中这三个矩阵通过训练学到不同的值。
| 词 | Q = X·Wq | K = X·Wk | V = X·Wv |
|---|---|---|---|
| 我 | [1, 0] | [1, 0] | [1, 0] |
| 爱 | [0, 1] | [0, 1] | [0, 1] |
| AI | [1, 1] | [1, 1] | [1, 1] |
Step 2b:计算注意力分数 Score = Q · KT
每个词的 Q 和所有词的 K 做点积,得到"相关性分数":
| Q · KT 计算过程 | |||
| Q (query) | K (key) | 点积计算 | 分数 |
|---|---|---|---|
| 我 [1,0] | → 我 [1,0] | 1×1 + 0×0 | 1 |
| 我 [1,0] | → 爱 [0,1] | 1×0 + 0×1 | 0 |
| 我 [1,0] | → AI [1,1] | 1×1 + 0×1 | 1 |
| 爱 [0,1] | → 我 [1,0] | 0×1 + 1×0 | 0 |
| 爱 [0,1] | → 爱 [0,1] | 0×0 + 1×1 | 1 |
| 爱 [0,1] | → AI [1,1] | 0×1 + 1×1 | 1 |
| AI [1,1] | → 我 [1,0] | 1×1 + 1×0 | 1 |
| AI [1,1] | → 爱 [0,1] | 1×0 + 1×1 | 1 |
| AI [1,1] | → AI [1,1] | 1×1 + 1×1 | 2 |
Step 2c:缩放 — Score / √d
除以 √d(d=2, √2≈1.414)防止点积过大导致 Softmax 梯度消失:
| → 我 | → 爱 | → AI | |
|---|---|---|---|
| 我 (query) | 1 / 1.414 = 0.707 | 0 / 1.414 = 0 | 1 / 1.414 = 0.707 |
| 爱 (query) | 0 / 1.414 = 0 | 1 / 1.414 = 0.707 | 1 / 1.414 = 0.707 |
| AI (query) | 1 / 1.414 = 0.707 | 1 / 1.414 = 0.707 | 2 / 1.414 = 1.414 |
Step 2d:Softmax 归一化 — 得到注意力权重
对每一行做 Softmax,让注意力权重加起来等于 1:
| → 我 | → 爱 | → AI | 求和验证 | |
|---|---|---|---|---|
| 我 (query) | e^0.707 / (e^0.707 + e^0 + e^0.707) = 0.370 | e^0 / (…) = 0.260 | e^0.707 / (…) = 0.370 | 1.000 ✓ |
| 爱 (query) | e^0 / (…) = 0.260 | e^0.707 / (…) = 0.370 | e^0.707 / (…) = 0.370 | 1.000 ✓ |
| AI (query) | e^0.707 / (…) = 0.289 | e^0.707 / (…) = 0.289 | e^1.414 / (…) = 0.422 | 1.000 ✓ |
解读注意力权重:
- • "我" 最关注自己和 "AI"(各0.370),对 "爱" 关注较少(0.260)
- • "爱" 最关注自己和 "AI"(各0.370),对 "我" 关注较少(0.260)
- • "AI" 最关注自己(0.422),因为它的向量 [1,1] 和自己最匹配
Step 2e:加权求和 — Output = Attention · V
用注意力权重对 V 做加权求和,得到每个词的新表示:
| "我" 的输出 = 0.370 × V_我 + 0.260 × V_爱 + 0.370 × V_AI | ||||
| 分量 | 0.370 × [1,0] | + 0.260 × [0,1] | + 0.370 × [1,1] | 结果 |
|---|---|---|---|---|
| 维度 1 | 0.370 | + 0 | + 0.370 | 0.740 |
| 维度 2 | 0 | + 0.260 | + 0.370 | 0.630 |
| "爱" 的输出 = 0.260 × V_我 + 0.370 × V_爱 + 0.370 × V_AI | ||||
| 分量 | 0.260 × [1,0] | + 0.370 × [0,1] | + 0.370 × [1,1] | 结果 |
|---|---|---|---|---|
| 维度 1 | 0.260 | + 0 | + 0.370 | 0.630 |
| 维度 2 | 0 | + 0.370 | + 0.370 | 0.740 |
| "AI" 的输出 = 0.289 × V_我 + 0.289 × V_爱 + 0.422 × V_AI | ||||
| 分量 | 0.289 × [1,0] | + 0.289 × [0,1] | + 0.422 × [1,1] | 结果 |
|---|---|---|---|---|
| 维度 1 | 0.289 | + 0 | + 0.422 | 0.711 |
| 维度 2 | 0 | + 0.289 | + 0.422 | 0.711 |
最终输出(每个词的新表示):
注意:现在每个词的向量都融合了其他词的信息!这就是"注意力"的魔力。
多头注意力 — Multi-Head Attention
一个"头"只能从一个角度看问题。多头注意力让模型同时从多个角度理解句子。
🎯 核心思想
把 Q、K、V 拆成多个"头"(head),每个头独立做注意力计算,最后把结果拼接起来,再通过一个线性变换整合。
类比:就像你读一句话时,同时用"语法视角"、"语义视角"、"情感视角"去理解它,最后综合所有视角得出全面理解。
📐 简化例子:2 个头,每头维度 d=1
沿用上面 "我 爱 AI" 的例子。原始 Q/K/V 维度为 2,我们拆成 2 个头,每个头只看一个维度:
| Step 2f-1:拆分 Q、K、V | |||
| 词 | 原始 Q (d=2) | Head 1 Q (第1维) | Head 2 Q (第2维) |
|---|---|---|---|
| 我 | [1, 0] | 1 | 0 |
| 爱 | [0, 1] | 0 | 1 |
| AI | [1, 1] | 1 | 1 |
K 和 V 同样按维度拆分(此处 Wq=Wk=Wv=I,所以 K 和 V 与 Q 相同)。
| Step 2f-2:Head 1 独立做注意力(只看第1维) | ||||
| Q (query) | K (key) | Q·K (标量) | Softmax 权重 | 加权 V |
|---|---|---|---|---|
| 我: 1 | 我:1 / 爱:0 / AI:1 | 1, 0, 1 | 0.370, 0.260, 0.370 | 0.370×1 + 0.260×0 + 0.370×1 = 0.740 |
| 爱: 0 | 我:1 / 爱:0 / AI:1 | 0, 0, 0 | 0.333, 0.333, 0.333 | 0.333×1 + 0.333×0 + 0.333×1 = 0.667 |
| AI: 1 | 我:1 / 爱:0 / AI:1 | 1, 0, 1 | 0.370, 0.260, 0.370 | 0.370×1 + 0.260×0 + 0.370×1 = 0.740 |
| Step 2f-3:Head 2 独立做注意力(只看第2维) | ||||
| Q (query) | K (key) | Q·K (标量) | Softmax 权重 | 加权 V |
|---|---|---|---|---|
| 我: 0 | 我:0 / 爱:1 / AI:1 | 0, 0, 0 | 0.333, 0.333, 0.333 | 0.333×0 + 0.333×1 + 0.333×1 = 0.667 |
| 爱: 1 | 我:0 / 爱:1 / AI:1 | 0, 1, 1 | 0.212, 0.394, 0.394 | 0.212×0 + 0.394×1 + 0.394×1 = 0.788 |
| AI: 1 | 我:0 / 爱:1 / AI:1 | 0, 1, 1 | 0.212, 0.394, 0.394 | 0.212×0 + 0.394×1 + 0.394×1 = 0.788 |
| Step 2f-4:拼接 + 线性变换 | |||
| 词 | Head 1 输出 | Head 2 输出 | Concat 后 |
|---|---|---|---|
| 我 | 0.740 | 0.667 | [0.740, 0.667] |
| 爱 | 0.667 | 0.788 | [0.667, 0.788] |
| AI | 0.740 | 0.788 | [0.740, 0.788] |
最后通过一个线性矩阵 Wo 做变换,整合所有头的信息:
每个头关注了不同的维度模式,拼接后模型能同时捕获多种关系。
Transformer 完整结构
自注意力只是 Transformer 的一个组件。完整的 Transformer 结构如下:
Transformer 没有循环结构,需要额外注入位置信息。用正弦/余弦函数生成位置向量加到词嵌入上。
把 Q/K/V 拆成多个"头",各自独立做注意力,再拼接。就像同时从不同角度理解句子。
两层 MLP + ReLU/GELU,对注意力输出做非线性变换。就是我们上一章学的 MLP!
每个子层都有残差连接和层归一化,保证梯度流通和训练稳定性。
PyTorch 实现
用 PyTorch 实现自注意力机制。
import torch
import torch.nn as nn
import math
class SelfAttention(nn.Module):
def __init__(self, d_model=2):
super().__init__()
self.d_model = d_model
# Q, K, V 的线性变换
self.Wq = nn.Linear(d_model, d_model, bias=False)
self.Wk = nn.Linear(d_model, d_model, bias=False)
self.Wv = nn.Linear(d_model, d_model, bias=False)
def forward(self, x):
# x: (seq_len, d_model)
Q = self.Wq(x) # (seq_len, d_model)
K = self.Wk(x) # (seq_len, d_model)
V = self.Wv(x) # (seq_len, d_model)
# 计算注意力分数
scores = torch.matmul(Q, K.T) / math.sqrt(self.d_model)
# Softmax 归一化
attn_weights = torch.softmax(scores, dim=-1)
# 加权求和
output = torch.matmul(attn_weights, V)
return output, attn_weights
# 手动设置为单位矩阵,复现手算结果
model = SelfAttention(d_model=2)
model.Wq.weight.data = torch.eye(2)
model.Wk.weight.data = torch.eye(2)
model.Wv.weight.data = torch.eye(2)
# 输入: "我 爱 AI"
x = torch.tensor([
[1.0, 0.0], # 我
[0.0, 1.0], # 爱
[1.0, 1.0], # AI
])
output, weights = model(x)
print("注意力权重:")
print(weights)
print("输出:")
print(output)
📝 总结
自注意力的完整流程
为什么 Transformer 革命性?
抛弃了 RNN 的顺序处理,所有位置可以并行计算,训练速度快几十倍。
无处不在的架构
GPT、BERT、ViT、DALL-E、Whisper… 几乎所有 SOTA 模型都基于 Transformer。
MLP 是它的组成部分
Transformer 的 FFN 层就是两层 MLP。学好 MLP → 理解 Transformer 的一半。
下一步
理解了自注意力,就可以探索多头注意力、位置编码、Transformer 完整训练流程。
扩展阅读:Mamba 与状态空间模型
Transformer 并不是序列建模的唯一选择。Mamba(2023)基于状态空间模型(State Space Model, SSM),提供了一种全新的序列建模范式。
SSM 的核心思想来源于控制论:用一个隐藏状态来压缩历史信息,每个时间步根据输入更新状态并产生输出。Mamba 的创新在于让更新参数依赖于输入本身("选择性"),从而实现了类似注意力的内容感知能力。
Transformer vs Mamba 对比
| 特性 | Transformer | Mamba |
|---|---|---|
| 核心机制 | 注意力机制 (Attention) | 选择性 SSM (Selective SSM) |
| 时间复杂度 | O(n²) | O(n) |
| 长序列处理 | 有瓶颈(显存随长度平方增长) | 擅长(线性增长) |
| 并行训练 | 完全并行 | 完全并行 |
| 推理速度 | 需要缓存 KV(显存占用大) | 线性扫描(固定状态大小) |
| 全局信息 | 任意位置直接交互 | 通过状态间接传递 |
| 代表模型 | GPT、BERT、ViT | Mamba、Mamba-2、Vision Mamba |
Mamba 不是要取代 Transformer,而是为不同场景提供了新选择。实践中两者各有优势,甚至可以组合使用。
小测验
1. Q 和 K 的点积代表什么?
2. 为什么要除以 √d?
3. Multi-Head Attention 的作用是什么?
4. Transformer 相比 RNN 的最大优势是什么?