注意力模块存在于编码器栈和码器栈的每个编码器中。我们首先来详细了解一下编码器的注意力机制。以英译西举例源序列示例是 The ball is blue.目标序列是 La bola es azul。源序列首先经过嵌入和位置编码层每个词被生成嵌入向量。嵌入向量随后被传递到编码器编码器首先会经过注意力模块。在注意力机制中嵌入的序列会经过三个线性层生成三个独立的矩阵查询矩阵、键矩阵和值矩阵用于计算注意力得分。需要注意的是这些矩阵的每一行都对应于源序列中的一个单词。输入的每一行都是序列中的一个单词要理解注意力机制的运作方式需要从源序列中的各个词语入手追踪它们在 Transformer 模型中的处理路径,即注意力模块内部的运作机制。这将有助于理解源序列和目标序列中的每个词是如何与其他词相互作用的。因此在下面的解释中请集中注意力关注每个词所执行的操作以及每个向量如何映射到原始输入词。如果矩阵形状、算术运算的具体细节、多个注意力头等与每个词的去向没有直接关系直接忽略这些细节。为了简化解释和可视化我们忽略嵌入维度只跟踪每个单词的行。每个词都经过一系列「可学习的」变换上面说的每一行都是由它对应的源词经过一系列变换生成的嵌入、位置编码、线性层。所有这些转换都是可训练的操作。这意味着这些操作中使用的权重并非预先设定而是由模型学习从而产生所需的输出预测。关键问题是Transformer 如何确定哪组权重能带来最佳结果我们稍后会再讨论。注意力分数Query 词和 Key 词之间的点积注意力机制执行多个步骤我们只关注线性层和注意力分数。从公式可以看出注意力机制的第一步是对查询矩阵Q和键矩阵K的转置进行矩阵乘法即点积。观察每个词的变化。我们生成一个中间矩阵我们称之为「因子矩阵」其中每个单元格都是两个单词之间的矩阵乘法例如第四行的每一列对应于第四个查询词与每个关键词的点积。注意力得分查询词和值词之间的点积下一步是将中间「因子矩阵」与值 (V) 矩阵相乘得出注意力模块输出的注意力分数。可以看到第四行对应于第四个查询词矩阵与所有其他键值对的乘积。这样就产生了注意力模块输出的注意力得分向量Z。理解输出得分的方法是对于每个词它是「值矩阵」中所有词的编码值乘以「因子矩阵」的权重。「因子矩阵」是该特定词的查询值与所有词的键值的点积。查询词、键和值的作用Query 词可以理解为 我正在为它计算注意力 的那个词。Key 和 Value 词是 我正在关注的那个词换句话说就是这个词跟我的 Query 词有多相关。举个例子。对于 The ball is blue 这个句子blue 那一行里包含了 blue 与其他每个词的注意力分数。在这个例子里 blue 就是 Query 词而其他词就是 Key / Value。注意力计算里还有别的操作比如除法和 Softmax。暂时忽略它们。这些操作只是改变矩阵里的数值但不会影响每个词所在的行在矩阵中的位置也不会引入任何词与词之间的交互。点积揭示词与词之间的相似度我们已经看到注意力分数通过计算点积并将结果相加捕捉到特定词语与句子中其他所有词语之间的某种交互作用。但是矩阵乘法是如何帮助 Transformer 确定两个词语之间的相关性的呢为了理解这一点请记住查询行、键行和值行实际上是具有嵌入维度的向量。让我们深入了解一下这些向量之间的矩阵乘法是如何计算的。当我们对两个向量进行点积运算时我们将成对的数字相乘然后将它们相加。如果两对数字例如上面的 a 和 d均为正数或均为负数则它们的乘积为正数。乘积会增加最终的总和。如果一个数是正数另一个数是负数那么它们的乘积将为负数。乘积会减少最终的总和。如果乘积为正数则两个数越大它们对最终总和的贡献就越大。这意味着如果两个向量中对应数字的符号一致则最终的总和会更大。不同词之间的相关性点积的这个特性同样适用于注意力分数。如果两个词的向量更对齐也就是符号一致的部分更多那么注意力分数就更高。那么我们希望 Transformer 表现出什么样的行为呢对于句子里彼此相关的两个词希望注意力分数高。对于不相关的两个词希望注意力分数低。举个例子。对于 The black cat drank the milk 这个句子milk牛奶和 drank喝非常相关。milk 和 cat猫可能稍微有点相关但没那么强。milk 和 black黑色的则基本不相关。我们希望模型学到的输出是这样的milk 和 drank 产生高注意力分数。milk 和 cat 产生一个稍低的分数。milk 和 black 产生一个可以忽略不计的低分。为了达到这个效果milk 和 drank 的词向量必须对齐milk 和 cat 的词向量会有些分歧而 milk 和 black 的词向量则会相当不同。现在回到前来遗留的问题Transformer 是怎么知道哪一组权重能给它带来最佳结果的这些词向量是基于词嵌入和线性层的权重生成的。因此Transformer 可以去学