深度学习——attention机制

一、序列编码

目前主流的处理序列问题像机器翻译,文档摘要,对话系统,QA等都是encoder和decoder框架,
编码器:从单词序列到句子表示
解码器:从句子表示转化为单词序列分布

深度学习——attention机制_第1张图片
 

1、第一个基本的思路是 RNN 层

RNN 的方案很简单,递归式进行:

8a394feeefe34cef647edfcfb30b9af303c39d52

但是,这种方式会有一个问题:对于长句子的翻译会造成一定的困难,而attention机制的引入可以解决这个问题。(为什么引入注意力模型?因为没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入的句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多的细节信息,所以要引入注意力机制)如下图所示:

深度学习——attention机制_第2张图片

 理解Attention模型的关键就是,由固定的中间语义表示C换成了根据当前输出单词来调整成加入注意力模型的变化的Ci.而每个Ci可能对应着不同的源语句子单词的注意力分配概率分布。

RNN+Attention:

这里,我们可以看到,decoder得到的序列中有几个输出值,对应的语义编码c则有相同的数量,即一个语义编码ci对应一个输出yi。而每个ci就是由attention机制得到,具体公式如下:

深度学习——attention机制_第3张图片

其中:ci:encoder序列加权得到的值; si:    ; yt:  

Neural machine translation by jointly learning to align and translate

这篇论文首先将注意力机制运用在NLP上,提出了soft Attention Model,并将其应用到了机器翻译上面。其实,所谓Soft,意思是在求注意力分配概率分布的时候,对于输入句子X中任意一个单词都给出个概率,是个概率分布。加入注意力机制的模型表现确实更好,但也存在一定问题,例如:attention mechanism通常和RNN结合使用,我们都知道RNN依赖t-1的历史信息来计算t时刻的信息,因此不能并行实现,计算效率比较低,特别是训练样本量非常大的时候。

不管是已经被广泛使用的 LSTM、GRU 还是最近的 SRU,都并未脱离这个递归框架。RNN 结构本身比较简单,也很适合序列建模,但 RNN 的明显缺点之一就是无法并行,因此速度较慢,这是递归的天然缺陷。

另外我个人觉得 RNN 无法很好地学习到全局的结构信息,因为它本质是一个马尔科夫决策过程

2、第二个思路是 CNN 层

其实 CNN 的方案也是很自然的,窗口式遍历,比如尺寸为 3 的卷积,就是:

09d4159dee99ecde9e27dddc4e15a039df15827c

基于CNN的Seq2Seq模型具有基于RNN的Seq2Seq模型捕捉long distance dependency的能力,此外,最大的优点是可以并行化实现,效率比基于RNN的Seq2Seq模型高。缺点:计算量与观测序列X和输出序列Y的长度成正比。

CNN+Attention:

深度学习——attention机制_第4张图片

在 FaceBook 的论文中,纯粹使用卷积也完成了 Seq2Seq 的学习,是卷积的一个精致且极致的使用案例,热衷卷积的读者必须得好好读读这篇文论。

3、Google的大作提供了第三个思路:纯 Attention,单靠注意力就可以。

RNN 要逐步递归才能获得全局信息,因此一般要双向 RNN 才比较好;CNN 事实上只能获取局部信息,是通过层叠来增大感受野;Attention 的思路最为粗暴,它一步到位获取了全局信息,它的解决方案是:

01d4e0756a4f0e090f53a6e779bdb8cc91586dd5

其中 A,B 是另外一个序列(矩阵)。如果都取 A=B=X,那么就称为 Self Attention,它的意思是直接将 xt 与原来的每个词进行比较,最后算出 yt。

本文的创新点在于抛弃了之前传统的encoder-decoder模型必须结合cnn或者rnn的固有模式,只用attention。文章的主要目的是在减少计算量和提高并行效率的同时不损害最终的实验结果,创新之处在于提出了两个新的Attention机制,分别叫做 Scaled Dot-Product Attention 和 Multi-Head Attention.

深度学习——attention机制_第5张图片

 回顾了传统的attention模型之后,我们看一下google翻译团队对attention模型的高度抽取概况。Google 给出的 Attention 的定义:

深度学习——attention机制_第6张图片

其中因子?tp=webp&wxfrom=5&wx_lazy=1起到调节作用,使得内积不至于太大(太大的话 softmax 后就非 0 即 1 了,不够“soft”了)。此外这个定义只是注意力的一种形式,还有一些其他选择,比如 query 跟 key 的运算方式不一定是点乘(还可以是拼接后再内积一个参数向量),甚至权重都不一定要归一化,等等。

他们将其映射为一个query和一系列,最终得到输出attention value的过程。这里的query相当于decoder中的si-1keyvalue都来自于encoder的hj,区别在于前后状态的hj。然后计算query与keyi的相似度并与valuei进行相乘,然后求和。

