共计 1984 个字符,预计需要花费 5 分钟才能阅读完成。
背景介绍
自注意力机制是 Transformer 架构的核心,它让模型能够动态地关注输入序列的不同部分。在 NLP 任务中,这种机制特别有用,因为它可以捕捉长距离的依赖关系,而不像 RNN 那样受限于序列长度。自注意力机制广泛应用于机器翻译、文本摘要、问答系统等场景。

数学原理
QKV 矩阵
自注意力机制的核心是 Q(Query)、K(Key)、V(Value) 三个矩阵。可以这样理解:
- Query:当前正在处理的 token 的表示
- Key:所有 token 的表示,用于计算相关性
- Value:实际用于生成输出的 token 表示
缩放点积注意力
计算注意力的步骤如下:
- 计算 Q 和 K 的点积,得到注意力分数
- 对分数进行缩放(除以√d_k,d_k 是 key 的维度)
- 应用 softmax 函数得到注意力权重
- 用权重对 V 进行加权求和
c3tr 模块实现
import torch
import torch.nn as nn
class MultiHeadAttention(nn.Module):
def __init__(self, d_model, num_heads):
super().__init__()
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 forward(self, x):
batch_size = x.size(0)
# 线性变换
Q = self.W_q(x)
K = self.W_k(x)
V = self.W_v(x)
# 分割成多头
Q = Q.view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
K = K.view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
V = V.view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
# 计算缩放点积注意力
scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.d_k))
attn_weights = torch.softmax(scores, dim=-1)
output = torch.matmul(attn_weights, V)
# 合并多头
output = output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
# 最终线性变换
return self.W_o(output)
多头机制解析
多头注意力的主要优势在于:
- 允许模型同时关注不同位置的不同表示子空间
- 增强了模型的表示能力
- 类似于 CNN 中的多通道概念
实现多头注意力的关键步骤:
- 将 Q、K、V 矩阵分割成多个头
- 对每个头分别计算注意力
- 将结果拼接起来
- 通过线性变换得到最终输出
性能考量
多头自注意力机制的主要性能影响因素:
- 计算复杂度:O(n²d),其中 n 是序列长度,d 是模型维度
- 内存占用:需要存储中间注意力分数矩阵
- 并行计算:可以充分利用 GPU 并行计算优势
优化建议:
- 对于长序列,可以考虑稀疏注意力或局部注意力
- 合理设置头数(通常 4 - 8 个)
- 使用混合精度训练减少内存占用
避坑指南
常见错误 1:维度不匹配
错误:在分割多头时维度计算错误
解决方案:确保 d_model 能被 num_heads 整除
常见错误 2:注意力分数过大
错误:未进行缩放导致 softmax 梯度消失
解决方案:始终记得除以√d_k
常见错误 3:未正确 mask
错误:在解码器未正确应用未来位置 mask
解决方案:使用 triu 函数生成 mask 矩阵
常见错误 4:内存溢出
错误:长序列导致内存不足
解决方案:使用 checkpointing 或减小 batch size
常见错误 5:初始化不当
错误:线性变换层初始化不当导致训练困难
解决方案:使用 xavier_uniform_或 xavier_normal_初始化
思考题
- 多头注意力中,不同头学习到的注意力模式有什么差异?如何可视化这些差异?
- 当序列长度非常大时(如 10000),如何改进多头注意力机制使其更高效?
- 在跨模态任务(如图文匹配)中,如何设计多头注意力机制?
多头自注意力机制是 Transformer 架构中最精妙的设计之一。通过本文的学习,你应该已经掌握了它的核心原理和实现细节。建议在理解本文内容的基础上,尝试在自己的项目中实现一个简单的多头注意力模块,这会帮助你更好地掌握这一重要技术。
正文完
发表至: 深度学习
近一天内
