Self-Attention 怎么计算:从 Q/K/V 到注意力输出
按一个完整的计算流程理解 Self-Attention:输入向量如何映射成 Q、K、V,如何得到注意力权重,以及最后怎样汇总成新的表示。
相关工具
先把一整套计算看成七个步骤
上一篇介绍了 Attention 的含义:当前位置根据相关性,从其他位置取回一部分信息。Self-Attention 的计算并不神秘,它可以拆成一条固定流程:准备输入向量,生成 Q、K、V,计算 Q 与 K 的相关性,进行缩放和 Softmax,再用权重对 V 加权求和,得到输出表示。
这里的“每个位置”可以是一句话中的一个词,也可以是分词后的一个 Token。假设序列有 n 个位置,每个位置的输入向量维度是 d_model,那么输入可以看成一个 n × d_model 的矩阵。模型会让整行输入一起参与计算,而不是单独处理某一个词。
Transformer 相关概念 采用先给出整体结构、再进入向量和矩阵计算的讲法。这样安排很有必要:如果一开始就写公式,很容易只记住符号,却不知道这些矩阵在解决什么问题。先记住目标:为每个位置生成一个融入上下文的新表示。

从输入向量开始,经过线性映射、相关性计算、Softmax 和加权求和,得到上下文感知的输出。
输入向量怎样变成 Q、K、V
设输入矩阵为 X,模型会准备三组可学习的参数矩阵 W_Q、W_K 和 W_V。通过矩阵乘法,可以得到 Q = XW_Q、K = XW_K、V = XW_V。三组结果来自同一份输入,但维度和作用可以不同。
如果 X 的形状是 n × d_model,Q 和 K 的最后一维通常是 d_k,V 的最后一维通常是 d_v。那么 Q 的形状是 n × d_k,K 的形状是 n × d_k,V 的形状是 n × d_v。每一行对应序列中的一个位置。
为什么不直接使用原始输入向量比较?因为三组线性映射让模型可以学习不同的表示空间:一组更适合提出查询,一组更适合提供可匹配线索,另一组更适合承载最终要汇总的信息。参数通过训练获得,不是人工为每个词写好的规则。
Q 和 K 的点积会生成一行分数
假设现在要计算第 i 个位置的输出。它对应的 Query 会和所有位置的 Key 做点积,得到一行分数。这个分数表达的是:第 i 个位置和每个位置有多匹配。分数越大,后续通常会分配到更高的注意力权重。
把所有位置的 Query 都算一遍,就得到一个 n × n 的相关性矩阵。矩阵的第 i 行表示第 i 个查询位置,第 j 列表示它对第 j 个 Key 位置的相关性。对角线位置表示关注自己,其他位置表示参考上下文。
分数不是概率,也不要求总和为 1。它可以是正数,也可以是负数,大小主要用来比较不同位置的相对关系。只有经过 Softmax 后,才会变成可以用于加权求和的权重。
为什么是 QKᵀ,而不是 QK
Q 的形状是 n × d_k,K 的形状也是 n × d_k。为了让每个 Query 都能和每个 Key 比较,需要把 K 转置成 d_k × n。这样 QKᵀ 的结果就是 n × n,刚好得到“查询位置 × 被查询位置”的相关性矩阵。
可以把它理解成一张表:行记录“谁在问”,列记录“问谁”。如果只计算同位置的向量相乘,就只能得到一条对角线,无法让当前词参考整句话。矩阵乘法的结构,正好一次性完成了所有位置之间的两两比较。
这也是 Transformer 适合并行计算的重要原因之一。只要输入矩阵准备好,多个查询位置的比较可以通过一次矩阵运算完成,不需要等待前一个时间步把隐藏状态传过来。
缩放是为了让分数保持在可训练的范围
当 d_k 较大时,Q 和 K 的点积可能出现较大的绝对值。分数一旦过大,Softmax 很容易变得过于尖锐,导致某些位置几乎拿到全部权重,其他位置几乎没有梯度。
因此,计算相关性矩阵后通常要除以 √d_k。完整的分数可以写成 S = QKᵀ / √d_k。缩放不会改变分数的相对排序,却能缓和数值范围,让后续归一化更稳定。
这一步不是为了让结果更“准确”,而是为了让训练过程更容易进行。模型最终能否学到合适的关系,还取决于数据、目标函数、参数初始化和训练过程。
Softmax 是按行处理的
对相关性矩阵 S 使用 Softmax 时,通常是对每一行进行归一化。第 i 行代表第 i 个 Query 对所有 Key 的关注分布,归一化后这一行的权重总和为 1。
以“学习”这个位置为例,它会得到一行分数,分别对应“我”“喜欢”“学习”“语言”等位置。Softmax 把这行分数变成一组权重,可能更偏向“喜欢”和“语言”,也可能根据训练结果形成其他分布。
注意力权重是相对关系,不是绝对意义上的重要性排名。换一个输入句子、换一层模型或换一个注意力头,分布都可能变化。我们要关注的是它如何参与下一步的信息汇总。

