从零手推:大语言模型核心——Attention 机制与 QKV 矩阵
前置知识: 序列模型、线性层与矩阵乘法
引言:为什么我们需要 Attention?
在学习《序列模型》(如 RNN / LSTM)时,我们知道处理“我 爱 你”这句话,模型是按顺序吃的:先吃“我”,再吃“爱”,最后吃“你”。 RNN 的致命弱点:
- 遗忘: 句子一长,看到后面就忘了前面。
- 慢: 必须串行计算,无法发挥 GPU 强大的并行矩阵运算能力。
2017 年,Google 提出了 Self-Attention(自注意力机制),彻底掀翻了 RNN。它的核心思想极其霸道:不排队了,句子里的所有词同时互相看,一次性算清楚谁和谁关系最铁!
下面,我们就用“我 爱 你”这三个词,手工推演这个“互相看”的过程。
第一步:词的数字化与 QKV 的诞生 (回顾)
假设我们的词向量维度 D=4,序列长度 L=3。 输入矩阵 X(包含了“我”、“爱”、“你”三个词的特征):
X=101011100010(维度: 3×4)
输入矩阵 X 分别乘以三个权重矩阵 WQ,WK,WV(这三个矩阵是模型在训练中学习到的,维度设为 4×4),我们得到了 Q(查询)、K(键/标签)、V(值/本体)三个矩阵。
这里假设算出来的 Q 和 K 矩阵如下:
Q=101011100110←我的查询←爱的查询←你的查询
K=101011010100←我的标签←爱的标签←你的标签
第二步:灵魂碰撞 —— 计算打分矩阵 (Q×KT)
Attention 的核心思想是:拿每个词的 Query,去和其他所有词的 Key 算相似度。 在数学中,计算两个向量相似度最直接的方法就是点积(Dot Product)。点积越大,说明两个向量越相似,注意力应该分配得越多。
为了一次性算出所有词两两之间的相似度,我们用矩阵乘法:Q 乘以 K 的转置 (KT)。
首先,把 K 躺平变成 KT(维度变为 4×3):
KT=100101101100
现在计算 Scores=Q×KT:
1010111001103×4×1001011011004×3=2111111123×3
💡 极其重要的物理意义解析(面试必考): 看看算出来的这个 3×3 的矩阵,这就是注意力打分矩阵(Attention Score Matrix)!
- 第一行 [2, 1, 1]:代表“我”这个词的 Q,分别去匹配“我”、“爱”、“你”的 K。发现“我”对“我”自己的注意力得分是 2,对“爱”和“你”是 1。
- 第二行 [1, 1, 1]:代表“爱”去匹配所有词的得分。
- 第三行 [1, 1, 2]:代表“你”对“我”、“爱”、“你”的打分。
到这一步,模型已经算出了任意两个词之间的关联程度。没有任何先后顺序,全部是一次矩阵乘法完成的。这就是 Transformer 比 RNN 快的根本原因!
第三步:缩放与概率化 (Scale & Softmax)
得出了打分矩阵,我们还要做两层处理。
1. 缩放 (Scale):除以 dk
公式里有一步是 dkQKT。这里的 dk 就是词向量的维度(我们这里是 4,所以除以 4=2)。
🔥为什么一定要除以 dk?不除会怎样? 标准答案: 为了防止梯度消失。当词向量维度 dk 很大时(比如 768),点积算出来的数值会非常大。如果直接把这么大的数值扔给后面的 Softmax 函数,Softmax 会被“撑爆”(推向饱和区),导致输出的概率变成一个极端的 One-hot 向量(如 [0.999, 0.001, 0]),这时候梯度接近于 0,模型参数就无法更新学习了。除以根号 dk 是一种方差控制手段,把数值拉回到合理的范围内。
在我们这个简化的例子里,除以 2 之后,打分矩阵变成了:
Scaled Scores=1.00.50.50.50.50.50.50.51.0
2. 概率化 (Softmax)
我们要把分数变成加起来等于 1 的百分比权重。沿着每一行做 Softmax。 (为了直观,这里直接给出近似的概率结果)
Attention Weights=Softmax(Scaled Scores)≈0.450.330.270.270.330.270.270.330.45
看第一行:对于“我”这个词,它分配了 45% 的注意力给自己,27% 给“爱”,27% 给“你”。
第四步:提取精华 —— 乘以 V 矩阵
现在我们有了每个词对其他词的“关注度百分比”,最后一步,就是拿这个百分比,去把 V 矩阵(包含真实内容)里的特征按比例提取出来。
最终结果 = AttentionWeights×V
0.450.330.270.270.330.270.270.330.453×3×v我v爱v你3×4
以第一行(更新后的“我”的特征)为例: 新“我” = 0.45×v我+0.27×v爱+0.27×v你
结论: 经过这套 Attention 运算后,输出的仍然是一个 3×4 的矩阵。但是,此时的“我”,已经不再是原本孤立的“我”了。它融合了 27% “爱”的语境和 27% “你”的语境。词语之间产生了灵魂的交融,模型就这样“理解”了上下文!
下一篇预告: 当有了 Attention 之后,为什么原版代码里还需要加上位置编码 (Rotary Embedding) 和 GQA 机制?我们将在下篇继续手撕大模型源码!
尺素
0 封尺素
正在取尺素...