当前位置:   article > 正文

深度学习建模训练总结(六):梳理NLP发展里程碑——细看transformer_transformer替代lstm

transformer替代lstm

之前也提到了,一般而言我们会采用LSTM处理输入的句子,根据上下文等信息调整词向量,但是LSTM终究有长期依赖问题,这是它的结构决定的,而self-attention的出现,既可以实现以上的目的,同时又避免了长期依赖问题,那为什么不用self-attention替代LSTM进行分析呢,这就是transformer提出的缘由。

在这里插入图片描述

简单来说,transformer就是在seq2seq的基础上,引入multi-head attention,用注意力机制全面替代CNN、LSTM、RNN,从结构上来说,虽然看起来复杂,但是需要知道本质上这就是一个encoder-decoder结构。

论文本身写道图中左侧是encoder右侧是decoder,但是我认为,其实右侧有一部分也是encoder(我标注的黄色部分),只是那部分是对上一时刻的output进行encode,对当前输入以及上一时刻的输出进行encode之后,会输入到multi-head attention进行计算分析,得到encoder-decoder的语义向量,再对语义向量进行分析,得到最终答案。

为了方便对比,我把结合注意力机制的seq2seq的相应部分一起标注出来,当然需要注意的是seq2seq的图并没有画出通过S(t-1)计算注意力的过程:

在这里插入图片描述

当然这些都是我个人的看法,如果有不同的意见也欢迎提出交流,接下来关于transformer,我想主要讨论几点:multi-head attention、masked multi-head attention的mask是怎么实现、如何理解position encoding。

对于multi-head attention,这是transformer的一大创新。之前在注意力机制中也详细说过说过,其实multi-head attention本质上就是对注意力计算框架的一个改进,对query、key、value做不同的线性变换,让模型可以参与到词向量的调整中,也就是:

Q i = Q ∗ W i Q Q_i = Q * W_i^Q Qi=QWiQ
K i = K ∗ W i K K_i = K * W_i^K Ki=KWiK
V i = V ∗ W i V V_i = V * W_i^V Vi=VWiV

上面的W就是一个参数矩阵,模型可以通过训练学习进行调整,因而比起原来只采用输入的词向量自由度更高。这就像CNN使用多个卷积核,我们可以理解成模型从多个角度对query、key、value进行分析,当然实际上使用多个W的主要作用还是在于增加模型参数量,提高模型的拟合能力。

所以我们可以完全把multi-head看成是强化版的attention计算框架,既然是强化版的计算框架,当然也就可以像原版那样对query、key、value的设定进行讨论,而在transformer中,确实也有两种不同的multi-head,一种是通常的multi-head,用于计算输入和上一时刻的输出的attention value,一种是self-attention,用于对输入进行特征提取。前者是我图中标注的红色部分,后者则是图中在左侧的multi-head。

整个模型除了以上两个multi-head,还有一个masked multi-head,由于transformer舍弃了LSTM,所以模型在训练阶段只能一次性把output输入进去,但是又必须防止模型在当前时刻的训练阶段提前"知道"未来的output,所以就需要把未来的部分mask掉。原文是这样解释mask的过程的:We implement this inside of scaled dot-product attention by masking out (setting to −∞) all values in the input of the softmax which correspond to illegal connections

在这里插入图片描述
从上图可以看出,其实mask操作就是在计算权重之前,把需要mask的部分设置为负无穷,这样softmax之后对应的权重就变成0,和value相乘就变成0,这样计算出来的attention value就不包含需要mask的部分。

最后再来说说position encoding,一开始也说到,用attention替代LSTM,优点就在于避免了长期依赖问题,但是也有一个缺点,就是注意力机制无法分析顺序信息,因为在注意力机制的计算过程中,两两词之间的计算是无区别的,这就造成了,即使把输入的顺序改变,比如"我打你"变成"你打我",multi-head分析的结果都是一样的,为了避免这种情况,就必须在词向量中引入顺序信息。