深度学习——attention机制_第7张图片

Google 的一般化 Attention 思路也是一个编码序列的方案,因此我们也可以认为它跟 RNN、CNN 一样,都是一个序列编码的层。

深度学习——attention机制_第8张图片

上面提到的query与key之间计算相似度有许多方法,如dot、general、concat和MLP等方式,具体公式如下所示。而attention模型抽象为query、key和value之间的相似度计算,总共有3个阶段。

第一阶段:query与keyi使用特定的相似度函数计算相似度,得到si;

第二阶段:对si进行softmax()归一化得到ai;

第三阶段,将ai与valuei对应相乘再求和,得到最终的attention value。

其实对比传统的attention公式。我们可以看出,这两套公式还是很像的。红色框中的是google提出的attention,蓝色框中的是传统的attention。

其中,是google提出的attention中未归一化之前的相似度,是传统的attention中未归一化之前的相似度。

深度学习——attention机制_第9张图片

Attention机制:将Source中的构成元素想象成是由一系列的数据对构成,此时给定Target中的某个元素Query,通过计算Query和各个Key的相似性或者相关性,得到每个Key对应Value的权重系数,然后对Value进行加权求和,即得到了最终的Attention数值。所以本质上Attention机制是对Source中元素的Value值进行加权求和,而Query和Key用来计算对应Value的权重系数。

事实上这种 Attention 的定义并不新鲜,但由于 Google 的影响力,我们可以认为现在是更加正式地提出了这个定义,并将其视为一个层地看待。

Attention 层

深度学习——attention机制_第10张图片

二、Transformer

BERT大火却不懂Transformer?读这一篇就够了  https://baijiahao.baidu.com/s?id=1622064575970777188&wfr=spider&for=pc

深度学习——attention机制_第11张图片

谷歌的这篇论文里提出的transformer模型抛弃了cnn,rnn,初次看有点一头雾水,总结了一下迷惑的地方有三个:

  • Positional embedding;(位置嵌入向量——其实类似word2vec,只不过处理的是位置信息罢了)。
  • multi-head attention; (多头注意力机制——点乘注意力的升级版本)
  • Position-wise Feed-Forward Networks(位置全链接前馈网络——MLP变形)
    现在一一分析:

Multi-Head Attention

这个是 Google 提出的新概念,是 Attention 机制的完善。

深度学习——attention机制_第12张图片   

不过从形式上看,它其实就再简单不过了,就是把 Q,K,V 通过参数矩阵映射一下,然后再做 Attention,把这个过程重复做 h 次,结果拼接起来就行了,可谓“大道至简”了。具体来说:

3ea6c41732d2b99a5d5f49d7b6e09744663c9a90

这里53797d704f5dd616a7d9ab28402c48b01cd593a7,然后:

bcd491d3c1bbd02e123239491bba468596c4be5e

最后得到一个 n×(hd̃v) 的序列。所谓“多头”(Multi-Head),就是只多做几次同样的事情(参数不共享),然后把结果拼接。

深度学习——attention机制_第13张图片

Transformer会在三个不同的方面使用multi-headattention:

  1. encoder-decoder attention:使用multi-head attention,输入为encoder的输出和decoder的self-attention输出,其中encoder的self-attention作为 key and value,decoder的self-attention作为query
  2. encoder self-attention:使用 multi-head attention,输入的Q、K、V都是一样的(input embedding and positional embedding)
  3. decoder self-attention:在decoder的self-attention层中,deocder 都能够访问当前位置前面的位置

Position-wise feed forward network

深度学习——attention机制_第14张图片

Position-wise feed forward network,其实就是一个MLP 网络,1 的输出中,每个 d_model 维向量 x 在此先由 xW_1+b_1 变为 d_f $维的 x',再经过max(0,x')W_2+b_2 回归 d_model 维。之后再是一个residual connection。输出 size 仍是 $[sequence_length, d_model]$

Positional embedding

Transformer中没有RNN、CNN的结构,所以也就没办法得到句子中每个单词的信息,于是 Google 再祭出了一招——Position Embedding,也就是“位置向量”,将每个位置编号,然后每个编号对应一个向量,通过结合位置向量和词向量,就给每个词都引入了一定的位置信息,这样 Attention 就可以分辨出不同位置的词了。 

 Google 直接给出了一个构造 Position Embedding 的公式:

深度学习——attention机制_第15张图片

这样做的目的是因为正弦和余弦函数具有周期性,对于固定长度偏差k(类似于周期),post +k位置的PE可以表示成关于pos位置PE的一个线性变化(存在线性关系),这样可以方便模型学习词与词之间的一个相对位置关系。

在这个纯 Attention 模型中,Position Embedding 是位置信息的唯一来源,因此它是模型的核心成分之一。

Position Embedding 本身是一个绝对位置的信息,但在语言中,相对位置也很重要,Google 选择前述的位置向量公式的一个重要原因如下:

