查询、键与值(query, key, value)
/ KWEER-ee, kee, and VAL-yoo /
查询、键与值,是注意力机制里每一项都要扮演的三种角色,最干净的类比是一次图书馆检索。查询,就是你要找的东西——你敲进去的检索词。键,是每本书书脊上的标签,检索就拿它来匹配。值,是你从架上抽出来的那本书里实际的内容。注意力把你的查询与每个键相比较,判定哪些书相关,再按各自匹配的好坏,把它们的值加权调和后递给你。
在 Transformer 里,每个词元的向量分别乘以三个独立的、学得来的权重矩阵,产出它自己的查询、键、值向量。某个词元用它的查询去与每个词元的键(包括它自己的)打分;这些分数变成注意力权重;该词元随后收到所有值的加权和。这种拆分是刻意的:把「我在找什么」(查询)与「我对外标榜什么」(键)以及「我实际交付什么」(值)分开,让模型有自由按一个依据去匹配,却传递另一样不同的东西。
这三件套是让注意力其余部分变得精确的词汇。自注意力,不过是查询、键、值都来自同一序列的那种情形;交叉注意力,则是查询来自一个序列、键与值来自另一个序列。懂了 QKV,便是注意力从「像魔法」到「看清其本来面目」的分水岭:一次学得来的、基于内容的查找,后接一次加权平均。这些矩阵是学出来的,所以什么算「匹配得好」,本身也是由训练塑造的,并非事先写定。
词元「河」提供一个大致意为「我与水/地理有关」的键,以及一个承载其内容的值。当词元「岸」形成一个诸如「我需要确定我的意思」的查询时,它与「河」的键打出高分,于是「河」的值流入,替「岸」消解了歧义。
按键匹配,取出值——一次柔性的、学出来的查找。
键与值是刻意分开的。一个词元可以在键上强烈匹配,却贡献一个说着相当不同之事的值——所以「注意力据以挑选的东西」与「它实际传递的东西」不必是同一个向量。把二者混为一谈,是初学者常犯的错。