这里先说一下transformer是怎么计算position encoding的:

P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos, 2i)} = sin(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)

P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos, 2i+1)} = cos(pos/10000^{2i/d_{model}}) PE(pos,2i+1)=cos(pos/100002i/dmodel)

上式中的pos表示词在句子中的位置,i表示词向量中元素的位置,比如现在有一个词,它的词向量是4维的,它在句子中的第一位,那么它加上的position encoding是:

[ s i n ( p o s 1000 0 0 ) , c o s ( p o s 1000 0 0 ) , s i n ( p o s 1000 0 2 / 4 ) , c o s ( p o s 1000 0 2 / 4 ) ] [sin(\frac{pos}{10000^0}), cos(\frac{pos}{10000^0}), sin(\frac{pos}{10000^{2/4}}), cos(\frac{pos}{10000^{2/4}})] [sin(100000pos),cos(100000pos),sin(100002/4pos),cos(100002/4pos)]

[ s i n ( 0 1000 0 0 ) , c o s ( 0 1000 0 0 ) , s i n ( 0 1000 0 2 / 4 ) , c o s ( 0 1000 0 2 / 4 ) ] [sin(\frac{0}{10000^0}), cos(\frac{0}{10000^0}), sin(\frac{0}{10000^{2/4}}), cos(\frac{0}{10000^{2/4}})] [sin(1000000),cos(1000000),sin(100002/40),cos(100002/40)]

对于这两条公式,我说一下我自己的看法,首先选择sin和cos的一个主要原因应该是不论句子有多长,最终输入到公式得到的结果都会小于1,这样加到embedding向量中也不会对向量的方向、长度造成很大的影响,可以有效保持embedding向量之间的距离关系。

至于位置信息,网上有很多文章有不同的解释,但我不是很喜欢从直觉或者感性的角度去看待这些公式,毕竟这就是一条条公式,整个模型就是一个复杂的函数,你认为这条公式可以帮助模型学习距离、顺序等信息,但是模型不会这样想,之所以最后能够达到预期效果,我认为主要的原因有几点,第一,position encoding的值只和句子中的位置有关,而和输入向量的数值完全无关,第二,模型训练的数据足够大,我们可以想象,其实加上position encoding之后,原始的embedding向量就变成了一个新向量,对于同一个词,出现在不同的位置就会产生不同的向量,但是因为数据量足够大,同一个词出现在同一个位置的情况肯定很多,所以模型就相当于基于新的词向量重新训练一遍,不过这一次,它不仅仅考虑了词与词之间的关系,还考虑了词在句子中的位置、它与其他词之间的顺序等信息。所以经过训练之后,模型就能明白当这个词与词是以这个顺序出现在一个句子里,表答了什么意思。

综上所述,其实position encoding在我看来更像是一个迁移学习的一部分,一开始的词向量仅仅是考虑了词与词之间的联系进行构建,而在position encoding中则在此基础上进一步考虑了词在句子中的位置、词与词之间的顺序。

以上就是对transformer的分析,作为总结,我们可以看看NLP是如何从RNN一步步发展到transformer的,一开始,RNN有长期依赖和无法实现变长输出的问题,于是提出了seq2seq,实现了变长输出,但是seq2seq的语义向量无法有效包含整个句子的语义信息,于是提出和注意力机制结合在一起,把一个语义向量变成多个语义向量,基于不同的语义向量计算不同时刻的输出,在这个过程中,发现了self-attention可以有效解决RNN的长期依赖问题,于是就更进一步,提出全面使用attention替代seq2seq中的RNN,同时也把原来的attention改进成multi-head attention,到这里,和一开始的RNN相比,就发现transformer一方面解决了长期依赖问题,也实现了动态输入输出,彻底解决了原有的问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/839010
推荐阅读
相关标签
  

闽ICP备14008679号