https://www.jianshu.com/p/25fc600de9fb

谷歌最近的一篇BERT取得了卓越的效果,为了研究BERT的论文,我先找出了《Attention is All You Need》,看看里面的Transformer模型作为基础。

Transformer是为了机器翻译任务中的问题所提出的。

传统的RNN神经网络结构是可以处理任意长度的输入,它非常适合于自然语言的建模,所以它在一段时间内占据了整个神经网络中的主流。随着学术的发展,我们也会看到RNN有些不足。

RNN的缺点主要有两点:

  • RNN序列的特性导致其非常难以并行化
  • 在RNN训练中,RNN的网络结构对于长距离和层级化的依赖关系难以建立

关于第二点举个例子:“The dog didn’t cross street because it wastoo tired”,当我们看到“tired”的时候知道这个it指dog 。如果把最后一个词换了,“The dog didn’t cross street because it was too wide”,这时候如果是人看了这句话就很容易发现it 指的是street,因为street because it was wide,不可能是dog too wide。对于人来说很简单,但是机器要分清楚指代关系是非常难的。

所以人们开始探索新的网络结构,例如FaceBook提出的《Convolutional Sequence to Sequence Learning》。

Google在这一问题上的探索结果便是Transformer。Transformer这个网络命名,Transformer在英文翻译过来有变形金刚的意思。

1. 整体结构

从整体上来看,Transformer依旧是一个“Sequence to Sequence”框架,拥有Encoder和Decoder两部分:

 
Transformer的整体结构

Transformer的Encoder其实有6层,Decoder也有6层,从Encoder的角度,低层的Encoder是表层的词法信息,逐步向上进行抽象之后,在上层将表示抽象语义信息。Encoder部分还在最上层连了几条线到每个Decoder的部分,这是为了在Decoder中进行Attention操作,Decoder的网络中和Encoder也有信息传递和交互的。最后一个特点是Decoder和Encoder画的大小是一样的,因为它们层的维度大小是一样的。

 
 

多层的神经网络结构能够对句子层级化信息进行建模,如果我们更精细的去看每一层的结构,就会发现这样的情况:Encode分两个子网络部分,第一个是Self-Attention,第二个部分是Feed Forward。

Self-Attention是自注意力机制层,表征句子当中不同位置词之间的关系,是我们前面提到的it和street 或dog之间的依赖关系。

 
 

2. Self-Attention

首先在做DeepNLP任务时,我们都会使用word2vec等技术生成词向量:

 
 

注:这里对词向量的维数都做了简化,以方便后面说明

那么首先要明白什么是Attention。从语言学的角度,它是表示词与词之间的关联关系,像下图所示,这是一个Self-Attention的示意,它这个it会和其他位置的词发生关系,颜色越深的是说关系越紧密,从中图中看到它很正确的关联到了animal它实际指代的一个词。

 
 

从机器学习的角度,这个Attention是神经网络隐层之间一个相似度的表示,什么是Self-Attention?就是表示句子内部词与词之间的关联关系,就像这里的it到animal,可以用于指代消解等问题。

在Transformer中提出一种扩展性更高、并行度更高的Attention计算方式,它把Attention看作一个基于内容的查询的过程,content based query,它会设置3个vector:QueryVector、Key Vector、Value Vector。并且每一个Vector都是通过它的input embedding和权重的矩阵相乘得到的。利用这个Q、K、V进行各种数值的计算,最终得到Attentionscore。

 
 
 
计算公式
 
 

用一个例子来给大家演示具体的Attention是怎么计算的。如果我们计算“Thinking”这个词,用Self-Attention的话,首先会用它的Query Vector乘以K的向量,如果计算和第二个位置的attention是乘以T2的矩阵得到一个score,这个score再去和它维度的平根根进行相除,这个相除有数学上的含义,能够使它回传的梯度更加稳定,除完后得到一个数值进行softmax,所有Attention都是正数并且相加之和等于1,这是从数学正确上考虑,并且最终得到概率这个值是去定义每一个词在当前位置的表现力。Softmax之后,我们会用softmax得到的乘以它Value的矩阵,这样实际得到Attention的值,最后会把不同位置得到Attention的score加到一起,形成当前位置Attention的Vector,就是Z1,加上逐词计算的话就得到所有位置的Attention。

 
 

使用矩阵形式来表示:

 
 
 
 

3. Multi-head Attention

