self-attention原理详解

该博客讲解的极其清晰,强烈推荐 https://jalammar.github.io/illustrated-transformer/
以下内容源于此博客(转载翻译分享)
1、让我们首先将模型看作一个黑盒子。在机器翻译应用程序中,它将使用一种语言的句子,并将其翻译输出到另一种语言中。
self-attention原理详解
文章图片

2、打开黑盒子,我们看到了编码组件,解码组件以及它们之间的连接。self-attention原理详解
文章图片

编码组件是一堆编码器(图中由6个编码器组成,数量可自己设置)。解码组件是相同数量的解码器的堆栈。
self-attention原理详解
文章图片

编码器在结构上都是相同的(但它们不共享权重)。每一个都分为两个子层:编码器的输入首先流经自我关注层 - 这一层帮助编码器在输入句子中编码特定单词时查看其他单词。自我关注层的输出被馈送到前馈神经网络。完全相同的前馈网络独立应用于每个位置。解码器具有这两个层,但它们之间是一个关注层,帮助解码器关注输入句子的相关部分(类似于seq2seq模型中的注意力)。
self-attention原理详解
文章图片

3、与NLP应用程序中的情况一样,我们首先使用嵌入算法将每个输入字转换为向量。 每个单词都嵌入到大小为512的向量中。我们将用这些简单的框表示这些向量。嵌入仅发生在最底部的编码器中。所有编码器接收每个大小为512的向量列表 - 在底部编码器中将是嵌入字,但在其他编码器中,它将是下面的编码器的输出。这个列表的大小是我们可以设置的超参数 - 基本上它是我们训练数据集中最长句子的长度。在我们的输入序列中嵌入单词后,它们中的每一个都流过编码器的两个层中的每一层。
【self-attention原理详解】在这里,我们开始看到Transformer的一个关键属性,即每个位置中的单词在编码器中流经自己的路径。自我关注层中的这些路径之间存在依赖关系。然而,前馈层不具有那些依赖性,因此各种路径可以在流过前馈层时并行执行。接下来,我们将示例切换为较短的句子,我们将查看编码器的每个子层中发生的情况。
self-attention原理详解
文章图片

4、在阅读Attention is All You Need论文之前,我个人从未遇到过这个概念。让我们提炼它是如何工作的。假设以下句子是我们要翻译的输入句子:“ The animal didn’t cross the street because it was too tired”这句话中的“it”是指什么?它指的是" cross"还是"animal"?这对人类来说是一个简单的问题,但对算法来说并不简单。当模型处理单词“it”时,自我关注允许它将“it”与“animal”相关联。当模型处理每个单词(输入序列中的每个位置)时,自我注意允许它查看输入序列中的其他位置以寻找可以帮助导致对该单词更好的编码的线索。如果您熟悉RNN,请考虑如何保持隐藏状态允许RNN将其已处理的先前单词/向量的表示与其正在处理的当前单词/向量合并。自我关注是transform用来将其他相关单词的“理解”融入我们当前正在处理的单词的方法。
self-attention原理详解
文章图片

当我们在编码器#5(堆栈中的顶部编码器)中编码单词“it”时,注意机制的一部分集中于“The animal”,并将其表示的一部分嵌入到“它”的编码中。
5、在第一步骤中每个单词,我们创建一个Query向量,一个Key向量和一个Value向量。这些向量是通过将嵌入向量乘以我们在训练过程中训练的三个矩阵而创建的。请注意,这些新向量的尺寸小于嵌入向量。它们的维数为64,而嵌入和编码器输入/输出向量的维数为512。它们不一定要小,这是一种架构选择,可以使多头注意力计算(大多数)不变。
self-attention原理详解
文章图片

self-attention原理详解
文章图片

6、首先是计算得分即Q与K之间的点乘,则第一个得分将是q1和k1的点积。第二个分数是q1和k2的点积。然后为了防止其结果过大,会除以一个尺度标度(query或者key的维度平方根)。再利用Softmax操作将其结果归一化为概率分布, 该softmax分数确定每个单词在该位置表达的程度。很明显,这个位置上的单词将具有最高的softmax分数,但有时候注意与当前单词相关的另一个单词是有用的。然后再乘以矩阵V就得到权重求和的表示。这会在此位置产生自我关注层的输出(对于第一个单词)。
self-attention原理详解
文章图片

最后,我们可以在一个公式中浓缩以上步骤来计算自我关注层的输出。 矩阵形式的自我关注计算如下图:
self-attention原理详解
文章图片

7、本文通过增加一种称为“多头”关注的机制,进一步完善了自我关注层。这以两种方式改善了关注层的性能:
(1)它扩展了模型关注不同位置的能力。在上面的例子中,z1包含了所有其他编码的一点点,但它可能由实际的单词本身支配。如果我们翻译一句“The animal didn’t cross the street because it was too tired”,我们会想知道“it”指的是哪个词,这将是有用的。
(2)它为注意层提供了多个“表示子空间”。正如我们接下来将看到的,我们不仅有一个,而是多组Query / Key / Value权重矩阵(Transformer使用8个注意头,因此我们最终为每个编码器/解码器设置了8个) 。这些集合中的每一个都是随机初始化的。然后,在训练之后,每组用于将输入嵌入(或来自较低编码器/解码器的矢量)投影到不同的表示子空间中。
如果我们进行上面概述的相同的自我关注计算,只有八个不同的时间使用不同的权重矩阵,我们最终得到八个不同的Z矩阵
self-attention原理详解
文章图片

这让我们面临一些挑战。前馈层不期望八个矩阵 - 它期望单个矩阵(每个字的向量)。所以我们需要一种方法将这八个压缩成一个矩阵。我们怎么做?我们将通过另外的权重矩阵WO将它们多个矩阵连接起来。
self-attention原理详解
文章图片

这就是多头自我关注的全部内容。我意识到,这是一小部分矩阵。让我尝试将它们全部放在一个视觉中,这样我们就可以在一个地方看到它们
self-attention原理详解
文章图片

现在我们已经触及了注意力的头,让我们重新审视我们之前的例子,看看不同的注意力头在哪里聚焦,因为我们在我们的例句中编码了“it”这个词:
self-attention原理详解
文章图片

8、我们到目前为止描述的模型中缺少的一件事是一种考虑输入序列中单词顺序的方法。为了解决这个问题,变换器为每个输入嵌入添加了一个向量。这些向量遵循模型学习的特定模式,这有助于确定每个单词的位置,或者序列中不同单词之间的距离。这里的直觉是,将这些值添加到嵌入中,一旦它们被投影到Q / K / V向量中并且在点积注意期间,就在嵌入向量之间提供有意义的距离。
self-attention原理详解
文章图片

    推荐阅读