标题引用原文热梗,手动滑稽哈哈哈。
Transformer于2017年由Vaswani等人提出。它是一种新的深度学习模型,它基于注意力机制,可以处理任意长度的输入序列。与传统的循环神经网络(RNN)和卷积神经网络(CNN)相比,Transformer具有更强大的学习能力和泛化能力。在自然语言处理任务上,Transformer已经取得了最先进的结果。
本文将以《Attention Is All You Need》的论文结构去总结transformer。(本文末有论文链接)
目录
模型架构
Transformer模型的架构如下图所示。它由两部分组成:编码器(Encoder)和解码器(Decoder)。编码器和解码器都由多个自注意力机制层和前馈层组成。自注意力机制层允许模型学习输入序列中各元素之间的关系,而前馈层则让模型可以学习到输入序列的整体信息。
Encoder编码器
如下图所示为编码器结构图。编码器负责将输入序列编码成一组向量。这些向量包含了输入序列中的信息,以及输入序列中各元素之间的关系。编码器由多个自注意力机制层和前馈层组成。自注意力机制层允许模型学习输入序列中各元素之间的关系,而前馈层则允许模型学习输入序列的整体信息。
该图展示的是单层Encoder层,在论文中作者使用了6层Encoder层,我们先只看单层的结果。从上图中可以看出,输入imput先进入Embedding,然后将加入Positional Encoding后将此结果作为输入放入Encoder层(Embedding和Positional Encoding后面有讲)。每个Encoder层中有两个子层,多头注意力层(Multi-Head Attention)和前向传播层(Feed Forward),并在每个子层后都使用了残差连接,并且一同使用了LayerNorm。这样每个子层的输出公式就为:
L
a
y
e
r
N
o
r
m
(
x
+
S
u
b
l
a
y
e
r
(
x
)
)
LayerNorm(x + Sublayer(x))
LayerNorm(x+Sublayer(x))
式中Sublayer就是每个子层。
LayerNorm
这里可以对比BatchNorm来理解一下LayerNorm。
BatchNorm和LayerNorm都是深度学习中常用的归一化方法,但它们之间存在一些区别:
- 作用范围不同。BatchNorm对一个批次中的所有样本进行归一化,而LayerNorm对一个样本中的所有特征进行归一化。
- 训练方式不同。BatchNorm需要在训练过程中计算批次均值和批次方差,而LayerNorm可以在训练和推理过程中直接计算特征均值和特征方差。
关于这方面的内容更多推荐李沐大神的transformer论文精度25:39的部分讲的LayerNorm和BatchNorm的区别以及为什么transformer使用LayerNorm。
Decoder解码器
如下图为解码器结构图。解码器负责将编码器输出的向量解码成输出序列。输出序列可以是自然语言句子、机器翻译结果、摘要等。解码器由两个多头注意力机制层和一个前馈层。
Decoder层有较于Encoder层的两个子层,Decoder层中多了一个多头注意力层(Multi-Head Attention),他对Encorder的输出做了多头注意力操作。和Encoder层类似,每个子层后都使用了残差连接和LayerNorm,但不同的是,一方面Decoder在做预测时,实际上他就是Encoder在之前时刻的一些输出作为这里的输入,所以Decoder的输入写的是一个output;另一方面,这里的第一个Multi-Head Attention是加了一个Masked与Encoder不同,这个Masked是做什么以及为什么要加masked,我们放到attention部分讲。
Attention
self-Attention自注意力机制
首先明确一点,自注意力机制就是Transformer论文中所提到的“Scaled Dot-Product Attention“,它允许模型学习任意长度的输入序列中各元素之间的关系。
自注意力机制的计算过程如下:
- 给定一个输入序列,首先将每个元素映射成三个向量:query、key和value。
- query与key进行点积,得到一个分数矩阵。
- 对分数矩阵进行softmax操作,得到一个注意力权重矩阵。
- 将注意力权重矩阵与value相乘,得到一个加权值的向量。
可以理解为将query和一系列的key-value pairs映射到某个输出的过程,这个输出向量就是value的加权和,而这个权重是由每一个value对应的key和查询的query的相似度计算得来的,不同的注意力机制有不同的相似度算法。下面这个公式就是自注意力机制的算法公式。
其中Q、K和V分别为3个矩阵,且其(第2个)维度分别为dq,dk,dv。
公式中的QK(T)代表的就是Q与K做内积,可以理解为内积的值越大(其实就是余弦值越大),那么这两个向量相似度越大(若内积为零,就是两个向量正交,即两个向量不像似)。
还用另一个问题就是为什么要除以根号dk,这里推荐一个知乎的回答,粗略的说就是如果dk较大时,很有可能存在某个 key,其与 query 计算出来结果远大于其他key与query计算的结果,这会使得softmax梯度过低,最终影响训练效率。qk的运算结果的分布满足均值为零方差为dk的分布,所有除以根号dk是为了让方差停留在[0,1]之间,从而解决softmax梯度过低的问题。这也是“Scaled Dot-Product Attention“中的“Scaled ”的由来。
至于Q,K,V到底是怎么来的,我们看下面这张图。
假设我们的输入是一个序列“我是谁”,那么输入X通过三种不同的线性映射方式,分别映射为Q,K,V。
在通过相似度计算得到一个分数矩阵如下图。
我们可以这样理解,第一行中0.7代表“我”与“我”的attention值,0.2为“我”与“是”的attention值,同理,0.1为“我”与“谁”的attention值,换句话说就是在编码时会将0.7的注意力放在“我”上,0.2的注意力在“是”上,0.1的注意力在“谁”上,得分矩阵第二,三行同理。这样我们就可以对向量进行编码了。但同时我们会发现一个问题,就是自注意力机制在编码时会过分注意自身位置的编码,但一句话中信息往往是具有联系的,因此Transformer作者提出多头注意力机制(Multi-Head Attention)来解决这一问题。
Multi-Head Attention多头注意力机制
Multi-Head Attention其实就是将原始的输入进行多组自注意力运算的处理过程,然后再讲每一组的运算结果直接堆叠起来再进行一次线性变换得到最后的输出结果,它可以并行学习输入序列中的多个子空间。
具体多头注意力公式如下:
其中
在论文中作者有提到,在实验中使用了h=8个头(Head)来构建一个多头注意力层,每个自注意力层都是用的维度dk = dv = d(model)/h = 64.这可以简单看出,多头其实就是把一个大的单头拆成几个多头来实现的。
上图展示的是一个h=2的两头Multi-Head Attention的部分处理过程。输入X分别乘以两个不同的参数矩阵得到不同的Q1,Q2,同理得到K1,K2,V1,V2,再由Q1,K1,V1通过自注意力层得到Z1,同时Q2,K2,V2通过一个自注意力层得到Z1,然后将Z1,Z2通过Concat堆叠起来,最后将堆叠结果乘以W0作为多头注意力层的输出(这里解释的其实就是多头注意力机制的公式)。
Mask
在transformer中,用到了两种不同类型的mask方法,分别是在Decoder中的Attention Mask和在网络训练过程中的Padding Mask。
Attention Mask
在解码过程中,为了模拟真实的预测场景,所以当前位置看不到后面时刻的信息,所以在训练过程中,加入了 Attention Mask来模拟这个情况。在Transformer中Attention Mask是将QK相乘得到的结果直接加上Attention Mask矩阵,其中Mask矩阵中需要mask的位置矩阵用负无穷代替,需要保留的位置信息置为零,如下图。通过softmax结果后mask的部分的权重系数就会被置为零。
Padding Mask
Padding Mask用于屏蔽输入序列中的填充元素。填充元素通常是用于补齐输入序列使其具有相同长度。在网络训练过程中,同一个batch会包含多个文本信息,而这些文本信息的序列长度不一定相同,因此,就需要将同一个batch中不同长的序列信息padding到相同长度。但在transformer中attention运算会计算到padding位置上的参数,
因此,transformer将每个样本padding的位置记录下来,并在计算得到的权重矩阵的相应位置将其置为负无穷,这样padding位置的权重参数经过softmax后的权重就会被置为0。
Positional Encoding
Transformer模型中的Embedding层负责将输入序列中的每个元素映射成一个向量。这个向量包含了该元素的信息,以及该元素与其他元素的关系。但其中缺少元素之间的序列信息,为了解决这一问题,Transformer引入了Positional Encoding为输入序列中的每个Token添加了序列信息。
我们可以对比RNN是如何引入序列信息的。在RNN里面,我们是将前一个时刻的输出加到下一个时刻的输入,这样做就直接将序列信息引入到计算之中。而Transformer是将当前这个词所在的位置i(比方说1,2,3…),直接加到输入里面,所以称为Positional Encoding。具体实现公式如下。
在Transformer论文中有规定,Inputs和Outputs的维度均为512( d(model)=512 ),所以在Positional Encoding也同样用一个512维的向量来表示当前Token的位置信息,然后将这个位置信息与Input Embedding相加,这样我们就直接将序列信息加入到我们的输入中了。而这个位置信息是由周期不同的正弦、余弦函数算出来的。
总结:
Transformer是一种不同的深度学习模型,它基于注意力机制,可以处理任意长度的输入序列。与传统的循环神经网络(RNN)和卷积神经网络(CNN)相比,Transformer具有更强大的学习能力和泛化能力。在自然语言处理任务上,Transformer已经取得了最先进的结果。
对比RNN:
其实全局流程RNN和Transformer相似,都是通过一个MLP来做一个语义空间的转换,但不一样的点在于如何传递序列信息。RNN是用前一个时刻的输出加入到下一个时刻的输入,这就完成了序列信息的加入;但Transformer中是通过一个Attention层,然后全局的去拿到整个序列的信息,然后再用过MLP做一个语义转换。但其实关注点都是怎样的去使用这个序列信息。
参考
链接: This post is all you need这篇文章是我学习Transformer中看的最多的一篇,认为将Transformer讲的非常透彻,不论是原理方面还是代码方面,本文中也多处引用了这篇文章中的许多观点和图片,非常值得初学者去看一下这篇文章。
链接: 为什么 dot-product attention 需要被 scaled在这篇文章中主要通过公式推导为什么自注意力机制要除以根号dk,这也是Transformer中非常重要的一点。
链接: 李沐大神的Transformer视频讲解非常详细,值得反复观看。
链接:Attention Is All You Need最后附上Transformer的论文链接。