Transformer: Attention Is All You Need

论文资源

The Illustrated Transformer
Attention Is All You Need

摘要

Transformer抛弃了传统的CNN和RNN,整个网络结构完全是由Attention机制组成,Bert就是基于Transformer构建的,这个模型广泛应用NLP邻域,例如机器翻译,问答系统,文本摘要和语音识别等等方向

导言和背景

   RNN之所以不支持并行化是因为它是一个时序结构,给定一个序列,它是把这个序列从左到右依次进行,t时刻依赖t-1时刻的输出,而t-1时刻是依赖t-2时刻的输出,如此循环向前,所以可以说t时刻依赖前t时刻所有的信息,这样子它就可以把前面学到的历史信息和当前词进行融合计算,得到输出,这就是RNN如何能够有效处理时序信息的一个原因
   简单来说RNN就是学习时序数据中的局部依赖关系,实际上深度学习很多模型的目的都是为了学习样本之间的局部关系,如CNN也是为了学习空间数据中局部依赖关系。为了完成对长距离样本之间依赖关系的学习,CNN采用多次卷积、池化等操作,这样需要加大网络的深度,才能更多的学习到更大范围的样本局部依赖关系,举个例子,用CNN做卷积计算时,由于受卷积核的大小限制,每次只能看到卷积核大小的那一块像素区域,如果两个像素距离很远,就需要堆叠很多层卷积层,最后才能把这两个距离很远的像素融合起来。
   RNN虽然理论上可以建立长距离依赖关系,但由于存在梯度消失,网络容量等问题,如果处理的时序信息比较长的话,可能会导致很早期的信息在后面的时候会被遗忘掉
   Transformer是一种避免使用循环的模型架构,完全依赖注意力机制来绘制输入和输出之间的全局依赖关系,transformer允许更显著的并行化

Transformer整体结构

在这里插入图片描述
在序列模型里面,有一个比较好的架构叫做编码器和解码器的架构,对编码器来讲,它会将长为n的向量(x1, x2, …, xn)作为输入,假设是一个句子,那么在这n个词里面xt就表示第t个词的信息,输出是(z1, z2, …, zn),每个zt对应的是xt的一个向量表示。而对于解码器来讲,它会将编码器的输出(z1, z2, …, zn)作为输入,依次生成一个字符的方式生成一个长为m的输出序列(y1, y2, …, ym) (n和m不一定相同,比如说英文翻译为中文,两个句子就不一定一样长)
论文中提到了自回归模型,将z输入到解码器中,它将生成第一个输出y1,就比如说英文翻译时把一整段英文句子输入进去,它将生成第一个输出y1,也就是一个字符,拿到y1之后就可以去生成y2,生成yt的时候,可以把之前所有的y1到yt-1结果作为输入,也就是过去时刻的输出可以做当前时刻的输入

可以看到它是一个编码器和解码器的架构,大致可以分为4个部分: Input、Encoder block、Decoder block、Output
Inputs: 有两个输入,一个是编码器的输入,另一个是解码器的输入,比如说英文翻译,编码器的输入就是一个英文句子。解码器的输入指的是解码器在之前时刻的输出,所以这里写的是output,shifted right意思是一个个往右移(后面再讲)
Encoder: 输入是单词的Embedding,再加上位置编码,然后进入一个统一的结构,这个结构可以循环很多次(N次),每一层又可以分成Attention层和全连接层,中间还有一些残差连接,以及Normalization
Decoder: 第一次输入是前缀信息,之后的就是上一次产出的Embedding,加入位置编码,然后进入一个可以重复很多次的模块。解码器比编码器部分多了一个Masked的多头注意力机制
Outputs: 最后的输出要通过Linear层(全连接层),再通过softmax处理

Encoder

LayerNorm和BatchNorm区别

在这里插入图片描述
BatchNorm就是每一次把每一列,也就是把每一个特征在一个Mini-batch里面将它的均值变为0,方差变为1,也就是把它这个向量本身的均值减去,然后再除以它的标准差就行了,当然也可以让这个向量学一个γ和β,然后便可以放缩成任意的方差以及任意的均值
LayerNorm就是对每个样本做normalization,而不是对每个特征做,也就是把每一行将它的均值变为0,方差变为1
在transformer里面,或者说正常的RNN里面,它的输入是一个三维的东西,因为它输入是一个序列的样本,比如说一个句子,句子里面有n个单词,每个词都可以用一个向量来表示,就是一个三维的维度
BatchNorm就是每一次取一个特征,然后把它的每个样本里面的所有元素,也就是序列的元素以及它的整个batch全部提取出来,把它的均值变为零,方差变为1

