NLP学习笔记——Transformer模型

NLP学习笔记——Transformer模型

1.概述

《Attention Is All You Need》是Google在2017年提出的一篇将Attention思想发挥到极致的论文。该论文提出的Transformer模型,基于encoder-decoder架构,抛弃了传统的RNN、CNN模型,仅由Attention机制实现,并且由于encoder端是并行计算的,训练时间大大缩短

Transformer模型广泛应用于NLP领域,机器翻译、文本摘要、问答系统等等,目前火热的Bert模型就是基于Transformer模型构建的。

2.模型特点

传统seq2seq最大的问题在于将Encoder端的所有信息压缩到一个固定长度的向量中,并将其作为Decoder端首个隐藏状态的输入,来预测Decoder端第一个单词(token)的隐藏状态。在输入序列比较长的时候,这样做显然会损失Encoder端的很多信息,而且这样一股脑的把该固定向量送入Decoder端,Decoder端不能够关注到其想要关注的信息。并且模型计算不可并行,计算隐层状态 h t h_t ht依赖于 h t − 1 h_{t-1} ht1以及状态 t t t时刻的输入,因此需要耗费大量时间。

Transformer优点:transformer架构完全依赖于Attention机制,解决了输入输出的长期依赖问题,并且拥有并行计算的能力,大大减少了计算资源的消耗。self-attention模块,让源序列和目标序列首先“自关联”起来,这样的话,源序列和目标序列自身的embedding表示所蕴含的信息更加丰富,而且后续的FFN层也增强了模型的表达能力。Muti-Head Attention模块使得Encoder端拥有并行计算的能力

3.模型原理

3.1 总体结构

transformer采用encoder-decoder架构,如下图所示。Encoder层和Decoder层分别由6个相同的encoder和decoder堆叠而成,模型架构更加复杂。其中,Encoder层引入了Muti-Head机制,可以并行计算,Decoder层仍旧需要串行计算

NLP学习笔记——Transformer模型

Encoder层和Decoder层内部结构如下图所示。

  1. Encoder具有两层结构,self-attention和前馈神经网络。self-attention计算句子中的每个词都和其他词的关联,从而帮助模型更好地理解上下文语义,引入Muti-Head attention后,每个头关注句子的不同位置,增强了Attention机制关注句子内部单词之间作用的表达能力。前馈神经网络为encoder引入非线性变换,增强了模型的拟合能力。
  2. Decoder接受output输入的同时接受encoder的输入,帮助当前节点获取到需要重点关注的内容

NLP学习笔记——Transformer模型

3.2 Multi-Head Attention

Multi-Head Attention 计算过程如下图,在讲解Multi-Head Attention之前,我们需要了解self-attention。

NLP学习笔记——Transformer模型

self-attention 机制用于计算句子中当前词与其他词的联系,举个例子:

The animal didn’t cross the street because it was too tired

The animal didn’t cross the street because it was too wide

两句话中的单词 it 指代不同,第一句话 it 指代 animal 而第二句指代 street。对于我们来说能很简单的判断出来,但是对于机器来说,是很难判断的,尤其是相对于传统seq2seq模型。两句话在单词 it 之前的内容是一样的,传统seq2seq模型encoder的顺序输入导致模型无法区分这种差别。而self-attention机制通过计算单词it与其他词之间的联系得知it的具体指代,最终结果如下图所示。

NLP学习笔记——Transformer模型

那么具体的计算过程是怎样的呢,我们先上公式,然后一步步拆解:

A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V

其实attention可以有很多种计算方式,加性attention,点积attention等等,论文中采用的是点积attention。公式如上

对于这个公式,我们首先进行一个大致的理解:Q,K,V是三个矩阵,分别是Query Key Value的缩写,Query与Key作用得到attention的权值,之后这个权值作用在Value上得到attention值。

NLP学习笔记——Transformer模型

举一个具体的例子:

  1. X X X 是我们的输入句子Embedding后的结果, X 1 X_1 X1 X 2 X_2 X2 是其前两个单词。算法的第一步需要计算 q q q$ k$ v v v 向量。这三个向量是 X X X 分别于其权重矩阵 W Q W^Q WQ W K W^K WK W V W^V WV相乘得到,如下图所示

