一. 从RNN到Transformer
文字数据由于天然具有序列特性,与图像数据是不同的,因此最初的特征提取器(类似于图像中的CNN)采用了RNN结构:
对RNN有一定了解的话,就会知道RNN的两个明显问题:
- 效率问题:需要逐个词进行处理,后一个词要等到前一个词的隐状态输出以后才能开始处理,因此无法并行处理
- 如果传递距离过长还会有梯度消失、梯度爆炸和遗忘问题
为了解决第二个问题,就需要在RNN的隐层里设计各种门结构,代表作有:
- LSTM
- GRU
但是上述第一个问题依旧无法解决。终于,2017年Google在神作《Attention is all you need》提出了Transformer结构,后来出世的Bert模型(类比于CV中的Resnet)正是采用Transformer作为特征提取器在NLP11项任务上取得了SOTA效果,一举让RNN结构成为历史。
Transfromer是一个N进N出的结构,也就是说每个Transformer单元相当于一层的RNN层,接收一整个句子所有词作为输入,然后为句子中的每个词都做出一个输出。但是与RNN不同的是,Transformer能够同时处理句子中的所有词,并且任意两个词之间的操作距离都是1,这么一来就很好地解决了上面提到的RNN的效率问题和距离问题。(这是什么鬼?!看下面Transformer结构…)
二. 解析Transformer
2.1 Transformer结构
宏观层面
Transformer本质上是一个Encoder-Decoder结构:
如论文中所设置的,编码器由6个编码block组成,同样解码器是6个解码block组成,每个block结构相同,但不共享参数。与所有的生成模型相同的是,编码器的输出会作为解码器的输入,如图所示:
微观层面
Ok,我们再来看一下每个encoder和decoder内部长什么样:
定义输入序列首先经过 word embedding,再和 positional encoding 相加后,输入到 encoder 中。输出序列经过的处理和输入序列一样,然后输入到 decoder。
最后,decoder 的输出经过一个线性层,再接 Softmax。
(是不是看起来很可怕?)不着急,后面会具体解析每个模块,现在先在脑子里先记住几个重要的单词!!!
- Self-attention
- Feed forward
- Add&Norm
记好了下面就开始了:
encoder
encoder由 6 层相同的层组成,每一层分别由两部分组成:
- 第一部分是 multi-head self-attention
- 第二部分是 position-wise feed-forward network,是一个全连接层
两个部分,都有一个残差连接(residual connection),然后接着一个 Layer Normalization。
decoder
和 encoder 类似,decoder 也是由6个相同的层组成,每一个层包括以下3个部分:
- 第一个部分是 multi-head self-attention mechanism
- 第二部分是 multi-head context-attention mechanism
- 第三部分是一个 position-wise feed-forward network
和 encoder 一样,上面三个部分的每一个部分,都有一个残差连接,后接一个 Layer Normalization。
decoder 和 encoder 不同的地方在 multi-head context-attention mechanism。
2.2 Attention
Transformer堪称把attention发挥到了极致,本节讲讲multi-head self-attention模块。
2.2.1 self-attention是什么
直观表示
如上图所示,我们想知道句子中的"it"是指什么,“animal”, “street” 或者其他单词,很显然,这里"it"指的就是"animal”,所以"it"会将更多的attention放在单词"animal"上。也就是说,"it"对于"animal"的权重是最大的。
个人理解,self-attention就是算出每个词对于这个词的权重,然后将这个词表示为所有词的加权和。
数学表示
为了求出这个权重大小,论文中给出了名为Scaled Dot-Product Attention的操作:
首先对于每个输入的embedding词向量x(论文中设为512维),利用线性变化矩阵Wq, Wk, Wv, 生成三个向量q(query), k(key), v(value), 论文中每个向量均为64维。
对于每一个词,为句子中的每个词计算一个score: score = qi . kj;
之后再对每个score除以 sqrt(dk)进行归一化,再计算其 softmax输出 score;
对于每个 value 向量的 score 加权和即为 当前词的attention输出。
利用向量表示为:
2.2.2 Multi-head Attention
这个模块即是将各个 self-attention模块的输出concat起来后再做一个线性变换。
公式表示为:
论文中 h取为8, 采用multi-head的优点为:
- 扩展模型能力可以注意到不同位置,一个注意力模型的关注点也许是错的,通过多个注意力模型可以提高这种泛化能力;
- 使得注意力层具有多个表示子空间,比如说上文的8个注意力模型,经过训练后,我们就可以将输入的词嵌入映射到8个不同的表示子空间;
2.3 Position-wise Feed Forward Network
对于每一个词,经过Attention模块化后输出一个向量Z, 将其输入一个全连接网络,即这里的前馈网络。论文中,输入和输出向量维数为512,中间层维数为2048.
2.4 Layer Normalization
我们发现Attention层和FFN层都会接一个Add&Norm,即残差模块。我们希望数据能够归一化为均值为0,方差为1,从而更好的训练。这里LN和著名的BN区别看这里。
2.5 Decoder
各个主要模块已经介绍完了,我们现在再来看看Decoder和Encoder有什么区别。
2.5.1 Encoder-Decoder Attention
我们看一下上面的图,解码器的顶层输出中,然后我们需要的是一组attention的集合(K,V)。(K,V)将代入每个Decoder的“encoder-decoder attention”层中去计算(这样有助于decoder捕获输入序列的位置信息)。也就是说,在解码器的Encoder-Decoder Attention模块,K,V 来自于编码器顶层,Q来自于上个解码器的输出。
2.5.2 Mask Multi-head Attention
与编码过程不同,解码过程是一个顺序操作的过程,也就是当解码第k个特征向量时,我们只能看到第k-1个向量及其之前的解码结果,每个底端解码器的输入为上一个时刻的输出再加上位置编码(后面会讲)。因此在Attention模块需要加上一个Mask操作,操作也很简单,在self-attention的softmax操作之前与上一个下三角阵即可。
下三角部分(包括对角线为1),上三角部分为0。则上三角部分为被mask掉的地方。
因为对于矩阵中的一个元素x, 与mask矩阵操作后成为 x-(1-m)*inf。
2.6 Embedding and Softmax
Linear层就是一个全连接网络,作用是把decoder输出的向量映射到一个大很多的logits 向量上。
比如模型从训练集中学会10,000个英文单词,那么logits vector就是10000维的,每一维对应一个词,记过softmax计算后输出分数最高的那个词就是这一步的输出。
2.7 Positional Embedding
Transformer的结构介绍完了,我们再回到最开始,Transformer本身没有捕捉序列的能力,也就是说对于每个单词Transformer都同等对待。为了解决这个问题,我们就需要对输入的词向量再加上一个位置编码。
文中给出了编码公式为:
其中 pos 是单词位置, i 为维数。
3 总结
Reference
- https://blog.csdn.net/linxid/article/details/84321617#1_Transformer_2
- https://blog.csdn.net/qq_41664845/article/details/84969266
- https://blog.csdn.net/weixin_40005743/article/details/85460869
- https://zhuanlan.zhihu.com/p/69290203
- https://zhuanlan.zhihu.com/p/48508221
- https://zhuanlan.zhihu.com/p/54356280
- https://zhuanlan.zhihu.com/p/47812375