“我吃了一个苹果”和“这台电脑来自苹果”,两处“苹果”需要结合不同上下文理解。第03章已经指出:如果相同token只查出相同向量,再各自经过同一个逐行变换,周围文字根本没有参与,它们便无法因此获得不同的上下文表示。
我们需要一种让位置之间交换信息的机制。Attention做的一件核心工作,就是让当前位置根据输入,决定从其他可见位置读取多少信息,再把读到的内容组合起来。这里的“注意”是数学运算的名字,不表示模型具有人的主观注意力。
先固定三件事:本章推理时不更新参数,只改变输入;用一个头算清楚;先允许全部位置可见,再单独加因果限制。这样,当结果变化时,我们能追到究竟是匹配份额、取回内容,还是可见范围变了。
1.把“找什么”和“取什么”分开
想象你在一叠通知中找会议地点。查找条件、用来匹配的标签、取回的内容,承担不同角色。Attention也分出三组向量,通常简称Q、K、V。
Q叫查询,表示当前位置拿什么去匹配;K叫键,表示各位置提供什么供匹配;V叫值,是最后真正被加权组合的内容。它们都是数字向量,不必能翻译成一句清晰的人话。Transformer原论文:Attention定义
在自注意力中,三者来自同一组位置表示,但通过不同参数矩阵得到。若输入矩阵叫X,使用第03章的横排约定,可以写成Q=XW_Q、K=XW_K、V=XW_V。下标只是区分用途,不需要额外数学知识。
三张W是训练得到的参数;Q、K、V是本次输入经过它们算出的中间结果。输入改变,三组结果可以改变,而参数不必改变。“同一个token这次更关注前文”,并不等于它临时重新训练了。
这些投影也接得上上一章的训练过程:最终损失的信号沿加权组合、softmax和点积往回传,再到投影参数。通常不需要人给每一个位置标注“应该注意哪个词”,但学到的读取方式是否有用,仍取决于数据和训练目标。每个头的一组参数通常跨位置共用,并非遇到新位置就新建一张权重表。
查询和键为何不直接共用同一个向量?分开变换,可以让“想找的信息”和“提供的匹配线索”使用不同组合。一个位置读取另一个位置,也不要求反向读取同样强。这和两组向量之间对称的几何相似度,并不是完全一样的问题。
2.用三处输入造一个能算完的单头
我们只放三个token位置,每个位置有两个数。这里不把它们强行绑定为真实汉字的向量:位置1为[1,0],位置2为[0,1],位置3为[1,1]。叠起来,X就是3行2列。
所有数字和矩阵都为教学手填,暂时省略位置编码、偏置和其他模块。设c=√2×ln 2,约为0.9803。ln 2在第04章出现过,指数运算后正好得到2;选择这个数只是为了稍后算出整齐的份额。
安排三张2×2矩阵:W_Q两行分别是[1,0]和[0,1];W_K两行是[c,0]和[0,c];W_V两行是[2,0]和[0,1]。
逐行乘上去,得到:
- Q的三行:[1,0]、[0,1]、[1,1]
- K的三行:[c,0]、[0,c]、[c,c]
- V的三行:[2,0]、[0,1]、[2,1]
例如位置3的输入[1,1]乘W_V,第一项为1×2+1×0=2,第二项为1×0+1×1=1,所以v₃=[2,1]。W_Q碰巧保持原值,也只是本例选择;真实模型的查询投影不必是这样的单位矩阵。
现在有了三份不同用途的表示。接下来不是把Q、K、V相加,而是先用Q和K决定V各占多少。
3.先匹配,再把分数变成份额
先只看位置3。它拿查询q₃=[1,1],分别与三个键做点积。逐项相乘再相加,分数依次是c、c、2c。
标准缩放点积注意力还会除以查询与键的维数的平方根。这里每个有2项,所以除以√2,分数变成[ln 2,ln 2,2 ln 2]。PyTorch:缩放点积注意力定义
维度较大时,点积的典型尺度可能随之变大,softmax容易变得过分集中。这个缩放用于控制尺度,不是在证明分数有多可信。它也不是第03章的余弦归一化,没有把每个向量都除以自己的长度。
为什么除以√d,而不是d?作一个有条件的尺度分析:假设Q、K的各个坐标彼此独立、均值为0、方差为1,那么d个乘积相加的方差是d,标准差是√d。d从1增到4、16,典型幅度便从1增到2、4;除以√d,把这种增长抵消。训练后的向量不保证始终满足这些假设,这解释的是缩放的设计动机。原论文第3.2.1节与脚注
再做softmax:指数后得到[2,2,4],总和是8;分别除以8,得到[1/4,1/4,1/2]。这就是位置3这一次读取的权重。
这里的分母只汇总当前查询允许读取的那些位置。不是把整张注意力矩阵所有格子一起归一化,也不是按列归一化。每个查询都分别形成总和为1的一行份额。
这些数和第04章的输出概率有相似的计算形式,却有不同用途。那里分配的是词表候选的下一token概率;这里分配的是读取位置的权重。位置3占一半,不能解释成“它有一半概率是正确答案”。
4.按份额组合内容,得到新的表示
权重准备好后,拿的是V,不是K。位置3的输出为:
o₃=1/4×[2,0]+1/4×[0,1]+1/2×[2,1]=[1.5,0.75]。
第一项是0.5+0+1=1.5;第二项是0+0.25+0.5=0.75。结果仍是两个数,但已经混合了三个位置提供的信息。
完整地算另外两行,也能得到:位置1的缩放分数为[ln 2,0,ln 2],权重为[2/5,1/5,2/5],输出[1.6,0.6];位置2的分数为[0,ln 2,ln 2],权重为[1/5,2/5,2/5],输出[1.2,0.8]。
这一步仍有信息压缩:三个值向量合成一个结果,并没有把三个位置的完整原样副本都装进去。在这个没有其他变换的单头里,份额非负、总和为1,每个输出坐标都处在各个值的对应坐标范围内。随后若加上输出投影、残差等运算,就不能把这个范围限制直接套到整个网络。
所以这一步输入3×2,输出仍是3×2。中间的匹配表却是3×3:每一行对应一个查询,每一列对应一个被读取位置。尺寸没变,不代表信息没变;原来的逐行变换,现在接上了跨位置的读取。
先看图1上半部分:Q和K在匹配处合流,V沿另一条路到加权求和。图下半部分把位置3的每个权重与对应V对齐,便于核对每一次乘法。