每一行对应一个查询位置,Softmax 后得到该位置对所有 Key 的注意力权重,行和为 1。
权重怎样作用到 V
得到注意力权重矩阵 A 后,最后一步是计算 O = AV。A 的每一行告诉模型,当前 Query 应该从每个 Value 位置取多少信息;V 的每一行则是对应位置真正要被汇总的内容。
对于某个位置 i,输出就是这一行权重和所有 Value 向量的加权求和。权重高的位置贡献更大,权重低的位置贡献更小。输出仍然是一个向量,但它已经不只是当前词的原始表示,而是带上了上下文信息。
这一步也解释了为什么 Q 和 K 负责计算关系,而 V 负责传递内容。一个位置可能在匹配时很重要,但最终传递的向量仍然由 V 的表示决定。把“判断关注谁”和“取回什么信息”分成两个角色,模型的表达空间更灵活。

以“学习”为查询位置,展示点积、缩放、Softmax 和权重乘 V 的完整过程。
为什么输出还要经过后续网络
Self-Attention 输出的是结合上下文后的表示,但 Transformer 不会在这里结束。输出通常还会经过残差连接、归一化和位置前馈网络,然后再进入下一层编码器或解码器。多层堆叠后,模型可以逐步形成更复杂的关系表示。
注意力擅长让位置之间交换信息,前馈网络则对每个位置进行独立的非线性变换。两者分工不同:前者负责“我应该参考谁”,后者负责“拿到这些信息后怎样变换”。
残差连接让当前层保留输入信息,归一化帮助不同层的数值保持稳定。理解这些结构时,不要把它们看成 Attention 的一部分公式,而要看成围绕注意力计算搭起来的稳定训练组件。
一个小例子怎样帮助检查理解
学习计算流程时,可以只取四个位置、很小的向量维度,手工完成一行计算:先为“学习”生成 Q,再和四个 K 做点积;将分数除以 √d_k;对结果做 Softmax;最后用四个权重分别乘四个 V,再相加。
手工例子不需要追求和真实模型完全一致,它的作用是检查形状和顺序。Q 与 K 点积后应该得到四个分数,Softmax 后应该得到四个总和为 1 的权重,加权 V 后得到一个与 V 维度相同的输出向量。
如果维度对不上,通常是矩阵转置或乘法顺序出了问题;如果权重和不是 1,通常是 Softmax 方向理解错了;如果输出维度不对,通常是把 Q/K 的维度和 V 的维度混在了一起。
Self-Attention 的计算链要这样复述
可以把完整过程压缩成一句话:输入序列先通过三组线性变换得到 Q、K、V;Q 和 K 的转置计算相关性并进行缩放;Softmax 把每个查询位置的分数变成权重;权重再对 V 加权求和,得到融合上下文的新表示。
如果再补充一句,就是这些位置可以在训练阶段一起计算,而不是严格按照时间步等待。它的计算成本会随着序列长度增加,但信息交互路径比单纯顺序传递更直接。
下一步学习多头注意力时,可以把它理解成多组独立的 Q/K/V 投影。每一组可能学习不同的关系,最后再把多组结果拼接并变换。先把单头 Self-Attention 的计算链弄清楚,多头就不会只剩下一个名词。
确认 X、Q、K、V、分数矩阵和输出矩阵的行列含义。
确认 Q 与 Kᵀ 的点积得到每个查询位置的相关性分数。
确认缩放后按行 Softmax,并且每行权重总和为 1。
确认权重乘 V 后得到与 V 维度一致的上下文表示。
常见问题
Self-Attention 的输出为什么还要和 V 相乘?
Q 和 K 的作用是计算相关性和关注权重,V 承载真正要汇总的内容。权重乘 V,才能把不同位置的信息按关注程度组合成输出。
注意力矩阵的每一行和每一列分别表示什么?
每一行代表一个 Query 查询位置,每一列代表一个 Key 被查询位置。对每一行做 Softmax 后,该行表示当前查询位置对所有位置的注意力分布。
为什么要把 K 转置?
Q 的形状通常是 n×d,K 的形状也是 n×d。把 K 转置成 d×n 后,QKᵀ 才能得到 n×n 的位置关系矩阵。