
Transformer 之所以强大,是因为其注意力模块。这是因为它能够捕捉序列中每个单词与其他每个单词之间的关系。但最重要的问题是它究竟是如何做到的?
在本文中,我们将尝试回答这个问题,并了解它为什么执行这样的计算。
要了解 Transformer 的工作原理,我们必须关注注意力机制。让我们先从输入开始,然后看看它如何处理这些输入。
输入序列如何到达Attention模块
编码器堆栈中的每个编码器以及解码器堆栈中的每个解码器中都存在注意力模块。我们首先来详细了解一下编码器注意力。

举个例子,假设我们正在研究一个英语到西班牙语的翻译问题,其中一个示例源序列是“球是蓝色的”。目标序列是“La bola es azul”。
源序列首先经过嵌入和位置编码层,该层为序列中的每个单词生成嵌入向量。嵌入被传递到编码器,在那里它首先到达注意力模块。
在注意力机制中,嵌入序列会经过三个线性层,产生三个独立的矩阵,即查询、键和值。这三个矩阵用于计算注意力得分。
要记住的重要一点是,这些矩阵的每一“行”对应于源序列中的一个单词。

每个输入行都是来自序列的一个单词
要了解注意力机制,我们首先要从源序列中的各个单词开始,然后追踪它们在 Transformer 中的路径。具体来说,我们要关注注意力模块内部发生的事情。
这将帮助我们清楚地看到源序列和目标序列中的每个词如何与源序列和目标序列中的其他词交互。
因此,当我们进行解释时,请集中精力于对每个单词执行的操作以及每个向量如何映射到原始输入单词。如果矩阵形状、算术计算的细节、多个注意力头等其他细节与每个单词的去向没有直接关系,我们就不需要担心它们。
因此,为了简化解释和可视化,我们忽略嵌入维度并仅跟踪每个单词的行。

每个单词都会经历一系列可学习的转换
每一行都是通过一系列转换(嵌入、位置编码和线性层)从其对应的源词生成的。
所有这些转换都是可训练的操作。这意味着这些操作中使用的权重不是预先确定的,而是由模型学习而来,从而产生所需的输出预测。

关键问题是,Transformer 如何确定哪组权重能产生最佳结果?请记住这一点,我们稍后会再讨论这个问题。
注意力得分——查询词和关键词之间的点积
注意力机制包括几个步骤,但在这里,我们只关注线性层和注意力分数。


从公式中我们可以看出,Attention 的第一步是将查询 (Q) 矩阵与关键 (K) 矩阵的转置进行矩阵乘法(即点积)。观察每个单词会发生什么。
我们生成一个中间矩阵(我们称之为“因子”矩阵),其中每个单元都是两个词之间的矩阵乘法。

例如,第四行的每一列对应于第四个查询词与每个关键词的点积。

注意力得分——查询关键词和值词之间的点积
下一步是将这个中间“因子”矩阵与值 (V) 矩阵相乘,以产生注意力模块输出的注意力分数。在这里我们可以看到,第四行对应于第四个查询词矩阵与所有其他关键字和值词相乘。

这会产生由注意力模块输出的注意力分数向量(Z)。
输出分数的思路是,对于每个单词,它是“值”矩阵中每个单词的编码值,由“因子”矩阵加权。因子矩阵是该特定单词的查询值与所有单词的键值的点积。

Query、Key 和 Value 词的作用是什么?
查询词可以解释为单词为此我们正在计算注意力。关键和价值词是词至我们正在关注该词与查询词有多相关。

例如,对于句子“球是蓝色的”,单词“蓝色”的行将包含“蓝色”和其他每个单词的注意力分数。这里,“蓝色”是查询词,其他单词是“键/值”。
还有其他操作正在执行,例如除法和 softmax,但在本文中我们可以忽略它们。它们只会改变矩阵中的数值,而不会影响矩阵中每个单词行的位置。它们也不涉及任何单词间相互作用。
点积告诉我们单词之间的相似性
因此,我们已经看到,注意力得分通过进行点积运算,然后将它们相加,来捕捉特定单词与句子中其他每个单词之间的一些交互。但是矩阵乘法如何帮助 Transformer 确定两个单词之间的相关性呢?
要理解这一点,请记住查询、键和值行实际上是具有嵌入维度的向量。让我们放大这些向量之间的矩阵乘法是如何计算的。