Self Attention Mechanism(自注意机制)

拿到不同的数据,我们的关注点可能会不同,关注度最大的区域将描述当前的数据有着怎样的特点,有着怎样的分辨能力。例如提取图像特征的时候,使用图像的热度图可视化方法,通过观察高响应区域便可判断出哪块区域被当作重点了。文本同理

举个例子(句中it指代的是什么?):

  1. The animal didn't cross the street because it was too tired
    由tired可知这里的it指代的是animal,所以对于it来说关注的重点是animal
  2. The animal didn't cross the street because it was too narrow
    由narrow可知这里的it指代的是street,所以对于it来说关注的重点是street

下图中颜色的深浅表示影响力的强弱(相当于权重越大影响越大),可以很容易的看出对it影响最大的是The和animal这两个单词

从例子可以看出,不同的语境it将指代不同的含义,所以在词做编码的时候,不能简单的考虑当前这一个词,还需要考虑当前词所处的上下文语境,也就是说要把整个上下文语境融入到当前词向量当中,Self-Attention就是查看句子中的单词与其他单词之间的相互影响

Details of Self-Attention

Encoder部分能支持并行化训练的关键就在于Self-Attention。不严谨的说,自注意力机制就是利用xi之间两两相关性作为权重的一种加权平均,将每一个xi映射到zi

如上图所示,x1 和 x2 表示“Thinking”和“Machines”的word embedding。此时可以说x1 和 x2 都只代表自己这个单词的信息,没有考虑局部依赖关系。自注意力机制首先计算了 x1 与 x1 和 x2 之间的相关性,记为θ11和θ12,z111v112v2 (v1和v2是value值,后面会提到),通过对v1、v2加权平均的方式得到z1,θ11和θ12可以理解为权重,权重越大表示相似度越大,z1就表示"Thinking"和其他词(假设一个句子中就Thinking和Machines两个单词,如果有多的单词,就是v1、v2、v3、…的加权平均)之间的依赖关系,同理z2就表示Machines和其他其他单词的依赖关系
每个zi可以看作是对应单词在考虑全局依赖后的一种embedding,不同的zi对不同的xi注意力分布不同,换句话说,在计算每一个zi时,需要的是全体xi,而不是依赖zi-1,所以Encoder可以并行化计算所有的zi,而无需像RNN那样严格按照时序依次迭代计算

  1. 论文中引入了三个矩阵作为辅助,来表征注意力的强弱,分别是Q(Query)、K(Key)、V(Value)

    如图所示,X是输入句子Embedding后的结果,x1和x2是其中的两个单词。x1转换成了三个不一样的向量,分别叫q1、k1、v1,x2同样转换成了三个不一样的向量,分别叫q2、k2、v2。Q、K、V是由X线性映射得到
      q1=x1WQ    q2=x2WQ
      k1=x1WK    k2=x2WK
      v1=x1WV    v2=x2WV
    上述过程中,不同的xi共用了同一个WQ、WK、WV ,也就是说,通过共享权值,x1和x2在某种程度上有着一定的信息交换

  2. 计算self-attention的值,该值决定了当我们在某一个位置encode一个单词时,对句子的所有单词的关注程度。q1和q2分别代表Thinking和Machines对应的query vector,k1和k2分别代表Thinking和Machines对应的key vector,则计算Thinking的attention score是计算q1与k1、k2的点乘,即q1·k1和q1·k2 (Thinking和Machines是论文中举的例子)
    点乘: a·b = |a||b|cos<a, b>,两个向量越相似点积越大,例如当两个向量重合时点积是最大的,当两个向量垂直时点积为0

  3. 将self-attention score进行一个softmax的计算,然后把Value和Softmax得到的值进行线性组合,便可得到z1和z2,有了z1和z2,再通过全连接层,就能输出Encoder层的输出r1和r2
    KaTeX parse error: Invalid size: 'θ_{11}, θ_{12}' at position 78: …_{22}v_{2} \\ [̲θ̲_̲{̲1̲1̲}̲,̲ ̲θ̲_̲{̲1̲2̲}̲]̲ = softmax(\fra…
    式子中的dk是向量q或k的维度,向量q和向量k的维度一定是一样的,因为向量q和向量k要做点积。而v的维度和向量q或k的维度不一定相同 (图中除以8是论文中举的例子)

    为何要除以√dk 论文中给了解释,是为了把注意力矩阵变成标准正态分布,使得softmax归一化之后的结果更加稳定:
    在这里插入图片描述
    在这里插入图片描述

  4. 这里用矩阵运算(矩阵运算可以用GPU加速),就是把输入的所有向量合并成矩阵形式,所有的Query、Key、Value向量也合并成了矩阵形式,用公式表示就是:
    A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q, K, V) = softmax(\frac{QK^{T}}{\sqrt{d_{k}}})V Attention(Q,K,V)=softmax(dk QKT)V