这个是Google提出的新概念,是Attention机制的完善。不过从形式上看,它其实就再简单不过了,就是把Q,K,V通过参数矩阵映射一下,然后再做Attention,把这个过程重复做h次,结果拼接起来就行了

 
 
 
 
 
 
 
 

4. Positional Encoding

这样的模型并不能捕捉序列的顺序!换句话说,如果将K,V按行打乱顺序(相当于句子中的词序打乱),那么Attention的结果还是一样的。这就表明了,到目前为止,Attention模型顶多是一个非常精妙的“词袋模型”而已。

Position Embedding,也就是“位置向量”,将每个位置编号,然后每个编号对应一个向量,通过结合位置向量和词向量,就给每个词都引入了一定的位置信息,这样Attention就可以分辨出不同位置的词了。

在以往的Position Embedding中,基本都是根据任务训练出来的向量。而Google直接给出了一个构造Position Embedding的公式:

 
 

这里的意思是将id为p的位置映射为一个dpos维的位置向量,这个向量的第i个元素的数值就是PEi(p)。

Position Embedding本身是一个绝对位置的信息,但在语言中,相对位置也很重要,Google选择前述的位置向量公式的一个重要原因是:由于我们有sin(α+β) = sinαcosβ+cosαsinβ 以及 cos(α+β)=cosαcosβ−sinαsinβ,这表明位置p+k的向量可以表示成位置p的向量的线性变换,这提供了表达相对位置信息的可能性。

 
 

这上面的编码结果好像有点问题,我运行了哈佛的代码后的结果如下,也可能我哪里没有理解清楚,希望有明白的大佬给我指点下。

 
 

需要注意的一点,结合位置向量和词向量其实有好几个可选方案,可以把它们拼接起来作为一个新向量,也可以把位置向量定义为跟词向量一样大小,然后两者加起来。Google论文中用的都是后者。

5. Position-wise Feed-Forward Networks

 
 
 
 

虽然线性变换在不同位置上是相同的,但它们在层与层之间使用不同的参数。 另一种描述这种情况的方法是两个内核大小为1的卷积。

6. Residual connection和layer-normalization

对于学习CV的人估计对这个结构一点也不陌生,Residual connection是对于较为深层的神经网络有比较好的作用,比如网络层很深时,数值的传播随着weight不断的减弱,Residual connection是从输入的部分,就是图中虚线的部分,实际连到它输出层的部分,把输入的信息原封不动copy到输出的部分,减少信息的损失。

 
 

layer-normalization这种归一化层是为了防止在某些层中由于某些位置过大或者过小导致数值过大或过小,对神经网络梯度回传时有训练的问题,保证训练的稳定性,这是神经网络设计比较常用的case。

基本在每个子网络后面都要加上layer-normalization、加上Residual connection,加上这两个部分能够使深层神经网络训练更加顺利。

 
 

到此为止,Encoder部分其实基本上就已经结束了,Decoder部分其实大多数结构都与Encoder部分相同,但是它的Attention部分还是有一些小小的不同。

7. Encoder-Decoder Attention

 
 

由上图可以看到,Decoder 部分除了Self-Attention的机制之外,还有Encoder-Decoder Attention。

其实,Encoder-Decoder Attention就是平常使用的Attention:

 
 

8. 小节

 
 

总体流程(上图是只画两层的Encoder和Decoder):

  1. 将底层的词的输入转化为embedding的输入,X1、X2
  2. 加上“Positional Encoding”的输入
  3. 输入到第一个Encoder当中,经过self-Attention层,直连的“Residual connection”和归一化层,得到的输出
  4. 将其输入到前馈神经网络中,前馈神经网络出来之后再经过直连层和归一化层,这样就完成了一个Encoder部分
  5. 再以这个输入到第二个Encoder之后,它会把第二个Encoder的输出(这里由于只有两层,所以第二个Encoder就是最后Encoder)作为第一个Decoder的输入,也是依次进行上面的过程
  6. 最后就是通过一个liner层之后由softmax层转化概率输出
 
 

注意:目标端的Attention注意力机制是一个masked注意力机制,为什么?比如在机器翻译当中,在源端能够看到所有的词,但如果你目标端生成翻译时是自左上右,生成翻译时能够看到前面已经生成词的信息,看不到后面层的,这是目标端Attention和源端Attention比较大的区别,所以在目标端所有的Attention都是加Masked的,这个Masked相当于把后面不该看到的信息屏蔽掉

参考:

  1. https://kexue.fm/archives/4765
  2. pytorch代码实现
  3. https://jalammar.github.io/illustrated-transformer/
  4. https://mp.weixin.qq.com/s/w3IKoygTLDsAxk1MB5JrGg