图1|X分三路得到Q、K、V;Q、K决定读取权重,V提供混合内容。形状分别为3×2、3×3、3×2。数值展开只追踪q₃这一行,暂不加mask,省略位置机制与输出投影。
做一次上下文改动:保持位置3和全部W不变,只把位置2改成[0,2]。位置2的键变成[0,2c],值变成[0,2]。位置3的分数于是变成[ln 2,2 ln 2,2 ln 2],权重成为[1/5,2/5,2/5],新输出为[1.2,1.2]。
还有一个值得注意的变化:虽然三张投影矩阵都只做线性变换,整个Attention却不是固定线性混合。权重经过softmax,而且会随着输入改变;换一个上下文,混合规则本身也跟着变。这正是它与“给所有位置永远取相同比例”之间的重要区别。
当前位置的原始输入没有变化,读到的上下文变了,最终表示就变了。这次同时改变了另一个位置的键和值,不能把全部变化只归因于“权重增加”。这也是分析真实模型时要分开观察的两条路径。
还可以拆开做受控检查。在计算得到K、V之后,只替换k₂而保留原V,输出是[1.2,0.8];只替换v₂而保留原权重,输出是[1.5,1.0]。两条路一起改,才是上面的[1.2,1.2]。这两次内部替换是用于分析依赖的人工干预,不是说原始输入变化时K、V会自然独立。

图2|固定q₃与全部参数,对照原例、只换K、只换V、两路都换。四种结果共同说明:权重与内容是不同的因果路径,不能只看权重就解释输出改动。
5.因果掩码怎样防止偷看答案
目前我们允许三个位置互相读取。如果要逐个预测后续token,位置2就不能利用尚未出现的位置3。训练时即使整段正确文本已经放在机器里,也要限制这一条信息路径。
因果掩码,也叫causal mask,为每个查询规定可见范围。在本例中,位置1只看1;位置2看1、2;位置3看1、2、3。允许看到自己,是因为这里的表示对应已经给出的当前位置,它可以用来预测下一个位置。Transformer原论文:解码器可见范围
回到未修改输入的例子。位置2原本的分数为[0,ln 2,ln 2]。mask把第三项排除,常在数学上写成负无穷,使其指数值为0。指数后的三个数成为[1,2,0],重新归一化,权重就是[1/3,2/3,0]。
它的输出随之变为1/3×[2,0]+2/3×[0,1]=[2/3,2/3]。不能先保留原来的[1/5,2/5,2/5],只把第三项划掉就结束;那样剩下的份额没有重新分配。