NLP学习笔记——Transformer模型

  1. 计算self-attention的分数值,该分数值决定了当我们在某个位置encode一个词时,对输入句子的其他部分的关注程度。这个分数值的计算方法是Query与Key做点乘,以下图为例,首先我们需要针对Thinking这个词,计算出其他词对于该词的一个分数值,首先是针对于自己本身即q1·k1,然后是针对于第二个词即q1·k2。NLP学习笔记——Transformer模型

  2. 接下来,把点成的结果除以一个常数,这里我们除以8,这个值一般是采用上文提到的矩阵的第一个维度的开方即64的开方8,当然也可以选择其他的值,然后把得到的结果做一个softmax的计算。得到的结果即是每个词对于当前位置的词的相关性大小,当然,当前位置的词相关性肯定会会很大。NLP学习笔记——Transformer模型

  3. 下一步就是把Value和softmax得到的值进行相乘,并相加,得到的结果即是self-attetion在当前节点的值。

NLP学习笔记——Transformer模型

为了方便理解,例子中都是通过向量进行计算,实际情况下为了提高计算速度,我们采用的是矩阵的方式。即embedding 后的输入矩阵 X X X ,与权重矩阵 W Q W^Q WQ W K W^K WK W V W^V WV得到 Q Q Q K K K V V V 矩阵,之后通过上述公式计算出attention值。

这种通过 query 和 key 的相似性程度来确定 value 的权重分布的方法被称为scaled dot-product attention。

  • 【一个小问题】为什么有缩放因子 1 d k \frac{1}{\sqrt{d_k}} dk 1

  • 先一句话回答这个问题: 缩放因子的作用是归一化。

  • 假设Q、 K里的元素的均值为0,方差为1,那么 中元素的均值为0,方差为d. 当d变得很大时, 中的元素的方差也会变得很大,如果 中的元素方差很大,那么 的分布会趋于陡峭(分布的方差大,分布集中在绝对值大的区域)。总结一下就是的分布会和d有关。因此 中每一个元素乘上 后,方差又变为1。这使得 的分布“陡峭”程度与d解耦,从而使得训练过程中梯度值保持稳定。**

实际上,在Transformer模型中,使用Muti-Head机制代替我们刚才讲解的single self-attention

同样先上公式:
M u t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , h e a d 2 , . . . , h e a d h ) W O w h e r e , h e a d i = A t t e n t i o n ( Q W i Q , K W i k , V W i V ) MutiHead(Q,K,V) = Concat(head_1,head_2,...,head_h)W^O \\ where, head_i = Attention(QW_i^Q,KW_i^k,VW_i^V) MutiHead(Q,K,V)=Concat(head1,head2,...,headh)WOwhere,headi=Attention(QWiQ,KWik,VWiV)
其中, W i Q ∈ R d m o d e l × d k , W i k ∈ R d m o d e l × d k , W i V ∈ R d m o d e l × d v , W O ∈ R h d v × d m o d e l W_i^Q\in R^{d_{model} \times d_{k}},W_i^k\in R^{d_{model} \times d_{k}},W_i^V\in R^{d_{model} \times d_{v}},W_O^\in R^{hd_{v} \times d_{model}} WiQRdmodel×dk,WikRdmodel×dk,WiVRdmodel×dv,WORhdv×dmodel

论文中采用8个头, h = 8 h=8 h=8, d k = d v = d m o d e l / h = 64 d_k=d_v=d_{model}/h=64 dk=dv=dmodel/h=64.

如果single self-attention理解,那么这部分其实也很好理解:通过权重矩阵 W i Q , W i k , W i V W_i^Q,W_i^k,W_i^V WiQ,Wik,WiV Q Q Q K K K V V V 分割,即我们所说的头,每个头分别计算 single self-attention,因为权重矩阵 W i Q , W i k , W i V W_i^Q,W_i^k,W_i^V WiQ,Wik,WiV各不相同, Q W i Q , K W i k , V W i V QW_i^Q,KW_i^k,VW_i^V QWiQ,KWik,VWiV的结果各不相同,因此我们说每个头的关注点各有侧重。最后,将每个头计算出的 single self-attention进行concat,通过总的权重矩阵 W O W^O WO决定对每个头的关注程度,从而能够做到在不同语境下对相同句子进行不同理解。

一句话总结:Attention是将query和key映射到同一高维空间中去计算相似度,而对应的multi-head attention把query和key映射到高维空间 α \alpha α 的不同子空间 ( α 1 , α 2 , . . . , α h ) (\alpha_1,\alpha_2,...,\alpha_h) (α1,α2,...,αh) 中去计算相似度。

3.3 Position-wise Feed Forward

F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x) = max(0,xW_1+b_1)W_2+b_2 FFN(x)=max(0,xW1+b1)W2+b2