作者:freedom_king
链接:https://www.jianshu.com/p/25fc600de9fb
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

《Attention is All You Need》的更多相关文章

  1. 《Attention is All You Need》浅读(简介+代码)

    2017年中,有两篇类似同时也是笔者非常欣赏的论文,分别是FaceBook的<Convolutional Sequence to Sequence Learning>和Google的< ...

  2. bert系列一:《Attention is all you need》论文解读

    论文创新点: 多头注意力 transformer模型 Transformer模型 上图为模型结构,左边为encoder,右边为decoder,各有N=6个相同的堆叠. encoder 先对inputs ...

  3. 关于注意力机制(《Attention is all you need》)

    深度学习做NLP的方法,基本上都是先将句子分词,然后每个词转化为对应的词向量序列.(https://kexue.fm/archives/4765) 第一个思路是RNN层,递归进行,但是RNN无法很好地 ...

  4. 《attention is all you need》解读

    Motivation: 靠attention机制,不使用rnn和cnn,并行度高 通过attention,抓长距离依赖关系比rnn强 创新点: 通过self-attention,自己和自己做atten ...

  5. 《Attention Augmented Convolutional Networks》注意力的神经网络

    paper: <Attention Augmented Convolutional Networks> https://arxiv.org/pdf/1904.09925.pdf 这篇文章是 ...

  6. 王之泰201771010131《面向对象程序设计(java)》第七周学习总结

    王之泰201771010131<面向对象程序设计(java)>第七周学习总结 第一部分:理论知识学习部分 第五章 第五章内容深度学习: 继承:如果两个类存在继承关系,则子类会自动继承父类的 ...

  7. 杨其菊201771010134《面向对象程序设计(java)》第六周学习总结

    <面向对象程序设计(java)>第六周学习总结 第一部分:理论知识 1)类.超类和子类2)Object:所有类的超类 3)泛型数组列表4)对象包装器和自动打包 5)参数数量可变的方法 6) ...

  8. 201871010116-祁英红《面向对象程序设计(java)》第七周学习总结

    项目 内容 <面向对象程序设计(java)> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/ ...

  9. 201871010111-刘佳华《面向对象程序设计(java)》第七周学习总结

    201871010111-刘佳华<面向对象程序设计(java)>第七周学习总结 实验时间 2019-10-11 1.实验目的与要求 1) 掌握四种访问权限修饰符的使用特点: (1)进一步理 ...

随机推荐

  1. linux java报错汇总

    一:♦linux 下javac 编译报 需要class, interface 或enum错误   ♦解析时已到达文件结尾 原因:大括号补匹配  //注意看报警提示  

  2. python+selenium九:ddt数据驱动

    第一种,测试数据放在Excel里面 test_Login: import unittestimport timeimport ddtimport osfrom selenium import webd ...

  3. springMVC源码分析--视图AbstractView和InternalResourceView(二)

    上一篇博客springMVC源码分析--视图View(一)中我们介绍了简单介绍了View的结构实现及运行流程,接下来我们介绍一下View的实现类做的处理操作. AbstractView实现了rende ...

  4. python 全栈开发,Day65(MySQL练习题,参考答案)

    一.MySQL练习题 一.表关系 请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号.ps:针对的是自己的生物成绩比物理成绩高,再 ...

  5. 主机可以ping通虚拟机,但是虚拟机ping不通主机的方法(转)

    https://blog.csdn.net/hskw444273663/article/details/81301470

  6. myBatis各种依赖包

    下载地址:myBatis各种依赖包

  7. scanf的一个问题(暂未解决)

    如下代码,没有按照预想的那样运行: int a; char b; printf("input a integer\n"); scanf("%d", &a ...

  8. javax.inject包

    javax.inject包 java提出的依赖注入标准,有别于以下传统的对象获取方式 构造方法 工厂模式 服务器定位模式(e.g. JNDI) 开发过程中是会有很多层层依赖的对象的,例如,Stopwa ...

  9. POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)

    题意:John的农场里field块地,path条路连接两块地,hole个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts.我们的任务是知道会不会在从某块地出发后又回来,看到了离开之前 ...

  10. Codeforces 160D Edges in MST tarjan找桥

    Edges in MST 在用克鲁斯卡尔求MST的时候, 每个权值的边分为一类, 然后将每类的图建出来, 那些桥就是必须有的, 不是桥就不是必须有. #include<bits/stdc++.h ...