当我们对两个向量进行点积计算时,我们将一对数字相乘然后将它们相加。
- 如果两对数字(例如上面的“a”和“d”)都是正数或都是负数,则乘积将为正数。乘积将增加最终总和。
- 如果一个数为正数,另一个数为负数,则乘积为负数。乘积将减少最终总和。
- 如果乘积为正数,则两个数字越大,对最终总和的贡献就越大。
这意味着如果两个向量中对应数字的符号对齐,则最终的总和会更大。
Transformer如何学习词语之间的相关性?
点积的概念也适用于注意力得分。如果两个词的向量越一致,注意力得分就越高。
那么我们希望 Transformer 具有什么样的行为呢?
我们希望句子中彼此相关的两个单词的注意力得分较高。我们希望彼此不相关的两个单词的分数较低。
例如,对于句子“黑猫喝了牛奶”,单词“牛奶”与“喝”非常相关,与“猫”的相关性可能略低,与“黑色”无关。我们希望“牛奶”和“喝”产生较高的注意力分数,“牛奶”和“猫”产生略低的分数,“牛奶”和“黑色”产生可忽略的分数。
这是我们希望模型学习产生的输出。
为了实现这一点,“牛奶”和“喝”的词向量必须对齐。“牛奶”和“猫”的向量会略有不同。而“牛奶”和“黑色”的向量会有很大不同。
让我们回到我们一直思考的问题——Transformer 如何确定哪组权重可以产生最佳结果?
词向量是根据词向量和线性层的权重生成的。因此,Transformer 可以学习这些词向量、线性权重等,以生成上述所需的词向量。
换句话说,它会以这样的方式学习这些嵌入和权重:如果句子中的两个单词彼此相关,那么它们的词向量就会对齐。从而产生更高的注意力分数。对于彼此不相关的单词,词向量不会对齐,并会产生较低的注意力分数。
因此,“牛奶”和“喝”的嵌入将非常一致,并产生较高的注意力分数。对于“牛奶”和“猫”,它们会略有不同,从而产生略低的分数,而对于“牛奶”和“黑色”,它们会有很大不同,从而产生较低的分数。
这就是注意力模块背后的原理。
总结——是什么让 Transformer 运转起来?
查询和关键字之间的点积计算每对词之间的相关性。然后,该相关性被用作“因子”来计算所有值词的加权和。该加权和被输出为注意力分数。
Transformer 以这样的方式学习嵌入等,使得彼此相关的单词更加一致。
这就是引入三个线性层并针对查询、键和值创建三个输入序列版本的原因之一。这为注意力模块提供了更多参数,使其能够学习调整词向量的创建。
Transformer 中的编码器自注意力机制
Transformer 中有三个地方使用了 Attention:
- 编码器中的自注意力——源序列关注自身
- 解码器中的自注意力——目标序列关注自身
- 解码器中的编码器-解码器注意力——目标序列关注源序列

在编码器自注意力机制中,我们计算源句子中每个单词与源句子中其他每个单词的相关性。这发生在堆栈中的所有编码器中。
Transformer 中的解码器自注意力机制
我们刚刚在编码器自注意力中看到的大部分内容也适用于解码器中的注意力,尽管存在一些细微但重要的区别。

在解码器自注意力机制中,我们计算目标句子中每个单词与目标句子中其他每个单词的相关性。

Transformer 中的编码器-解码器注意力机制
在 Encoder-Decoder Attention 中,Query 来自目标句子,Key/Value 来自源句子,从而计算目标句子中每个单词与源句子中每个单词的相关性。

结论
希望这能让您充分感受到 Transformer 设计的优雅。请阅读我系列中的其他 Transformer 文章,深入了解为什么 Transformer 现在已成为众多深度学习应用程序的首选架构。