1. Transformer基础:从自注意力机制到完整模型实现
在深度学习领域,Transformer架构已经成为自然语言处理任务的事实标准。理解Transformer的核心在于掌握其自注意力机制的工作原理,这是它与传统RNN/LSTM架构最本质的区别。让我们从一个简单的自注意力函数开始,逐步拆解Transformer的各个关键组件。
1.1 自注意力机制的核心实现
自注意力机制的核心数学表达可以用以下Python函数表示:
python复制import torch
import math
def attention(query, key, value, dropout=None):
"""
缩放点积注意力实现
参数:
query: 查询矩阵 [batch_size, seq_len, d_k]
key: 键矩阵 [batch_size, seq_len, d_k]
value: 值矩阵 [batch_size, seq_len, d_v]
dropout: 可选的dropout层
返回:
加权后的value和注意力权重
"""
d_k = query.size(-1) # 获取query的最后一个维度大小
# 计算注意力分数
scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)
# 应用softmax得到注意力权重
p_attn = scores.softmax(dim=-1)
if dropout is not None:
p_attn = dropout(p_attn)
# 加权求和
return torch.matmul(p_attn, value), p_attn
这个看似简单的函数实际上包含了自注意力机制的三个关键步骤:
- 分数计算:通过query和key的点积计算相关性分数,除以√d_k进行缩放(防止梯度消失)
- 权重归一化:使用softmax将分数转换为概率分布
- 加权求和:用注意力权重对value进行加权组合
提示:为什么需要除以√d_k?当维度d_k较大时,点积的结果会变得非常大,导致softmax的梯度变得极小(接近0或1)。缩放操作保持了梯度的稳定性,使模型更容易训练。
1.1.1 加权求和的直观理解
让我们通过一个具体的例子来理解矩阵相乘如何实现加权求和:
python复制# 注意力权重矩阵 [2,3] - 2个query对3个key的注意力分布
p_attn_2d = torch.tensor([[0.1, 0.7, 0.2], [0.8, 0.1, 0.1]])
# 值矩阵 [3,4] - 3个key对应的4维value向量
value_2d = torch.tensor([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# 加权求和
output_2d = torch.matmul(p_attn_2d, value_2d)
"""
计算结果:
tensor([[5.0, 6.0, 7.0, 8.0], # 0.1*[1,2,3,4] + 0.7*[5,6,7,8] + 0.2*[9,10,11,12]
[2.2, 3.2, 4.2, 5.2]]) # 0.8*[1,2,3,4] + 0.1*[5,6,7,8] + 0.1*[9,10,11,12]
"""
这个例子清晰地展示了注意力机制的本质:每个query位置的输出是所有value向量的加权组合,权重由query与key的相似度决定。第一个query的输出更接近第二个value(权重0.7),而第二个query的输出更接近第一个value(权重0.8)。
1.2 注意力机制在Transformer中的应用
在Transformer架构中,注意力机制有三种主要应用场景:
- Encoder自注意力:query、key、value都来自同一输入序列,用于捕捉序列内部的关系
- Decoder掩码自注意力:query、key、value来自目标序列,但使用掩码防止看到未来信息
- Encoder-Decoder注意力:query来自目标序列,key和value来自编码器输出,用于连接源语言和目标语言信息
1.2.1 Encoder-Decoder注意力的物理意义
在机器翻译等seq2seq任务中,Encoder-Decoder注意力的三个矩阵有着明确的语义:
- Q(来自Decoder):代表"当前已生成的目标序列信息",即翻译到当前位置时已知的目标语言上下
