多头注意力
多头注意力在多个投影子空间并行建立关系并合并回模型维度。
学习目标
- 两头注意力核对分数与输出形状
- 头数加倍会让输出维度加倍吗?
- 说明:多头提供不同子空间的容量,但各头不保证分工,也不应把权重直接解读为因果解释。
为什么需要这个概念
多头注意力对 Q、K、V 做可学习投影,按 head 拆分后分别计算缩放点积注意力,再拼接各头并执行输出投影。
学习前需要掌握
背景与问题
单个注意力分布只能用一套投影衡量位置关系。多头注意力把表示投影到多个子空间,让不同关系能够并行形成再被融合。
概念定义
多头注意力对 Q、K、V 做可学习投影,按 head 拆分后分别计算缩放点积注意力,再拼接各头并执行输出投影。
直观理解
同一段文字交给多组不同观察角度,每组产生自己的信息汇总,再把结果一起整合。观察角度由训练学出,不保证自然对应可命名语法规则。
核心原理
若总维度 D、头数 H,每头常取 d_h=D/H,所以 D 必须能被 H 整除。分数张量典型形状为 ,softmax 在 key 轴归一化;输出合并回 。
每头的输入来自投影,不是简单把原始 token 切成互不关联的几段;完整 Q、K、V 线性投影通常先混合特征。缩放使用每头 d_h 的平方根,避免高维点积量级过大。
PyTorch MultiheadAttention 默认返回跨头平均权重;要检查每头应设置 average_attn_weights=False。注意力权重是计算中的混合系数,不能单独当作模型解释或因果贡献。
数学表达
核心公式
多头注意力对 Q、K、V 做可学习投影,按 head 拆分后分别计算缩放点积注意力,再拼接各头并执行输出投影。
变量含义
Nbatch sizeD/H特征或隐藏维度
计算步骤
- 1每头产生 3×3 的 query-key 权重。
- 2返回未平均的权重 shape 为 (2,2,3,3)。
- 3拼接两头后输出仍为 (2,3,8)。
代码对应位置
示例 1两头注意力核对分数与输出形状的最小验证:使用完整构造输入核对两头注意力核对分数与输出形状,输出只表示本例计算。
变量解释
| 变量 | 含义 |
|---|---|
N | batch size |
D/H | 特征或隐藏维度 |
完整数值示例
两头注意力核对分数与输出形状
已知条件
- N=2,L=3,D=8,H=2
- 每头维度为 4
计算步骤
- 每头产生 3×3 的 query-key 权重。
- 返回未平均的权重 shape 为 (2,2,3,3)。
- 拼接两头后输出仍为 (2,3,8)。
计算结果
每个 query 在每个头上的 key 权重和约为 1。
处理前后对比
- 多头提供不同子空间的容量,但各头不保证分工,也不应把权重直接解读为因果解释。
两头注意力核对分数与输出形状
若只打印默认权重,会看到 (2,3,3),容易误以为网络只有一个头。该形状是平均后的结果,计算中仍有两个独立分布。
示例关闭 dropout 并评估,检查归一化性质。训练时若对权重施加 dropout,单次返回的注意力行和可能不再严格为 1,不能把这一检查不加条件用于所有模式。
计算与实现步骤
- 每头产生 3×3 的 query-key 权重。
- 返回未平均的权重 shape 为 (2,2,3,3)。
- 拼接两头后输出仍为 (2,3,8)。
代码实现
示例 1
两头注意力核对分数与输出形状的最小验证
example_01.py用途:使用完整构造输入核对两头注意力核对分数与输出形状,输出只表示本例计算。
import torch
from torch import nn
torch.manual_seed(7)
mha = nn.MultiheadAttention(8, 2, dropout=0., batch_first=True)
mha.eval()
x = torch.zeros(2, 3, 8)
with torch.inference_mode():
y, weights = mha(x, x, x, average_attn_weights=False)
print("output:", tuple(y.shape), "weights:", tuple(weights.shape))
print("rows sum to one:", bool(torch.allclose(weights.sum(-1), torch.ones(2, 2, 3))))代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
使用完整构造输入核对两头注意力核对分数与输出形状,输出只表示本例计算。
y- 目标标签或连续目标值。
Step 1 · 1–10 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import torch
from torch import nn
torch.manual_seed(7)
mha = nn.MultiheadAttention(8, 2, dropout=0., batch_first=True)
mha.eval()
x = torch.zeros(2, 3, 8)
with torch.inference_mode():
y, weights = mha(x, x, x, average_attn_weights=False)
print("output:", tuple(y.shape), "weights:", tuple(weights.shape))
print("rows sum to one:", bool(torch.allclose(weights.sum(-1), torch.ones(2, 2, 3))))预期输出或运行结果
output: (2, 3, 8) weights: (2, 2, 3, 3) rows sum to one: True
常见错误 · 4 条
- D 不能整除头数
- 换轴后错误 view
- 把头解释为固定语法
- 确认样本轴、特征轴以及 X 与 y 的第一维完全对应。
实际应用
- 自注意力与交叉注意力
- 核对注意力头与权重张量
常见错误
- D 不能整除头数
- 换轴后错误 view
- 把头解释为固定语法
常见问题
头数加倍会让输出维度加倍吗?
若保持总维度 D 不变,通常每头维度相应减半,拼接后仍是 D;头数和总维度应分别理解。
这个示例能说明什么边界?
多头提供不同子空间的容量,但各头不保证分工,也不应把权重直接解读为因果解释。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。