Multi-headed Attention

类似于卷积神经网络中的filter,一种卷积核可以在原始图像中提取出一种特征,可以用多种卷积核堆叠来提取多种特征。Encoder中一组Q、K、V能得到一组当前词的特征表达,如果用不同的WQ、WK、Wv,就能得到不同的Q、K、V,好处是有多个Q、K、V就能得到多个特征表达,可以从多个角度来看待Attention,也就是可以让Attention有更丰富的层次。一般有8个head就差不多了

将多个特征z拼接成一个长的向量,然后通过一层全连接层进行降维,也就是乘以一个矩阵WO

下图用了八个Attention,从蓝色到灰色分别用八种不同的颜色表示,我们可以看到以一个单词在八个Attention上对句子里每个单词的权重。这里只挑出橙色和绿色,先看橙色部分,对单词it进行编码时,连接的权重最大的是animal,说明最关注的是animal,再看绿色部分,它的注意力集中在tired上。所以模型对it这个单词的特征体现在animal和tired上
在这里插入图片描述

Attention Mask – Padding Mask

在上面的self attention的计算中,x的维度是[batch size, max sequence length],我们通常使用mini batch来计算,也就是一次计算多句话,一个mini batch是由多个不等长的句子组成,我们就需要按照这个mini batch中最大的句长进行补齐长度,一般是用0进行填充,这个过程叫做padding
但这时进行softmax的时候就会产生问题,回顾softmax函数 σ ( z ) i = e z i ∑ j = 1 K e z j σ(z)_{i} = \frac{e^{z_{i}}}{\sum\limits_{j=1}^{K}e^{z_{j}}} σ(z)i=j=1Kezjezi,e0是1,是有值的,这样的话softmax中被Padding的部分就参与了运算,就等于是让无效的部分参与了运算,会产生很大的隐患

这时就需要做一个mask让这些无效区域不参与运算,我们一般给无效区域加一个很大的负数的偏置,也就是:
z i l l e g a l = z i l l e g a l + b i a s i l l e g a l b i a s i l l e g a l → − ∞ z_{illegal} = z_{illegal} + bias_{illegal} \\ bias_{illegal} →-∞ zillegal=zillegal+biasillegalbiasillegal
e-∞ 基本上为0,就不会对softmax造成影响

Positional Encoding(位置编码/位置嵌入)

输入模型的数据不仅要有word embedding还要有positional embedding,这是为了让网络知道这个单词所在句子中的位置,也就是想让网络在做Self-Attention时不但要知道注意力聚焦在哪个单词上,还要知道单词之间的相互距离

Q: 为何要知道单词之间的相对位置?
A: Transformer模型没有RNN的迭代操作,为了让模型能利用序列的顺序,必须输入每个字的位置信息给Transformer,才能识别出语言中的顺序关系

论文中是使用sin和cos函数来提供模型位置信息
P E p o s , 2 i = s i n ( p o s 1000 0 2 i / d m o d e l ) PE_{pos, 2i}=sin(\frac{pos}{10000^{2i/d_{model}}}) PEpos,2i=sin(100002i/dmodelpos)
P E p o s , 2 i + 1 = c o s ( p o s 1000 0 2 i / d m o d e l ) PE_{pos, 2i+1}=cos(\frac{pos}{10000^{2i/d_{model}}}) PEpos,2i+1=cos(100002i/dmodelpos)
上式中,pos指的是句中字的位置,取值范围是[0, max sequence length),i指的是词向量的维度,取值是[0, embedding dimension),sin和cos则是对应着embedding dimension维度的一组奇数和偶数序号的维度
举例:

