教育软件(学习科学与智能教育)学习讨论小组

04-Transformer(Attention Is All

2019-10-10  本文已影响0人  HsuanvaneCHINA

本文是观看B站视频(传送门:https://www.bilibili.com/video/av48285039/?p=92
)后做的笔记,一方面加深理解,另一方面方便日后复习的时候不用重头再来。


transformer有一个非常出色的应用叫做BERT,下一篇将会说明BERT,我会在学习后做好笔记并把它上传。

1.引入

在讲transformer之前,我想提一下RNN,我们都知道RNN非常擅长处理这些input是sequence,但是它有个问题,不容易被平行化(单向信息流),也就是说每个word Embedding都不能同时计算,而需要按照顺序执行。


那么现在就有人提出用CNN来代替RNN。


但是单层的CNN相比RNN考虑的序列有限,如上图中它只考虑了4个vector。为了考虑更长的序列,这就需要增加CNN的层数,那么第二层的filter卷积核会将第一层的输出Output当成它的Input。

CNN的优势在于可以不需要等待第一个filter卷积核计算完成,自己才能进行计算,它达到了平行的状态,也就是说所有的filter卷积核能够同时进行计算。
而伴随二楼的CNN的缺点就是必须要叠加很多层,以便为了得到上下文的更多信息,反之只能得到很少的范围。

2.Self-Attention

那么为了解决这个问题,self-attention应运而生,它取代了RNN可以做的事情(Input是sequence,output也是sequence),它特别的地方是相比于RNN(需要按顺序执行),如下图b1到b4它是可以同时进行计算的。


下面将对self-attention以及multi-head attention的原理进行介绍,进而引出transformer模型

2.1Self-Attention从输入到输出到底发生了什么?(含详细计算过程)

Self-attention出现在google发表的一篇论文名为Attention is all you need中(原文地址:https://arxiv.org/abs/1706.03762).

2.1.1q,v,k分别是什么,怎么产生的?

首先,这里的input是x^1x^4,然后通过Word Embedding再乘上matrix W变成a^1a^4,然后把它们丢进self-attention 层中,这时候每一个input都分别乘上3个不同的matrix产生3个不同的vector,分别把它们命名为q,k,v

q代表的是查询向量,query (to match others用来去匹配其它的向量)
k代表的是地址向量,key (to be matched用来去被query匹配的向量)
v代表的是内容向量,value(information to be extracted用来被抽取的信息的向量)

2.1.2用q和k做attention,得到α向量


现在要做的工作就是用每个query 去对每个 key 做attention(吃2个向量,输出就是告诉你这2个向量有多么匹配或者可以说输入两个向量输出一个分数(而怎么去吃2个向量output一个分数,有很多不同的做法))。

这里的公式被称为 Scaled Dot-Product Attention 被缩放的点积 注意力,它是由向量q与向量k做点积然后除以\sqrt{d},这里的\sqrt{d}指的是qk向量的维度。
至于为什么要除以\sqrt{d},一种直观的解释是qk的点积会随着它们维度的增加,点积中相加的子项就越多,所以除以\sqrt{d}(论文有注解。)(思考:如果这里的点积换成其他的方式,效果会不会更好?)

这里普及下点乘的几何意义:

可以用来表征或计算两个向量之间的夹角,以及在$b$向量在$a$向量方向上的投影
     a·b>0    方向基本相同,夹角在0°到90°之间

     a·b=0    正交,相互垂直  

     a·b<0    方向基本相反,夹角在90°到180°之间 

2.1.3soft-max


接下来要做的是Soft-max,会将到通过Soft-max层得到biaozheng到 。

2.1.4得到输出b


我们用和每一个v相乘,和相乘加上和相乘。以此类推并相加,最终得到。

刚才说self-attention就是输入一个sequence输出一个sequence,现在我们已经得到了要输出的sequence的第一个vector b^1,这时候的b^1,根据它的计算过程使得它考虑到了全部的sequence。

这里考虑一下得到b的其他情况:

这就做到了想截取input哪部分的sequence,self-attention都可以实现它。


因为self-attention是可以同时进行计算的,那么self-attention可以在计算b1的时候同时计算b^2b^3b^4,计算过程与b^1相同,他们这些表征向量是可以平行的计算出来。

2.1.5整体架构


如果以黑盒的角度看,self-attention的机制就是这样的。

2.2self-attention进阶版

下面根据2.1的内容,更详细的说明self-attention每一步是怎么进行计算的。

2.2.1q,v,k分别是什么,怎么产生的?

整体思路:输入信息,通过线性变换得到为查询向量序列,键向量序列和值向量序列。

首先看第一行:

这时候我们可以把q^1q^4拼接起来作为一个matrix。概括一下将a^1a^4整合为I,将q^1q^4整合为Q,整体为Q=W^qIq代表每个位置的query。

同理,对于k向量的计算同q向量。将k^1k^4整体概括为K。整体为K=W^kI
对于v向量的计算也同q向量。将v^1v^4整体概括为V。整体为V=W^vI

2.2.2用q和k做attention,得到α向量;soft-max得到\widehat {a}


之前说我们用每一个向量去和做attention,其实是做点积。

这里将k做转置与q点积,可以将\sqrt{d}省去,让式子更加简化。
那么α_{1,1} = k^1q^1α_{1,2} = k^2q^1α_{1,3} = k^3q^1α_{1,4} = k^4q^1 ,在这个过程中我们发现所有式子都用到了q^1,那么这时候我们将q^1提取出来,将k^1k^4叠放在一起成为一个matrix矩阵,那么这时候q^1乘以这个matrix矩阵,得到的结果是α_{1,1}α_{1,4}的matrix矩阵。


同理,到的计算过程和一样,和到组成矩阵相乘得到到,依此类推。

我们将q^1q^4组成的向量叫做Q,k^1k^4组成的向量转置叫做K^T,他们之间相乘的结果为A,经过softmax得到\widehat {a}

2.1.3得到输出b

现在按照之前的步骤,我们要得到b,此时按照线性代数的公式,用v^1v^4组成的矩阵V乘以\widehat {A}矩阵,即V的行去相乘相加\widehat {A}矩阵的每一列,第一次计算得到b^1,以此类推直到b^4。将b^1b^4的向量组成矩阵O(也是整个self-attention层的输出)。

2.1.4回顾

现在我们再将刚才的运算回顾一下,我们将a^1a^4组成的输入叫做I(以下用I来指代),输出b^1b^4叫做O。下面我们梳理下从IO这个过程之中,self-attention层做了哪些事情。
1.首先,我们将I分别和三个不同的matrix相乘,w^qw^kw^v。我们得到了q^1q^4向量组成的矩阵Qk^1k^4向量组成的矩阵Kv^1v^4组成的矩阵V
2.然后,我们用矩阵QK的转置k^{T}相乘(为了省去\sqrt{d},让式子简化),得到了A矩阵(attention矩阵),每个元素α代表的是input输入的的sequence每个位置上的两两之间的attention(即概率分布)。
3.然后A矩阵经过softmax计算,成为了\widehat {A}矩阵
4.最后,\widehat {A}矩阵与V矩阵相乘就得到了输出O矩阵。

Tips:我们发现self-attention中做的就是一连串的矩阵乘法,我们可以使用GPU进行加速计算。

3.Multi-head Self-attention 多头自注意力机制


除了self-attention,现在还有多头自注意力机制 Multi-head Self-attention。下面以2头注意力机制作为说明。

多头的关键之处就在于,分别将q,k,v向量继续细分为q^{i,1},q^{i,2};k^{i,1},k^{i,2};v^{i,1},v^{i,2}

这里的q^{i,1}只和位置在1的k进行相乘,如q^{i,1}乘以k^{i,1}k^{j,1},得到\alpha,然后经过soft-max的\widehat {\alpha},再和v^{i,1}v^{j,1}相乘相加,最终得到b^{i,1}

同理,q^{i,2}同上q^{i,1},最终得到b^{i,2}


进行到这一步,这时候我们拥有了和,如果不想要和组成的矩阵的维度(这里是2),我们可以进行降维,得到。
这样多头的机制有什么好处呢?在论文中,不同的head它们关注的部分不同,这样每个head会各司其职注意力集中于各自的区域,

(换句话说,多头注意力(multi-head attention)是利用多个查询Q = [q^1, · · · , q^M],来平行地计算从输入信息中选取多个信息。每个注意力关注输入信息的不同部分,然后再进行拼接)

在模型中head的个数也是超参数,可以进行调优。

4.Transformer在此前的基础上改进了什么?


我们这里有个问题,对于self-attention来说,它的Input的sequence是没有顺序的,这显然不是我们想要的。

在Transformer的论文中,我们手动设定了位置编码向量e^i,它代表了位置信息,我们就可以知道某个a^i现在在哪个位置。

那么这里可能会有疑问,直接将位置向量e^i和输入向量a^i相加会不会导致向量混乱影响结果,这里对e^i的产生有一种解释(与原论文不同,但是最后的公式一致):

在输入x^i的时候,每个输入的x^i再加入一个用one-hot编码的向量pi用来代表位置信息。
1.将x^ip^i进行拼接;
2.然后与W(W分为W^IW^P)相乘得到Embedding,
3.根据线性代数公式W^Ix^i相乘,W^Pp^i相乘然后相加。

对比上面的式子e^i+a^iW^Ix^i相乘就得到a^iW^Pp^i相乘然后相加就得到e^i

而在原论文中比较匪夷所思的是,W^P是人工设置的。


右边的图形就是的样子。

4.1什么是Transformer?

Transformer就是seq2seq model with Attention。

4.2从Input到output发生了什么?

Encoding的时候所有输入的序列的词,两两进行attention,这些attention是平行的,有三层所以做三次。

Decoding的时候,不仅会attend之前已经输入的部分还有已经输出的部分。

4.3Transformer内部原理

一个seq2seq的model,左边是encoder,右边是decoder,希望输入中文输出是英文。

比如输入的是机器学习
首先decoder给一个BOS的token,decoder输出machine,然后将machine作为输入,输出learning,然后知道输出句点,就结束了。

下面解释下transformer内部发生了什么?
左半部分:
1.input通过一个input Embedding层变为vector;
2.vector会加上位置编码进入block,这个block会重复N次;
3.block的第一层是multi-head attention,通过它会得到另一个sequence;


4.然后是add&norm,其中add是:将multi-head attention的输出b和输入a加起来b';norm是:将b'经过layer norm做layer normalization(详情见https://www.jianshu.com/p/c357c5717a60);
5.经过add&norm,vector会进入feed forward进行处理(简单的全连接网络,对每个position的向量分别进行相同的操作,包括两个线性变换和一个ReLU激活输出),然后再进行add&norm;

右半部分:
1.decoder的底部的output是由前一个向量计算产生的结果作为输入;
2..同理。vector会加上位置编码进入block,这个block会重复N次;
3.进入第一层,block的第一层是masked multi-head attention。这里的masked是attend on the generated sequence,意思就是decoder只会参加到已经产生出的sequence中(由于是序列生成过程,所以在时刻 i 的时候,大于 i 的时刻都没有结果,只有小于 i 的时刻有结果,所以没有产生出来的向量是不存在的,无法进行attention),然后进行add&norm;
4.之后进入一层 multi-head attention,它的输入是之前encoder部分的输出;
5.然后再与3.的输出进行add&norm,之后进入feed forward进行处理,进入add&norm,然后是linear层(Linear层就是一个全连接网络,作用是把decoder输出的向量映射到一个大很多的logits 向量上。)
6.经过softmax计算后输出分数最高的那个词就是这一步的输出。

4.4Transformer的应用场景


transformer的应用场景:
只要是可以用seq2seq,就可以用transformer

上一篇下一篇

猜你喜欢

热点阅读