每一层经过attention之后,还会有一个FFN,这个FFN的作用就是空间变换。FFN包含了2层linear transformation层,中间的**函数是ReLu。

曾经我在这里有一个百思不得其解的问题:attention层的output最后会和 W O W_O WO 相乘,为什么这里又要增加一个2层的FFN网络?

其实,FFN的加入引入了非线性(ReLu**函数),变换了attention output的空间, 从而增加了模型的表现能力。把FFN去掉模型也是可以用的,但是效果差了很多。

3.4 Layer Normalization

在每个block中,最后出现的是Layer Normalization,其作用是规范优化空间,加速收敛
L N ( x i ) = α x i − μ i σ 2 + ξ + β LN(x_i) = \alpha\frac{x_i-\mu_i}{\sqrt{\sigma^2+\xi}}+\beta LN(xi)=ασ2+ξ xiμi+β

NLP学习笔记——Transformer模型

当我们使用梯度下降算法做优化时,我们可能会对输入数据进行归一化,但是经过网络层作用后,我们的数据已经不是归一化的了。随着网络层数的增加,数据分布不断发生变化,偏差越来越大,导致我们不得不使用更小的学习率来稳定梯度。Layer Normalization 的作用就是保证数据特征分布的稳定性,将数据标准化到ReLU**函数的作用区域,可以使得**函数更好的发挥作用

Normalization有两种方法,Batch Normalization和Layer Normalization。关于两者区别不再详述。

3.5 Positional Encoding

位置信息编码位于encoder和decoder的embedding之后,每个block之前。它非常重要,没有这部分模型就无法运行。Positional Encoding是transformer的特有机制,弥补了Attention机制无法捕捉sequence中token位置信息的缺点。
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) 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)}=sin(pos/10000^{2i/d_{model}})\\ PE_{(pos,2i+1)}=cos(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)
Positional Embedding的成分直接叠加于Embedding之上,使得每个token的位置信息和它的语义信息(embedding)充分融合,并被传递到后续所有经过复杂变换的序列表达中去。

NLP学习笔记——Transformer模型

使用Positional Encoding的优势

优势1

  • transformer中,模型输入encoder的每个token向量由两部分加和而成

    • Position Encoding
    • Input Embedding
  • transformer的特性使得输入encoder的向量之间完全平等(不存在RNN的recurrent结构),token的实际位置于位置信息编码唯一绑定。Positional Encoding的引入使得模型能够充分利用token在sequence中的位置信息。

优势2

论文中使用的Positional Encoding(PE)是正余弦函数,位置(pos)越小,波长越长,每一个位置对应的PE都是唯一的。同时作者也提到,之所以选用正余弦函数作为PE,是因为这可以使得模型学习到token之间的相对位置关系:因为对于任意的偏移量k, P E p o s + k PE_{pos+k} PEpos+k 可以由 P E p o s PE_{pos} PEpos 的线性表示:
P E ( p o s + k , 2 i ) = s i n ( ( p o s + k ) / 1000 0 2 i / d m o d e l ) P E ( p o s + k , 2 i + 1 ) = c o s ( ( p o s + k ) / 1000 0 2 i / d m o d e l ) PE_{(pos+k,2i)}=sin((pos+k)/10000^{2i/d_{model}})\\ PE_{(pos+k,2i+1)}=cos((pos+k)/10000^{2i/d_{model}}) PE(pos+k,2i)=sin((pos+k)/100002i/dmodel)PE(pos+k,2i+1)=cos((pos+k)/100002i/dmodel)
上面两个公式可以由 s i n ( p o s / 1000 0 2 i / d m o d e l ) sin(pos/10000^{2i/d_{model}}) sin(pos/100002i/dmodel) c o s ( p o s / 1000 0 2 i / d m o d e l ) cos(pos/10000^{2i/d_{model}}) cos(pos/100002i/dmodel)的线性组合得到。也就是 P E p o s PE_{pos} PEpos 乘上某个线性变换矩阵就得到了 P E p o s + k PE_{pos+k} PEpos+k

3.6 Mask 机制

mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。

  1. padding mask

    什么是 padding mask 呢?因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。

    具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0!

    而我们的 padding mask 实际上是一个张量,每个值都是一个Boolean,值为 false 的地方就是我们要进行处理的地方。

  2. Sequence mask

NLP学习笔记——Transformer模型

文章前面也提到,sequence mask 是为了使得 decoder 不能看见未来的信息。也就是对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。