维度解析

这里强推b站视频,讲的是真的好 从零解读碾压循环神经网络的transformer模型(一) - 注意力机制 - 位置编码 - attention is all you need

  1. 输入X的维度是 [batch size, max sequence length]
  2. 经过Input Embedding,查询词库表 (词库表的维度是 [vacab size, embedding dimension]) 得到字的词向量Embedding Lookup,维度是 [batch_size, max sequence length, embedding dimension]
  3. Positional Embedding的维度是 [max sequence length, embedding dimension]
    Xembedding = Embedding Lookup(X) + Positional Embedding
    Xembedding的维度是 [batch size, max sequence length, embedding dimension]
  4. 对Xembedding做线性映射,也就是分配三个权重矩阵WQ、WK、Wv,这三个权重矩阵维度是 [embedding dimension, embedding dimension],矩阵相乘得到Q、K、V三个矩阵,和线性变换之前的维度一致
  5. 进行多头注意力机制,也就是multi head attention,因为要用多头注意力机制来提取多重语意的含义,首先定义head的数量(num of heads / h),注意embedding dimension必须整除h,因为要把embedding dimension分割成h份
    分割后Q、K、V的维度是 [batch size, max sequence length, h, embedding dimension / h]
    之后我们把Q、K、V中的max sequence length, h进行一下转置,是为了方便后续的计算,则转置后的Q、K、V的维度是 [batch size, h, max sequence length, embedding dimension / h]
    在这里插入图片描述
  6. 计算Q与K.T的乘积,从图中可以看到,注意力矩阵的第一行第一列是c1c1,含义是第一个单词与第一个单词的注意力机制,然后依次向后求得c1c2,c1c3, …,所以每一行指的是当前字与句子中所有字的关联程度,要使得每一行的关联程度的和为1,也就是要使得每个字与句中所有字的注意力权重的和为1,需要进行softmax操作,也就是沿着列进行softmax归一化
  7. 注意力矩阵的作用就是一个注意力权重的概率分布,我们要用注意力矩阵的权重给V进行加权

    上图中,我们从注意力矩阵取出一行(和为1)然后依次点乘V的列,矩阵V的每一列代表着每个字向量的数学表达,也就是用注意力权重进行这些数学表达的加权线性组合,从而使得每个字向量都含有当前句子内所有字向量的信息
Decoder

Decoder也是由若干个layers堆叠而成,上层的layer接受下层layer的输出作为输入,这和encoder是一样的,Decoder每一层的结构和encoder很类似,只是在下面的Multi head self attention是经过masked,并且多了Encoder-Decoder Multi-head Attention

Shift Right

在这里插入图片描述
以翻译为例:

  • 输入:我爱中国
  • 输出: I Love China

因为输入(“我爱中国”)在Encoder中进行了编码,这里我们具体讨论Decoder的操作,也就是如何得到输出(“I Love China”)的过程
Decoder执行步骤
Time Step 1

  • 初始输入: 起始符 + Positional Encoding(位置编码)
  • 中间输入:(我爱中国)Encoder Embedding
  • 最终输出:产生预测“I”

Time Step 2

  • 初始输入:起始符 + “I”+ Positonal Encoding
  • 中间输入:(我爱中国)Encoder Embedding
  • 最终输出:产生预测“Love”

Time Step 3

  • 初始输入:起始符 + “I”+ “Love”+ Positonal Encoding
  • 中间输入:(我爱中国)Encoder Embedding
  • 最终输出:产生预测“China”

Shifted Right实质上是给输出添加起始符/结束符,方便预测第一个输出/结束预测的过程

Sequence mask

Encoder中的self-attention使用了padding mask,而Decoder还需要防止标签泄露,即在t时刻不能看到t时刻之后的信息,因此为了防止模型提前看到待预测的内容,在上述padding mask的基础上,还要加上sequence mask
在这里插入图片描述
上三角区域全部设为-inf,由于e-∞=0不会对softmax造成影响

Encoder-Decoder Multi-head Attention

Decoder中的第二层注意力层,输入不仅有前一层的输出x,还有来自Encoder的输出m,然后把Encoder产生的向量m作为Decoder的Key和Value,Decoder的x作为Query,然后进行Self-Attention
Q=xWQ    K = mWK    V = mWv

参考资源

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.DoubleBean.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值