如何理解注意力机制与Transformer结构
Attention and Transformer
Attention
Seq2Seq模型
最初的用于机器翻译的Seq2Seq模型是由Encoder RNN和Decoder RNN组成的:
上图中,Encoder RNN的输入
从上述描述中可知Seq2Seq模型通过最后一个状态来记忆整个源语言句子的信息,这就导致该模型难以处理长的句子,Encoder的最后一个状态可能会漏掉一些信息,假如源语言句子中的某些单词被忘记了,Decoder就无从得知完整的句子,也就不可能产生正确的翻译。
从上诉图片中也可以证明我们之前的推测,在Seq2Seq模型结合Attention机制后这种情况就可以得到大大的缓解。
注:BLEU是衡量翻译的准确率,它有许多变体如BLEU-1用于衡量单词翻译的准确率,更高阶的BLEU可以衡量句子的流畅性
Attention改进Seq2Seq模型
Seq2Seq翻译模型加入Attention后的优缺点:
- 加入Attention机制后能够大幅改善模型的性能
- 使用了Attention机制后,Seq2Seq模型就不会遗漏源输入的细节
- 在Attention机制作用下,Decoder部分就能知道该聚焦哪儿
- 但是Attention机制也带来了更大的计算量
但Encoder对输入计算完成后,通过
有多种方法来计算这个相关性:
方法一(在原始的Attention论文中使用的):
该方法首先将
方法二(Transformer使用的方法):
该方法的输入依旧是
根据上述得到的每个Encoder时间步隐藏状态的相关性权重系数与隐藏状态向量进行加权求和可以得到一个Context vector
每个
回到Decoder部分,如何通过
时间复杂度
Attention的时间复杂度为
Attention:权重可视化
上图展示了Decoder出来的每个单词与输入单词的相关性,连线越深表示联系越紧密。
Self-Attention
Attention不仅可以用于Seq2Seq RNN模型中,它可以用于所有的RNN模型中。Self-Attention模型最初的论文就是用在LSTM模型中的。下面以原始的RNN举例,介绍Self-Attention的工作机制。
首先对于一个RNN网络,初始的状态向量
唯一的区别是把
然后通过输入
然后
之后不断地重复这个过程直到结束。
Self-Attention总结
使用了Self-Attention后,RNN可以避免遗忘,另外还可以帮助RNN关注与当前输入最相关的部分。
上图是论文中的原图,红色的代表输入,紫色代表与当前输入最相关的词语。
Transformer Model: Attention without RNN
Attention
之前介绍的Seq2Seq模型中,使用了Attention层进行改善。Seq2Seq模型可分为Encoder和Decoder部分,Encoder的输入为m个向量
其中align()函数的原理如下:
首先计算key和query向量:
然后计算权重:
其 中 还需要计算一个value向量:
上述 线性映射矩阵都是可学习的参数。
有了query、key和value向量后,通过将value与权重参数进行加权求和得到Context Vector
现在的问题是如何在这个Seq2Seq模型中移除RNN层而只保留Attention层呢?
首先我们考虑Seq2Seq模型的输入和输出:
上图中
通过Encoder部分的输入我们可以得到Key和Value:
所以,通过Encoder的输入就可以得到全部的key和value。
之后通过Decoder的输入可以得到所有的query:
然后通过得到的所有key和value以及每个query得到相应的权重向量
然后通过权重系数得到相应的Context Vector
每个query得到一个权重系数向量,然后得到相应的Conetxt Vector直到结束,最后Attention输出的就是所有的Context Vector
有个疑问是这里的
拿生成
之后可以将整个结构看出一个Attention层:
这个Attention层的输入为
Self-Attention
self-attention取代rnn的过程与attention的过程十分类似,略有不同的是self-attention的输入两个都是
其详细过程为,通过输入
然后通过所有的Key和当前的query计算得到一个权重参数向量,与此类似逐步得到所有的相应的权重向量:
然后各个权重向量与所有的value进行计算得到当前的Context Vector
与此类似可以得到所有的Context Vector
至此,我们可以将self-attention看作一个层,其两个输入都是
Transformer Model: From Shallow to Deep
本节主要讲如何由简单的Attention层和Self-Attention层搭建起简易的Transfomer骨架。
首先对于一个Self-Attention层,我们可以称之为“单头自注意力层”,我们可以使用l个“单头自注意力层”进行堆叠得到多头自注意力层:
对于其中的每个自注意力层,它们的参数相互不共享(参数即三个线性变换矩阵),同时把这些自注意力层的输出也堆叠起来就可以的得到
而多头注意力层的构造方式也类似将多个注意力层进行堆叠以及将输出也进行拼接。
对于多头自注意力层的输出,将其通过一个全连接层并使用ReLU激活函数进行激活得到新的输出
上图的全连接层参数共享。
为了使网络更深,我们可以以上面的方式堆叠多层:
如果将一个多头自注意力层与一个全连接层合起来看成一个Block,那么这个Block的输入是512×m(m为输入序列长度),输出也是512×m
最初的Transformer一共使用了6个Block:
然后是对注意力层进行堆叠,首先将输入通过一个6个Block的Encoder模块得到矩阵
然后将Decoder的输出
然后将矩阵
之后对于每个
这里的全连接层的参数是共享的。
这样就可以组成一个Decoder的block:
然后通过Encoder Block和Decoder Block组成Transformer结构:
首先是Encoder网络:
然后将Encoder网络的输出作为Decoder网络的输入,每个Decoder Block都会使用到Encoder网络的输出:
这样就组成了基本的Transformer结构。