一篇读懂 Attention:Q、K、V 到底在算什么

每个词都要「看见」别的词

「小明把书递给小刚,因为它太重了。」——这里的「它」指书还是小刚?人读一遍就懂,但模型要算出这种关系,就必须让每个 token 都能「看见」句子里其他的 token,并判断谁与自己有关、有多相关。注意力机制(Attention)干的就是这件事:让信息在 token 与 token 之间按相关性流动。它也是 Transformer 架构的核心组件。

更早的做法是把整句话压缩成一个定长向量再往下传,句子一长,信息就挤丢了。注意力让每个词都能直接「连线」到任何其他词——不管隔多远,都只差一步,长句子的远距离依赖从此有了着落。

一个检索类比:Q、K、V

把每个 token 想象成图书馆里的一本书,它同时扮演三个角色:

  • Q(query,查询):我想找什么——这本书发出的检索请求;
  • K(key,键):我能被怎么找到——贴在书脊上的索引标签;
  • V(value,值):我携带的内容——翻开书后真正读到的正文。

Q、K、V 从哪来?同一个词的向量表示分别乘上三个可学习的矩阵,就得到这个 token 的三重身份——模型在训练中学的,正是这三个矩阵该长什么样。

注意力的一次计算过程是:每个 token 拿自己的 Q,去和所有 token 的 K 一一算相似度;相似度经过 softmax 变成一组加起来为 1 的权重;再用这组权重去加权平均所有 token 的 V。结果是一个融合了上下文的新表示——「它」的 Q 与「书」的 K 相似度高,于是「它」的新表示里就掺入了大量「书」的内容,指代关系在向量层面被建立起来。

三步合起来就是那个著名的公式:

Attention(Q, K, V) = softmax(Q·Kᵀ / √d_k) · V

为什么要除以 √d_k

点积有个坏脾气:维度 d_k 越大,两个随机向量点积的数值方差就越大,容易算出很大的数。logits 一大,softmax 就会饱和——最大的那一项独占几乎全部概率,其余项接近 0,梯度随之消失,训练就不稳定了。除以维度开平方 √d_k,把点积的量级拉回稳定区间,这是「缩放点积注意力」名字里「缩放」二字的由来。附带的好处是:模型更大、d_k 更长时,缩放项自动跟着变大,公式本身不用改。

多头:多双眼睛各看各的

一次注意力只能捕捉一种关系模式。多头注意力(multi-head attention)的做法是:把表示切成若干份,每份独立配一组 Q、K、V,并行计算注意力——有的头专盯语法结构,有的头追指代,有的头看位置邻近关系。最后把各头的输出拼接起来,再做一次线性变换把信息揉回去。头与头分工不同,模型才能同时从多个角度理解一句话。

因果掩码:看不见未来

生成式模型有条铁律:预测第 i 个 token 时,只能看第 i 个及之前的内容,不能偷看未来。实现方式是因果掩码(causal mask):在算注意力权重时,把「未来位置」的相似度设成负无穷,softmax 之后它们的权重精确为 0。

这个掩码还解释了 Transformer 训练与生成的一个不对称性:训练时,整个序列一次性输入,掩码保证每个位置都只依赖过去,所以所有位置的预测可以并行计算;推理生成时,下一个 token 的内容还不存在,只能一步一步来。训练并行、生成串行,根源就在这里。

连接到工程:KV Cache

推理时还有一个关键观察:某个位置的 K 和 V 只由该位置及之前的内容决定,一旦算出来就不会再变。于是可以把历史所有位置的 K、V 缓存下来(KV Cache),每生成新 token 只需为新位置算一组 Q、K、V,与缓存做注意力即可,不必把整段前文重算一遍。代价是缓存随上下文长度线性增长,慢慢变成吃显存的大户,「注意力在推理时受显存带宽约束」也因此成为大模型服务最常见的瓶颈。关于 KV Cache 的展开——缓存怎么存、为什么吃显存、怎么省——本站另有专文,它与投机解码一文互为表里:一个管「记住历史」,一个管「更快生成未来」。

小结

回顾这条主线:token 之间要交流信息,于是每个 token 带上 Q、K、V 三个角色;Q 与 K 的缩放点积算出「该看谁」,softmax 把相似度变成权重,加权平均 V 得到融合后的新表示;多头让模型多角度看问题;因果掩码保证不偷看未来,也造成了训练并行、生成串行的分野;而 K、V 只依赖历史的性质,最终长成了推理工程里的 KV Cache。理解了这副骨架,再看 Transformer 的其他细节,就都只是在上面的近似与优化。

← 返回资讯列表

读者留言

COMMENTS 暂无
仅本站原创文章开放留言 · 请勿留下手机号、邮箱等个人信息

还没有留言,来说第一句?