为什么需要它
把一句话喂给模型之前,每个词会被映射成一个固定的向量——这叫 embedding。问题来了:
"bank" 这个词在 "river bank" 和 "savings bank" 里意思完全不同,但它的 embedding 一开始是同一个。
要让模型理解上下文,每个词的表示就必须根据它周围的词动态调整。注意力机制就是干这件事的——它让每个 token 都能"看一眼"句子里的其他 token,然后按需融合信息。
图书馆的查询比喻
想象一个图书馆。你拿着一张提问卡(query),每本书有自己的索引标签(key)和内容(value)。
- 把你的提问卡和每本书的标签对比——算出一个相似度分数。
- 分数归一化成百分比(softmax),告诉你应该给每本书多少注意力。
- 按这个百分比加权混合所有书的内容,得到回答。
注意力机制做的就是这件事,只不过每个 token 同时扮演三个角色:作为提问者发出 query,作为被查者提供 key 和 value。这一切完全可微分——所有 query / key / value 都是 embedding 经过线性变换得到的,权重可以训练出来。
Q / K / V 的诞生
那「线性变换」具体是怎么把一个 embedding 变成三个东西的?三个学出来的权重矩阵 、、 分别"提取"同一个 embedding 的不同侧面。点一下 Q / K / V 看效果:
input · x (embedding,dim = 8)
Q — Query (dim = 4)
「我想找什么」—— 这个 token 的提问卡。
注意——Q、K、V 同源。它们都从同一个 embedding 出发,只是用不同的视角看自己。这就是为什么注意力是「self-attention」:每个 token 都在用自己的三种身份和句子里其他 token 的三种身份打交道。
三步算法
数学上只有三步。设句子有 个 token,每个 embedding 维度是 :
第一步:每对 (query, key) 做点积,得到 的相似度矩阵:
第二步:每一行做 softmax,把分数变成概率分布:
第三步:用 给所有 value 加权求和:
下面这张交互图就是真实跑出来的 ——句子 "the cat sat on the mat" 里,每个 token 都在看其他 token:
「sat」 attends to →
注意动词 sat——它同时关注主语 cat 和地点 mat。这就是注意力的魔法:它学会了"谁该看谁",而且这套规则是从数据里学出来的,没有人手写过。
换一种视角看同一个矩阵——这次把它画成弧线,更像句法分析图:
为什么除以
公式里那个 不是装饰。
当 很大时(GPT 里通常是 64 或 128),两个随机向量的点积方差会变大——分数会变得很极端。极端的分数喂进 softmax 之后,几乎所有概率会塌缩到最大的那一个上,其他全是 0。这会让梯度几乎消失,模型学不动。
除以 其实就是把 softmax 的温度调高,让分布柔和。拖一下温度感受这件事:
熵越大,分布越平均;熵越小,越尖锐。Transformer 默认除以 就是为了把熵拉到一个梯度能流动的舒服区间。
T 很小时分布尖锐,T 很大时分布均匀。Transformer 默认把温度设成 ,让熵落在一个梯度能稳定流动的区间。
多头注意力
一个 head 只能学一种"看"。但语言里同时存在很多关系:主谓、动宾、修饰、指代、位置……Transformer 的做法是同时跑 h 个独立的注意力,每个有自己的 、、。
邻近:每个 token 关注前一个
主谓:动词找主语
动宾:动词找宾语
全局:每个 token 都广播
最后把所有 head 的输出拼接,再用一个 投影回原维度。这就是 multi-head attention:用并行换表达力。