MQA(Multi-Query Attention) 是一种对标准多头注意力的改进,它让所有注意力头共享同一份键(K)和值(V),而只保留查询(Q)是各自独立的。
流程
输入表示
对于序列中第 i 个位置的输入向量 \mathbf{x}_i,我们计算:
- 查询向量(每个头独立):
\mathbf{q}_i^{(s)} = \mathbf{x}_i \mathbf{W}_q^{(s)} \quad (s=1,\dots,h)
- 键向量(所有头共享):
\mathbf{k}_i = \mathbf{x}_i \mathbf{W}_k
- 值向量(所有头共享):
\mathbf{v}_i = \mathbf{x}_i \mathbf{W}_v
参数含义
- i:输入序列中的位置索引,取值范围为 1 到序列长度 L,对应每个位置的词或特征向量 \mathbf{x}_i。在自注意力中,每个位置会与序列所有位置进行交互。
- s:注意力头的编号,取值范围为 1 到总头数 h。每个注意力头学习不同的表示子空间,用于计算查询向量 \mathbf{q}_i^{(s)}。键向量 \mathbf{k}_i 和值向量 \mathbf{v}_i 在原文中为所有头共享,不随 s 变化。
- h:注意力头的总数,是多头注意力机制的超参数(常用如 8、12、16)。每个头使用独立的查询变换矩阵 \mathbf{W}_q^{(s)},而键/值变换矩阵 \mathbf{W}_k, \mathbf{W}_v 在所有头间共享(与标准 Transformer 不同)。所有头的输出会拼接或聚合为该位置的完整表示。
注意力计算
注意力计算(对每个头 s):
在解码的第 t 步,第 s 个头的输出 \mathbf{o}_t^{(s)}
是通过将当前查询 \mathbf{q}_t^{(s)}
与之前所有位置的共享键 \mathbf{k}_{1},\dots,\mathbf{k}_t
做点积,得到注意力权重,再对共享值 \mathbf{v}_{1},\dots,\mathbf{v}_t
加权求和:
\mathbf{o}_t^{(s)} = \frac{\sum_{i=1}^{t} \exp\left(
\mathbf{q}_t^{(s)} \cdot \mathbf{k}_i^\top \right)
\mathbf{v}_i}{\sum_{i=1}^{t} \exp\left( \mathbf{q}_t^{(s)}
\cdot \mathbf{k}_i^\top \right)}
最终输出
将所有 h 个头的输出向量拼接起来,得到第 t 步的注意力输出: \mathbf{o}_t = \left[ \mathbf{o}_t^{(1)}, \mathbf{o}_t^{(2)}, \dots, \mathbf{o}_t^{(h)} \right]
这样做的优势:因为 K 和 V 的投影矩阵被所有头共享,模型在推理时需要缓存的数据量大大减少(只需缓存一份 K 和 V),从而显著节省内存并提高推理速度,同时通常能保持与标准多头注意力相近的模型效果。