由于我们有 sin(α+β)=sinα cosβ+cosα sinβ 以及 cos(α+β)=cosα cosβ−sinα sinβ,这表明位置 p+k 的向量可以表明位置 p 的向量的线性变换,这提供了表达相对位置信息的可能性。

结合位置向量和词向量有几个可选方案,可以把它们拼接起来作为一个新向量,也可以把位置向量定义为跟词向量一样大小,然后两者加起来

模型整体

深度学习——attention机制_第16张图片

Transformer也会遵循这种结构,encoder和decoder都使用堆叠的self-attention和point-wise,fully connected layers。

Encoder: encoder由6个相同的层堆叠而成,每个层有两个子层。第一个子层是多头自我注意力机制(multi-head self-attention mechanism),第二层是简单的位置的全连接前馈网络(position-wise fully connected feed-forward network)。在两个子层中会使用一个残差连接,接着进行层标准化(layer normalization)。也就是说每一个子层的输出都是LayerNorm(x + sublayer(x))。网络输入是三个相同的向量q, k和v,是word embedding和position embedding相加得到的结果。为了方便进行残差连接,我们需要子层的输出和输入都是相同的维度。

Decoder: decoder也是由N(N=6)个完全相同的Layer组成,decoder中的Layer由encoder的Layer中插入一个Multi-Head Attention + Add&Norm组成。输出的embedding与输出的position embedding求和做为decoder的输入,经过一个Multi-HeadAttention + Add&Norm((MA-1)层,MA-1层的输出做为下一Multi-Head Attention + Add&Norm(MA-2)的query(Q)输入,MA-2层的Key和Value输入(从图中看,应该是encoder中第i(i = 1,2,3,4,5,6)层的输出对于decoder中第i(i = 1,2,3,4,5,6)层的输入)。MA-2层的输出输入到一个前馈层(FF),经过AN操作后,经过一个线性+softmax变换得到最后目标输出的概率。
对于decoder中的第一个多头注意力子层,需要添加masking,确保预测位置i的时候仅仅依赖于位置小于i的输出。
层与层之间使用的Position-wise feed forward network。

Attention 层的好处是能够一步到位捕捉到全局的联系,因为它直接把序列两两比较(代价是计算量变为 ?(n2),当然由于是纯矩阵运算,这个计算量相当也不是很严重)。

相比之下,RNN 需要一步步递推才能捕捉到,而 CNN 则需要通过层叠来扩大感受野,这是 Attention 层的明显优势。 

不足之处:

  1. 论文标题为 Attention is All You Need,因此论文中刻意避免出现了 RNN、CNN 的字眼,但我觉得这种做法过于刻意了。事实上,论文还专门命名了一种 Position-wise Feed-Forward Networks,事实上它就是窗口大小为 1 的一维卷积,因此有种为了不提卷积还专门换了个名称的感觉,有点不厚道。(也有可能是我过于臆测了)。 
  2. Attention 虽然跟 CNN 没有直接联系,但事实上充分借鉴了 CNN 的思想,比如 Multi-Head Attention 就是 Attention 做多次然后拼接,这跟 CNN 中的多个卷积核的思想是一致的;还有论文用到了残差结构,这也源于 CNN 网络。 
  3. 无法对位置信息进行很好地建模,这是硬伤。尽管可以引入 Position Embedding,但我认为这只是一个缓解方案,并没有根本解决问题。举个例子,用这种纯 Attention 机制训练一个文本分类模型或者是机器翻译模型,效果应该都还不错,但是用来训练一个序列标注模型(分词、实体识别等),效果就不怎么好了。那为什么在机器翻译任务上好?我觉得原因是机器翻译这个任务并不特别强调语序,因此 Position Embedding 所带来的位置信息已经足够了,此外翻译任务的评测指标 BLEU 也并不特别强调语序。 
  4. 并非所有问题都需要长程的、全局的依赖的,也有很多问题只依赖于局部结构,这时候用纯 Attention 也不大好。事实上,Google 似乎也意识到了这个问题,因此论文中也提到了一个 restricted 版的 Self-Attention(不过论文正文应该没有用到它)。它假设当前词只与前后 r 个词发生联系,因此注意力也只发生在这 2r+1 个词之间,这样计算量就是 ?(nr),这样也能捕捉到序列的局部结构了。但是很明显,这就是卷积核中的卷积窗口的概念。 

 

以上大部分内容来源:

https://www.jianshu.com/p/3f2d4bc126e6   论文笔记:Attention is all you need

https://yq.aliyun.com/articles/342508?utm_content=m_39938  一文读懂「Attention is All You Need」| 附代码实现

https://www.cnblogs.com/Ann21/p/9784444.html     关于注意力机制(《Attention is all you need》)

 

你可能感兴趣的:(深度学习,attention机制)