Transformer的视觉解释(第3部分):多头注意力
直觉式Transformer系列NLP,简明英语自我注意力,编码器-解码器注意力,注意力得分和掩蔽的内部运作的温和指南。
这是我关于Transformers系列的第三篇文章。我们以自顶向下的方式介绍了其功能。在之前的文章中,我们了解了Transformers是什么,其体系结构以及其工作方式。
在本文中,我们将更进一步,更深入地研究'多头注意力',这是'变形金刚'的大脑。
这是该系列中以前和之后文章的快速摘要。我的目标始终是不仅要了解某件事情的工作原理,而且要理解为什么它会那样工作。
· 功能概述(如何使用Transformers,以及为什么它们比RNN更好。体系结构的组成部分以及训练和推理期间的行为)
· 它是如何工作的(内部操作端到端。数据如何流动以及如何执行计算,包括矩阵表示)
· 多头注意力-本文(整个Transformer中'注意力'模块的内部工作原理)
· 为何注意能提高性能(不仅注意能做什么,而且为什么会如此出色。注意如何捕获句子中单词之间的关系)
如果您还没有阅读过以前的文章,那么最好先阅读它们,因为本文以我们在此介绍的许多概念为基础。
Transformers中如何使用注意力
正如我们在第2部分中讨论的那样,在三个地方的Transformer中使用Attention:
· 编码器中的自注意力-输入序列要注意自身
· 解码器中的自注意力-目标序列要注意自身
· 解码器中的编码器-解码器注意-目标序列注意输入序列
> (Image by Author)
注意输入参数-查询,键和值
注意层以三个参数的形式获取其输入,即查询,键和值。
所有这三个参数在结构上都是相似的,序列中的每个单词都由一个向量表示。
编码器自我注意
输入序列被馈送到输入嵌入和位置编码,输入嵌入和位置编码为输入序列中的每个单词生成一个编码表示,捕获每个单词的含义和位置。这被馈入第一个编码器中'自我注意'中的所有三个参数,即'查询','键'和'值',然后它还会为输入序列中的每个单词生成一个编码表示,现在还包含每个单词的注意力得分。当它通过堆栈中的所有编码器时,每个'自我注意'模块也会在每个单词的表示形式中添加自己的注意力得分。
> (Image by Author)
解码器自我注意
进入解码器堆栈,目标序列被馈送到输出嵌入和位置编码,后者为目标序列中的每个单词生成一个编码表示,捕获每个单词的含义和位置。这被馈入第一个解码器中的'自我注意'中的所有三个参数,即'查询','键'和'值',然后还会为目标序列中的每个单词生成一个编码表示,现在它也合并了每个单词的注意力得分。
通过层规范后,将其馈入第一个解码器的'编码器-解码器注意'中的'查询'参数
编码器-解码器注意
随之,堆栈中最终Encoder的输出将传递到Encoder-Decoder Attention中的Value和Key参数。
因此,Encoder-Decoder Attention获得了目标序列的表示(来自Decoder Self-Attention)和输入序列的表示(来自Encoder堆栈)。因此,它为每个目标序列词生成了一个带有注意力得分的表示形式,该表示形式也从输入序列中捕获了注意力得分的影响。
当它通过堆栈中的所有解码器时,每个自我注意和每个编码器-解码器注意都会在每个单词的表示形式中添加自己的注意分数。
多头注意力
在Transformer中,'注意'模块并行多次重复其计算。这些中的每一个都称为关注头。Attention模块将其Query,Key和Value参数进行N次拆分,并将每次拆分分别通过单独的Head传递。然后将所有这些相似的注意力计算合并在一起以产生最终的注意力得分。这就是所谓的'多头注意',它赋予了Transformer更大的力量,可以为每个单词编码多个关系和细微差别。
> (Image by Author)
为了准确了解数据是如何在内部进行处理的,我们在培训'变形金刚'以解决翻译问题时,逐步完成'注意力'模块的工作。我们将使用一个训练数据样本,其中包括一个输入序列(英语为'欢迎您')和一个目标序列(西班牙语为' De nada')。
注意超参数
有三个确定数据维度的超参数:
· Embedding Size —嵌入矢量的宽度(在示例中,我们使用6的宽度)。这个尺寸会在整个Transformer模型中保留下来,因此有时会用'模型尺寸'等其他名称来表示。
· 查询大小(等于键和值的大小)—三个线性层分别用于生成查询,键和值矩阵的权重的大小(在示例中,我们使用3的查询大小)
· 注意头数(我们在示例中使用2个头)
此外,我们还具有'批次'大小,为我们提供了一个样本数量维。
输入层
输入嵌入和位置编码层生成形状矩阵(样本数,序列长度,嵌入大小),该矩阵被馈送到堆栈中第一个编码器的查询,键和值。
> (Image by Author)
为了使可视化变得简单,我们将在图片中放置'批次'维度,然后将重点放在其余维度上。
> (Image by Author)
线性层
查询,键和值有三个单独的线性层。每个线性层都有自己的权重。输入通过这些线性层产生Q,K和V矩阵。
> (Image by Author)
在Attention头之间拆分数据
现在,数据将分散到多个Attention头上,因此每个头都可以独立处理。
但是,要了解的重要一点是,这仅是逻辑上的分裂。'查询','键'和'值'在物理上并未拆分为单独的矩阵,每个'注意'头均对应一个矩阵。单个数据矩阵分别用于'查询','键'和'值',每个Attention标头的逻辑上各不相同的部分。同样,没有单独的线性层,每个'注意'头各一层。所有Attention头共享相同的Linear层,但仅在数据矩阵的'自身'逻辑部分上进行操作。
线性层权重在逻辑上按头划分
通过在Attention头上均匀划分输入数据和线性层权重来完成此逻辑拆分。我们可以通过选择'查询大小'来实现此目的,如下所示:
查询大小=嵌入大小/头数
> (Image by Author)
在我们的示例中,这就是查询大小= 6/2 = 3的原因。即使图层权重(和输入数据)是单个矩阵,我们也可以将其视为'堆叠'每个磁头的单独图层权重。
> (Image by Author)
因此,可以通过单个矩阵运算而不是需要N个单独的运算来实现所有Head的计算。这使得计算效率更高,并使模型简单,因为所需的线性层更少,同时仍然获得了独立Attention头的功能。
重塑Q,K和V矩阵
线性层输出的Q,K和V矩阵被重塑为包括一个明确的Head尺寸。现在,每个'切片'对应每人一个矩阵。
通过交换' Head'和' Sequence'维,可以再次重塑此矩阵。尽管未绘制'批次'维度,但现在为Q的维度('批次','标题','序列','查询大小')。
The Q matrix is reshaped to include a Head dimension and then reshaped again by swapping the Head
在下面的图片中,我们可以看到从线性层出来之后拆分示例Q矩阵的完整过程。
最后阶段仅用于可视化-尽管Q矩阵是单个矩阵,但我们可以将其视为每个头在逻辑上分开的Q矩阵。
> Q matrix split across the Attention Heads (Image by Author)
我们准备计算注意力得分。
计算每个人的注意力得分
现在,我们将3个矩阵Q,K和V分开分配。这些用于计算注意力得分。
第一步是在Q和K之间进行矩阵乘法。
> (Image by Author)
现在将Mask值添加到结果中。在'编码器自我关注'中,该遮罩用于遮蔽填充值,以使它们不参与注意力得分。
稍后将在流程中使用不同的掩码,分别应用于'解码器自注意'和'解码器编码器注意'中。
> (Image by Author)
现在通过除以查询大小的平方根来缩放结果,然后将Softmax应用于它。
> (Image by Author)
在Softmax的输出和V矩阵之间执行另一个矩阵乘法。
> (Image by Author)
编码器自注意力中的完整注意力得分计算如下:
> (Image by Author)
合并每个主管的注意力得分
现在,每个人都有单独的注意力得分,这些注意力得分需要结合在一起形成一个得分。该合并操作本质上与拆分操作相反。
通过简单地重塑结果矩阵以消除Head尺寸即可完成此操作。这些步骤是:
· 通过交换'头部'和'序列'尺寸来重塑注意力得分矩阵。换句话说,矩阵形状从(批,头,序列,查询大小)变为(批,序列,头,查询大小)。
· 通过重塑为(批,序列,头*查询大小)来折叠'头'尺寸。这有效地将每个头部的注意力得分向量连接到一个合并的注意力得分中。
由于嵌入大小=标题*查询大小,因此合并的分数为(批,序列,嵌入大小)。在下图中,我们可以看到示例分数矩阵的完整合并过程。
> (Image by Author)
端到端多头注意力
综上所述,这就是多头注意力的端到端流程。
> (Image by Author)
多头拆分捕获更丰富的解释
嵌入向量捕获单词的含义。如我们所见,在多头注意的情况下,输入(和目标)序列的嵌入向量在逻辑上跨多个头分割。这有什么意义?
> (Image by Author)
这意味着嵌入的各个部分可以学习每个单词含义的不同方面,因为它与序列中的其他单词相关。这使'变形金刚'可以捕获更丰富的序列解释。
这可能不是一个现实的例子,但可能有助于建立直觉。例如,一个部分可能捕获名词的'性别'(男,女,中性),而另一部分可能捕获名词的'基数'(单数或复数)。这在翻译过程中可能很重要,因为在许多语言中,需要使用的动词取决于这些因素。
解码器的自我注意和掩蔽
除对目标序列的每个字进行操作外,'解码器自注意'的工作方式与编码器'自注意'相同。
> (Image by Author)
类似地,'掩蔽'掩蔽了目标序列中的填充词。
解码器编码器-解码器注意和掩蔽
编码器-解码器注意从两个来源获取输入。因此,与计算每个输入词与其他输入词之间的交互的'编码器自我注意'和计算每个目标词与其他目标词之间的交互的'解码器自我注意'不同,'编码器-解码器注意力'计算每个输入词与其他目标词之间的交互每个输入单词的目标单词。
> (Image by Author)
因此,所得注意力得分中的每个单元对应于一个Q(即目标序列词)与所有其他K(即输入序列)词与所有V(即输入序列)词之间的交互。
类似地,如本系列的第二篇文章中详细解释的那样,Masking屏蔽了目标输出中的后面的单词。
结论
希望这可以使您对Transformer中的Attention模块的功能有一个很好的了解。当与我们在第二篇文章中讨论的整个Transformer的端到端流程放在一起时,我们现在涵盖了整个Transformer架构的详细操作。
现在,我们确切地了解了Transformer的功能。但是,我们尚未完全回答'变压器的注意力'为何执行其计算的问题。为什么要使用查询,键和值的概念,为什么要执行刚才看到的矩阵乘法?
我们有一个模糊的直觉性想法,即'捕获每个单词之间的关系',但这到底是什么意思?究竟如何使'变形金刚的注意力'能够理解序列中每个单词的细微差别?
这是一个有趣的问题,是本系列最后一篇文章的主题。一旦了解到这一点,我们将真正理解Transformer体系结构的优雅。让我们继续学习!
(本文由闻数起舞翻译自Emmett Boudreau的文章《Transformers Explained Visually (Part 3): Multi-head Attention, deep dive》,转载请注明出处,原文链接:https://towardsdatascience.com/transformers-explained-visually-part-3-multi-head-attention-deep-dive-1c1ff1024853)