1.前言
Transformer是由论文《Attention is All You Need》首次提出,Transformer首次提出时主要是用来解决机器翻译任务的,在这之前大家做机器翻译任务用的最多的是基于RNN的Encoder-Decoder模型,结构如图1所示。Encoder-Decoder模型在序列处理中有很好的表现,在2018年之前被广泛的使用。该模型主要是有RNN构成,存在两个主要问题:首先RNN模型容易出现梯度消失或者梯度爆炸的问题,主要原因是RNN在计算当前值的时候会使用上一时刻点的值,即在计算某一时刻点的梯度时,存在长期依赖的问题,当函数的激活函数的梯度求导小于1时,随着时间序列的不断深入,小数的累乘就会导致梯度越来越小直到接近于0,这就是“梯度消失“现象。如果激活函数的求导大于1时,不断累积会出现梯度爆炸的问题。为了解决这个问题,后面提出了LSTM和GRU能够在一定程度上缓解这个问题。另外RNN是序列结构,本时刻的值依赖上一时刻的输出,不能实现并行化,在正常模型训练过程中,速度很慢。
为了更好的解决上述两个问题,作者提出了transformer模型,该模型抛弃了传统的CNN和RNN,整个网络结构完全是由Attention机制组成。作者通过attention机制提取当前值和上下文之间的相关关系,通过位置编码引入单词在句子中的位置关系,替代RNN通过序列结构依次提取从左到右或者从右到左的序列关系。这样能够提取更长序列结构信息,不会出现信息丢失现象,另外attention机制不是序列结构,因此能够通过矩阵运算,更好的并行化。接下来本文将从Transformer的主要思想,结构做分析,并且会讲解核心代码以及在推荐系统中如何落地
该论文的核心是基于注意力机制替换NLP任务中的RNN结构,相较于原始的RNN序列提取结构,Transformer不仅能够提取更长的序列特征,而且能够快速的并行化运行。一经提出就成为了学术界和工业界研究的焦点,目前该结构主要应用于NLP领悟的机器翻译,问答系统,文本摘要和语音识别等方向,同时在计算机视觉和推荐系统等也有很多尝试,也都取的了不错的效果。本文将从模型结构以及关键模块的代码实现展开讲解,最后会适当分析一下在推荐系统中的部分应用。
2. 模型结构
论文中的验证Transformer的是的机器翻译项目,下文中以机器翻译为例子详细剖析Transformer的结构。如图2所示,transformer模型中也采用了 encoer-decoder 架构,但其结构相比于Attention更加复杂,论文中encoder层由6个encoder堆叠在一起,decoder层也一样。
Transformer 的详细结构如图3所示,共有四个部分:输入、encoder、decoder和输出部分。
输入 :首先输入单词经过embedding,然后再加上位置编码信息得到一个基本的输入embedding向量
Encoder: 输入向量经过一个统一网络的结构,这个结构就是编码结构,编码结构有N次,会对输入循环处理N次(论文中使用的是6次)。每一个encode层中又可以分成Attention层和全连接层,再额外加了一些处理,比如Skip Connection,做跳跃连接,然后还加了Normalization层。
Docedder: 它的第一次输入信息是前缀信息,之后的就是上一次产出的Embedding,加入位置编码,然后进入一个可以重复很多次的模块(论文中使用的也是6次),即解码模型。该模块可以分成三块来看,第一块也是Attention层,第二块是cross Attention,不是Self-Attention,第三块是全连接层。也用了跳跃连接和Normalization。
输出:模型的最后的输出要通过Linear层(全连接层),再通过softmax做预测。下面分模块做一个讲解,部分模块会加有一些代码部分帮助理解。
2.1 输入
Transoformer模型输入是由单词embedding和位置编码(表示单词在序列中的位置信息)相加得到。这里融合两个向量不是采用通用的concat操作,而是直接使用加法运算,具体原因下面会详细讲解。
1.单词embedding
输入单词的embeding的表示方法通常有两种方法,一种是基于类似Word2Vec、Glove模型预训练得到,然后固化做lookup查询使用;还有一个方法是采用随机初始化的方法,在训练过程中随着模型进行更新训练,调整embedding的表示参数。在transformer原始论文中采用的是第二种方法。
2.位置编码
self-attention机制只能得到当前单词和其他单词之间相关关系,不能获取当前单词在句子中的位置信息,而单词的前后文顺序关系对自然语言理解至关重要,所以在Transfomer中通过位置编码embedding引入单词在序列中的相对或者绝对位置信息。为了表示位置关系有两种方法,一种是通过学习获取独特的位置表示,还有一种是使用特定的编码规则。论文中作者使用了第二种方法,具体的计算公式如下:(PE表示embedding表示)
$$
PE(pos,2i)=sin(\frac{pos}{10000^{2i/d_{model}}})
$$
$$
PE(pos,2i+1)=cos(\frac{pos}{10000^{2i/d_{model}}})
$$
这里最开始个人不是很理解,这两个复杂的编码公式和位置有什么具体的关系吗?反复查阅文献,大致理解这里只是为了刻画每个位置的唯一性,通过编码规则能够将所有位置编码都能表示出来,不重复。这里举一个小例子。
Eg: 对于一个单词w位于$ pos \in [0, L-1] $,假设使用embedding的维度为4,那么基于上述公式这个单词的encoding表示为:
$$
e_w = [sin(\frac{pos}{10000^0}), cos(\frac{pos}{10000^0}, sin(\frac{pos}{10000^{2/4}},cos(\frac{pos}{10000^{2/4}})))] \
= [sin(pos), cos(pos, sin(\frac{pos}{100},cos(\frac{pos}{100})))]
$$
为什么这样做呢?用图形的方式可以直觉上理解。图4为一个长度为50,维度是128的句子的Positional Encoding(每一行为一个Encoding向量)。图中一行就是一个单词的Positional Encoding。上图可以看出,不同位置的Positional Encoding是独特的。计算Positional Encoding的方式不是唯一的,还可以有别的方法,不是必须使用sin和cos表示,只要能够唯一表示就可以。这里选择正弦曲线版本是因为它可以使模型外推到比训练过程中遇到的序列更长的序列长度,相较训练的方法鲁棒性更强。
3. 整体输入表示
上面提到过这里采用的是相加不是通常使用的concat方式,通过计算公式拆分的方法,可以看出两种计算方法相差不大。$x^i和P^i$分别表示单词embedding和pos embedding,concat成一个矩阵然后再做矩阵运算和等式右边分别做矩阵运算再相加。
2.2 attention机制
Attention(注意力)机制如果浅层的理解,跟他的名字非常匹配。他的核心逻辑就是「从关注全部到关注重点」。Attention 机制很像人类看图片的逻辑,当我们看一张图片的时候,我们并没有看清图片的全部内容,而是将注意力集中在了图片的焦点上。attention机制是该论文的核心模块,如图6中可以看出左侧encoder和右侧decoder都包含attention模块,这里主要介绍self-attention、multi-head attention以及Masked Multi-head Attention。
1. self-attention
self-attention机制是transformer的核心部分,其核心思想是当前单词和句子中的其他单词之间学习一个相关系数。如图7所示,是句子"The animal didn't cross the street because it was too tired"中it的权重可视图,图中的颜色深浅是用来表示相关性,越深则越相关,从图中可以看出对it影响力最强的两个单词分别是The和animal,所以Self-Attention就是说,句子内各单词的注意力,应该关注在该句子内其他单词中的哪些单词上。
上面讲解了主要的思想,下面将讲解如何实现该机制。在self-attention中,每个单词有3个不同的向量,它们分别是Query向量(Q),Key向量(K)和Value向量(V),它们是由嵌入向量 X 乘以三个不同的权值矩阵WQ,WK,WV得到,具体计算示意图如下。
!
得到矩阵 Q, K, V之后就可以计算出 Self-Attention 的输出了,计算的公式如下:
$$
Attention(Q,K,V) = softmax(\frac{QK^T}{\sqrt(d_k)}) \
d_k 是Q,K矩阵的列数,即向量维度
$$
公式中计算矩阵Q和K每一行向量的内积,为了防止内积过大,因此除以$ d_k $的平方根。Q乘以K的转置后,得到的矩阵行列数都为 n,n为句子单词数,这个矩阵可以表示单词之间的attention强度。下图为Q乘以 KT ,其中1234 表示的是句子中的单词。
得到$ QK^T $之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1。
得到 Softmax 矩阵之后可以和矩阵V相乘,得到最终的输出Z,如图11上半部分所示。在图11下半部分中是具体计算过程, Softmax矩阵的第1行表示单词x1与其他所有单词的attention系数,最终单词1的输出Z1等于所有单词i的值Vi根据 attention 系数的比例加在一起得到。
如图12所示,Multi-head attention是由self-attention堆叠而成,这样做可以提升特征提取的维度,类似cnn网络不同卷积核可以提取不同的特征,比如有的卷积核主要用来提取边缘特征,有的卷积核主要用来提取方形特征等,这里不同的self-attention可以针对句子中的语义相似度,词性相关性等其它抽象的特征,为精准的刻画单词表达。具体的做法是首先将输入X分别传递到 h 个不同的 Self-Attention 中,计算得到 h个输出矩阵Z。图13所示是h=8时候的情况,此时会得到8个输出矩阵$ Z_i $。得到8个输出矩阵$ Z_1 $到$ Z_8 $之后,Multi-Head Attention 将它们拼接在一起,然后传入一个Linear层,得到 Multi-Head Attention 最终的输出Z。
3. Masked Multi-head Attention
由于在机器翻译中,解码过程是一个顺序操作的过程,也就是当解码第 k 个特征向量时,我们只能看到第 k−1 及其之前的解码结果,论文中把这种情况下的multi-head attention叫做masked multi-head attention,具体的操作就是在将第k个单词后面的系数设置为0,不参与具体的运算
2.3 Encoder 和decoder结构
如图3所示,encoder和decoder中还有Add和Norm结构以及decoder中的双multi-head attention的作用需要讲解。
1. Add和Norm结构
Add & Norm模块接在Encoder端和Decoder端每个子模块的后面,其中Add表示残差连接,Norm表示LayerNorm,残差连接来源于论文Deep Residual Learning for Image Recognition,LayerNorm来源于论文Layer Normalization,因此Encoder端和Decoder端每个子模块实际的输出为:(其中Sublayer(x)为子模块的输出)
$$
LayerNorm(X + Sublayer(X))
$$
skip connection最早是在计算机视觉的ResNet里面提到的,是微软亚洲研究院的何凯明做的,主要是想解决当网络很深时,误差向后传递会越来越弱,训练就很困难,那如果产生跳跃连接,如果有误差,可以从不同路径传到早期的网络层,这样的话误差就会比较明确地传回来。跳跃层不是必须的,在Transformer中,作者建议这样做,在Selft-Attention的前后和每一个Feed Forwar前后都用了跳跃层,如图3所示。
Norm结构主要是正则化的作用,用的是一种新的Layer Normalize结构,不是常用的Batch Normalize。是一种正则化的策略,避免网络过拟合。BN的主要思想就是:在每一层的每一批数据上进行归一化,而LN是在每一个样本上计算均值和方差,而不是BN那种在批方向计算均值和方差!LN只考虑自己不考虑其他数据,这样就避免了不同batch size的影响。具体计算逻辑图如图13所示:
2. decoder结构
decoder结构中包含两个multi-head attention结构,第一个是masked multi-head attention结构,他的输入是训练集合的标签Y, 预测当前时刻的值只能使用序列前的值,故需要对后面的结果做掩码处理。以 "我有一只猫" 翻译成 "I have a cat" 为例,首先根据输入 "
第二个multi-head attntion变化不大, 主要的区别在于其中 Self-Attention的K,V矩阵不是使用上一个Decoder block的输出计算的,而是使用Encoder的编码信息矩阵 C计算的。根据 Encoder 的输出C计算得到K, V,根据上一个Decoder block的输出Z计算Q (如果是第一个Decoder block则使用输入矩阵X进行计算),后续的计算方法与之前描述的一致。这样做的好处是在Decoder的时候,每一位单词都可以利用到 Encoder 所有单词的信息。
2.4 输出层
当decoder层全部执行完毕后,怎么把得到的向量映射为我们需要的词呢?这里通过多分类的方法,在模型结尾添加一个全连接层和softmax层,假如我们的词典是1w个词,那最终softmax会输入1w个词的概率,概率值最大的对应的词就是我们最终的结果。
3. 在推荐系统中的应用
在推荐系统中,用户的历史点击item序列是我们需要挖掘的主要特征,这些历史的点击序列类似于NLP中的句子一样,有一定的上下文关系,在提取点击序列特征时,可以使用multi-head attention 提取用户真正喜欢的item做一定的加权处理。在推荐系统的召回算法中,SASRec(Self-Attentive Sequential Recommendation )是一个比较早的应用transformer结构做推荐的,结构如图15所示。用户的点击item会按照时间顺序排列,从左往右。序列化的item经过embedding层后输入到self-attention层,每个item只会与时间在前面的item计算注意力权重。经过transformer结构,也就是多个block,每个item的输出向量用于预测下一个点击的item。最后一个item的item向量用于预测target item。线上召回时也是用最后一次点击的item向量。线上实验时,SASRec有不错的曝光量和高的点击率。
之后提出了Bert4Rec(BERT4Rec: Sequential Recommendation with Bidirectional Encoder Representations from Transformer)将self-attention的计算由从左到右变为双向的顺序,并且用了bert中mask的训练方法。但是在实际工业应用中需要考虑耗时原因,该算法应用有限。后面阿里提出的MIND召回中也应用了该思想。
Multi-head attention思考在推荐系统的排序模型中也多有应用,如果阿里提出的DIN、DIEN网络等等
4. 总结
Transformer的核心部分就是Multi-head Attention模块,该模块后续被应用于图像、推荐等领域都取得了很不错的效果。特别在推荐系统中,提取序列特征有很大的帮助,能够在一定程度上挖掘到用户兴趣点,找到用户更加关注的item特征,在线上性能开销允许的条件下,把序列特征输入到主干网络前,添加multi-head attention结构,可能可以得到更好的效果。
5. 参考文献:
- 我的微信小程序
- 这是我的微信小程序扫一扫
-
- 我的微信公众号
- 我的微信公众号扫一扫
-
评论