Happy-LLM 学习笔记 02:把 Attention 看成可学习的信息路由
读第二章时,我最大的感受是:Attention 不是一个神秘模块,而是把“谁该看谁、看多少”这件事显式写进了模型。RNN 依赖顺序传递信息,长依赖和并行性都不理想;Attention 则把序列里每个 token 之间的关系一次性算出来,再让模型按相关性取信息。这个变化看起来只是计算方式不同,实际上却是 Transformer 能成立的前提。
Q、K、V 本质上是在分工
我以前很容易把 Q、K、V 记成三组抽象符号。现在更愿意把它们理解成三种角色:Query 是“我现在想找什么”,Key 是“我能提供什么索引”,Value 是“真正要取走的内容”。模型先用 Q 和 K 做相似度匹配,再用 softmax 把匹配结果变成权重,最后对 V 加权求和。也就是说,Attention 并不是直接生成答案,而是先决定信息流向,再把信息聚合起来。
这个设计的好处在于,相关性是可学习的。词和词之间到底该互相看多少,不需要人手写规则,而是交给参数矩阵去学。对我来说,这也是 Transformer 和传统特征工程最大的分界线:它不再靠人工定义“哪些词重要”,而是让模型自己学会路由规则。
自注意力和掩码自注意力
Self-Attention 的核心变化很小,但意义很大:Q、K、V 都来自同一个序列。这样做之后,模型可以直接建模句子内部任意位置之间的依赖,而不是只看局部窗口。我喜欢你 和 你喜欢我 的区别,不再是靠位置硬编码提醒模型,而是靠位置编码和注意力共同表达。
在生成式任务里,还要加上 Mask。我的理解是,Mask 的作用不是“删掉未来”,而是把未来位置的注意力分数压成不可见,让模型只能按左到右的顺序预测。代码里用上三角矩阵配合 -inf,再接 softmax,就是把这个约束变成了可并行的矩阵运算。这个实现很漂亮,因为训练时依然能批量跑,但语义上仍然保持自回归。
多头注意力解决的是“只看一种关系”太窄的问题
单头 Attention 可以学相关性,但一个头通常只擅长一种视角:有的头更像语法关系,有的头更像局部搭配,有的头更像长距离依赖。多头注意力的价值,就是让模型在不同投影空间里同时看同一段序列,再把这些结果拼回来。它不是简单堆算力,而是在表达能力上把“关系类型”拆开了。
这也解释了为什么实现上要先把 n_embd 切成多个 head,再做并行矩阵乘法。真正关键的不是“多算几次”,而是“每次看的角度不同”。工程上如果头数、维度、mask 形状错了,模型往往不是报一个很直观的错,而是训练能跑但效果很怪,所以这里特别值得盯住张量维度。
读代码时最有启发的几个点
torch.matmul加上transpose就能完成 QK 相似度和加权汇聚,Attention 的本质其实是矩阵代数。torch.triu生成的上三角 mask,把因果约束变成了可广播的张量。register_buffer说明 mask 不是参数,但要随模型一起保存和迁移设备。- 输出维度从
(B, T, h, d)合并回(B, T, dim),说明多头最后还是要回到同一条残差流里。
我的结论
这一章给我的最大启发,是把 Attention 看成一种信息路由机制。模型先判断哪些 token 值得互相交换信息,再把这些信息按权重聚合。Transformer 的强,不只是因为它并行,而是因为它把“关系建模”从隐式递归变成了显式计算。
以后我再看 LLM 里的注意力层,会优先检查三件事:输入是不是被正确切分,mask 有没有把因果关系限制住,多头的维度有没有对齐。很多看起来像玄学的问题,最后都落在这三件事上。

浙公网安备 33010602011771号