图3|行是查询位置,列是被读取位置。因果mask保留对角线与左下部分;位置2先把第三项排除,再对剩余指数值1、2归一化,得到1/3、2/3、0。
遮住未来,是限制信息从哪来,并不是让训练必须一个位置一个位置串行计算。只要每一层都遵守掩码,就能同时算许多已知训练位置,而不把未来内容泄漏进去。实际生成还没有未来token,依然要逐步得到它们。
另外,补齐长度用的空白位置也可能需要遮挡,但它与“未来不可见”是不同理由的mask。后面SFT中的损失mask又是另一件事:它决定哪些位置参与评分,不直接代替这里的信息访问限制。
6.多头让同一位置有多种读取方式
一个头只给出一组匹配和汇总。假如某项任务同时需要追踪时间、对象和条件,把信息一次混合,未必是最方便的表示。因此可以并行使用多组查询、键、值投影,分别计算注意力,再合并结果,这就是多头注意力。
用一个仅说明尺寸的例子:两个头各为三个位置输出两个数,分别得到3×2的结果;按每个位置拼接,成为3×4;再乘一张4×2的输出矩阵W_O,回到3×2。PyTorch:多头注意力的拼接与输出投影
拼接不是投票,也不等于直接平均。输出投影可以继续学习怎样组合不同头的结果。各头可能学出不同的读取模式,但我们不能未经检验就给它们分配“语法头”“常识头”“逻辑头”等固定职责。
这个例子让两头各有二维,便于追踪。真实设计常在固定总宽度下把通道分配给多个头,因此头数增加不等于把完整模型复制更多份,也不保证能力随头数单调提高。
自注意力的“自”,说的是Q、K、V来自同一组序列表示。若查询来自正在生成的文本,键和值来自另一组输入表示,就是交叉注意力的一种用法。匹配、归一化、加权组合的核心过程仍然相通。
7.从原论文走到Qwen3,哪些结构保留下来
2017年的Transformer原论文使用8个注意力头,基础模型每头的键和值都是64维。它将多头结果拼接后再投影,已经具备本篇描述的基本计算路径。原论文第3.2.2节
Qwen3技术报告则明确说明使用分组查询注意力GQA。以其中Qwen3-0.6B为例,报告列出的查询头数为16,键值头数为8;同组多个查询头共享键和值,而不是每个查询头都配置完全独立的一组K、V。Qwen3技术报告第2节
这种共享减少了需要存放和读取的键值表示,是推理效率的一种取舍;它不意味着所有查询头会产生相同权重,因为查询仍可不同。GQA原论文
报告还提到QK归一化、旋转位置编码等细节。因此,我们的小算例展示通用机制,并不声称逐项复现Qwen3内部实现,更不能把手填数字当作真实模型的注意力图。
8.读得多,不代表理由已经被解释清楚
注意力图展示某层某头怎样分配读取份额,但最终输出还受到V的内容、输出投影、其他头、其他层和后续计算影响。即便一个位置权重较大,也不能直接把它称为最终结论的主要原因。
最简单的反例可以在纸上验证:如果两个位置的V完全相同,那么在两者之间重新分配权重,只要它们的总份额不变,加权结果就不变。注意力图变了,传给后面的内容却可能完全一样。
2019年的《Attention is not Explanation》在所研究任务中发现,明显不同的注意力分配可以产生相同预测。这支持的谨慎结论是:不能只凭权重热图就声称得到了完整因果解释;并不意味着注意力图在任何分析里都没有价值。原始研究
本篇为手算省略了位置机制,也留下一个限制:没有位置信息和可见性差异时,交换两组键和值的排列,只要它们仍然一一对应,加权总和不会因此改变。这样的读取本身不能充分表达词序。下一章需要补上位置机制,才能区分“谁先发生”“谁修饰谁”等顺序相关关系。
读取范围大也有代价。若n个位置都与n个位置配对,普通稠密注意力要处理与n²相关的匹配计算;从100个位置扩到200个位置,完整配对格子从一万变成四万。这里比较的是这部分计算规模,不能断言整个模型耗时恰好四倍。
FlashAttention这类高效实现可以避免在显存中展开完整注意力矩阵;也有方法限制可见位置,但这些优化有各自条件。FlashAttention原论文长文本能装进去,更不保证关键条件会被正确利用。Attention提供信息通路,训练目标和数据决定模型怎样学会使用它。
本章练习
题目
问题1|追踪两条依赖
固定Q、K,只把v₂从[0,1]改为[0,2],位置3的权重与输出各怎样变化?哪些量是参数?
问题2|先屏蔽,再归一化
回到原始输入,对位置2加因果mask。写出指数值、归一化权重和输出;说明为何不能只删掉原权重第三项。
问题3|权重变了,内容呢
构造一个权重变化、输出不变的例子。取v₁=v₂=[2,1],将两项权重由[0.2,0.8]改为[0.7,0.3],算两次输出,并说明注意力图能证明什么、还不能证明什么。
思考提示
提示1|对应问题1
先找权重的计算依赖,再找加权和的依赖。W与本次计算结果是两类对象。
提示2|对应问题2
先屏蔽分数,再求指数与分母;检查一行权重合计是否为1。
提示3|对应问题3
分别展开两个加权和,注意共同的值向量可以提出来。
参考答案与解析
答案1|对应问题1
权重仍为[1/4,1/4,1/2],因为Q、K没有变;输出变成1/4×[2,0]+1/4×[0,2]+1/2×[2,1]=[1.5,1.0]。W_Q、W_K、W_V是参数,Q、K、V和权重是本次计算的中间结果。
答案2|对应问题2
屏蔽后的指数值为[1,2,0],权重为[1/3,2/3,0],输出为[2/3,2/3]。原权重[1/5,2/5,2/5]删掉第三项后只剩总和3/5,没有把份额在可见位置间重新分配。
答案3|对应问题3
两次输出都是[2,1],因为权重总和都是1且两项V相同。注意力图能显示这一层这一头的读取份额,却不能单独证明最终答案因哪个词产生;还要看值向量、后续计算以及受控干预。
下一章
读取已经让位置之间交换信息,但一次读取之后,原表示与新信息怎样组合?下一章把Attention接入Transformer,追踪残差、归一化与位置旋转如何共同支持深层计算。