那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的

  • 对于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同时需要padding mask 和 sequence mask 作为 attn_mask,具体实现就是两个mask相加作为attn_mask。
  • 其他情况,attn_mask 一律等于 padding mask。

3.7 Residual Network 残差网络

残差网络是深度学习中一个重要概念。在神经网络可以收敛的前提下,随着网络深度的增加,网络表现先是逐渐增加至饱和,然后迅速下降,这就是我们经常讨论的网络退化问题。

在transformer模型中,encoder和decoder各有6层,为了使当模型中的层数较深时仍然能得到较好的训练效果,模型中引入了残差网络。

残差连接可以使得网络只关注到当前差异的部分,公式如下所示:

NLP学习笔记——Transformer模型

NLP学习笔记——Transformer模型

关于残差网络的详细解释可以参考下面的博客:

https://zhuanlan.zhihu.com/p/80226180?utm_source=wechat_session

3.8 Linear & Softmax

Decoder最后是一个线性变换和softmax层。解码组件最后会输出一个实数向量。我们如何把浮点数变成一个单词?这便是线性变换层要做的工作,它之后就是Softmax层。
线性变换层是一个简单的全连接神经网络,它可以把解码组件产生的向量投射到一个比它大得多的、被称作对数几率(logits)的向量里。不妨假设我们的模型从训练集中学习一万个不同的英语单词(我们模型的“输出词表”)。因此对数几率向量为一万个单元格长度的向量——每个单元格对应某一个单词的分数(相当于做vocaburary_size大小的分类)。接下来的Softmax 层便会把那些分数变成概率(都为正数、上限1.0)。概率最高的单元格被选中,并且它对应的单词被作为这个时间步的输出。

NLP学习笔记——Transformer模型

Transformer中Encoder和Decoder模型结构到这里就介绍完了

模型整体运行过程如下图所示:

NLP学习笔记——Transformer模型

4.细节问题

  • 1… Transformer为什么需要进行Multi-head Attention

原论文中说到进行Multi-head Attention的原因是将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。其实直观上也可以想到,如果自己设计这样的一个模型,必然也不会只做一次attention,多次attention综合的结果至少能够起到增强模型的作用,也可以类比CNN中同时使用多个卷积核的作用,直观上讲,多头的注意力有助于网络捕捉到更丰富的特征/信息

  • 2.Transformer相比于RNN/LSTM,有什么优势?为什么?
  1. RNN系列的模型,并行计算能力很差。RNN并行计算的问题就出在这里,因为 T 时刻的计算依赖 T-1 时刻的隐层计算结果,而 T-1 时刻的计算依赖 T-2 时刻的隐层计算结果,如此下去就形成了所谓的序列依赖关系。

  2. Transformer的特征抽取能力比RNN系列的模型要好。

    具体实验对比可以参考:放弃幻想,全面拥抱Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较

    但是值得注意的是,并不是说Transformer就能够完全替代RNN系列的模型了,任何模型都有其适用范围,同样的,RNN系列模型在很多任务上还是首选,熟悉各种模型的内部原理,知其然且知其所以然,才能遇到新任务时,快速分析这时候该用什么样的模型,该怎么做好。

  • 3. 为什么说Transformer可以代替seq2seq?

seq2seq缺点:这里用代替这个词略显不妥当,seq2seq虽已老,但始终还是有其用武之地,seq2seq最大的问题在于将Encoder端的所有信息压缩到一个固定长度的向量中,并将其作为Decoder端首个隐藏状态的输入,来预测Decoder端第一个单词(token)的隐藏状态。在输入序列比较长的时候,这样做显然会损失Encoder端的很多信息,而且这样一股脑的把该固定向量送入Decoder端,Decoder端不能够关注到其想要关注的信息。

Transformer优点:transformer不但对seq2seq模型这两点缺点有了实质性的改进(多头交互式attention模块),而且还引入了self-attention模块,让源序列和目标序列首先“自关联”起来,这样的话,源序列和目标序列自身的embedding表示所蕴含的信息更加丰富,而且后续的FFN层也增强了模型的表达能力,并且Transformer并行计算的能力是远远超过seq2seq系列的模型,因此我认为这是transformer优于seq2seq模型的地方。

参考文章:

https://zhuanlan.zhihu.com/p/38485843

https://blog.****.net/weixin_41510260/article/details/101445016?utm_medium=distribute.pc_relevant.none-task-blog-title-3&spm=1001.2101.3001.4242

https://blog.****.net/urbanears/article/details/98742013

https://jalammar.github.io/illustrated-transformer/