【Transformer】什么是transformer? transformer输入输出是什么。transformer用于GPT的方法。tranformer的代码。chat-gpt

1 前言

  在自然语言处理领域,chat-GPT为这几年最让人感觉到强大的自然语言模型。GPT基于Transformer,Transformer又是基于attention机制。这次咱们从Encoder-Decoder->Attention->Transformer逐步讲解,一步一步深入。

2 Encoder-Decoder

2.1 Encoder-Decoder简介

  Encoder-Decoder框架顾名思义也就是编码-解码框架,目前大部分attention模型都是依附于Encoder-Decoder框架进行实现,在NLP中Encoder-Decoder框架主要被用来处理序列-序列问题。也就是输入一个序列,生成一个序列的问题。这两个序列可以分别是任意长度。具体到NLP中的任务比如:

  • 文本摘要,输入一篇文章(序列数据),生成文章的摘要(序列数据)
  • 文本翻译,输入一句或一篇英文(序列数据),生成翻译后的中文(序列数据)
  • 问答系统,输入一个question(序列数据),生成一个answer(序列数据)

基于Encoder-Decoder框架具体用的较多的应该就是seq2seq模型和Transformer了。
形象化的理解编码器可以理解为:Encoder相当于耳朵,用于读取并且编码原始的信息。Decoder相当于人的嘴巴,将大脑处理过的信息通过复杂网络之后输出得到表达的词语。

2.2 Encoder-Decoder结构原理

在这里插入图片描述

图1 NLP中编码器与解码器的结构图

  如图1所示是Encoder-Decoder框架在NLP领域中抽象后的最简单的结构图。经过原始句子转化成向量后,输入网络最终能够以一种词字典的概率输出,根据字典概率大小查询单词。
  Encoder:编码器,对于输入的序列 x 1 , x 2 , x 3 … x n x_1,x_2,x_3…x_n x1,x2,x3xn进行编码,使其转化为一个语义编码C,这个C中就储存了序列 x 1 , x 2 , x 3 , … , x n x_1,x_2,x_3,…,x_n x1,x2,x3,,xn的信息。Decoder:解码器,输出序列为图中的 y 1 , y 2 , . . . , y n y_1,y_2,...,y_n y1,y2,...,yn.

2.2.1 Encoder编码方式

  编码方式有很多种,在文本处理领域主要有: R N N / L S T M / G R U / B i R N N / B i L S T M / B i G R U RNN/LSTM/GRU/BiRNN/BiLSTM/BiGRU RNN/LSTM/GRU/BiRNN/BiLSTM/BiGRU.
在这里插入图片描述

图2 RNN编码单元

  以RNN为例来具体说明一下:以上图为例,输入 x 1 , x 2 , x 3 , x 4 x_1,x_2,x_3,x_4 x1,x2,x3,x4,通过RNN生成隐藏层的状态值 h 1 , h 2 , h 3 , h 4 h_1,h_2,h_3,h_4 h1,h2,h3,h4.之后需要计算中间的语义编码C,最简单的办法直接用最后时刻输出的 h t h_t ht作为C的状态值,这里也就是可以用 h 4 h_4 h4直接作为语义编码 C = q ( h 4 ) C=q(h_4) C=q(h4)的值,也可以将所有时刻的隐藏层的值进行汇总,然后生成语义编码C的值,那就是 C = q ( h 1 , h 2 , h 3 , h 4 ) C=q(h_1,h_2,h_3,h_4) C=q(h1,h2,h3,h4)q是非线性激活函数。如果想要知道如何计算得到的h,具体代码以及RNN计算过程,请看文章RNN如何进行编码
得到了语义编码C之后,接下来就是要在Decoder中对语义编码C进行解码了。

Decoder:解码器,根据输入的语义编码C,然后将其解码成序列数据,解码方式也可以采用RNN/LSTM/GRU/BiRNN/BiLSTM/BiGRU。Decoder和Encoder的编码解码方式可以任意组合.
常见的解码网络基于这两篇论文。

图3 解码方式-固定语义C

  论文1中指出,因为语义编码C包含了整个输入序列的信息,所以在解码的每一步都引入C。文中Ecoder-Decoder均是使用RNN,在计算每一时刻的输出yt时,都应该输入语义编码C,即 h t = f ( h t − 1 , y t − 1 , C ) , p ( y t ) = f ( h t , y t − 1 , C ) h_t=f(h_{t-1},y_{t-1},C),p(y_t)=f(h_t,y_{t−1},C) ht=f(ht1,yt1,C)p(yt)=f(ht,yt1,C) h t h_t ht为当前t时刻的隐藏层的值, y t − 1 y_{t-1} yt1为上一时刻的预测输出,作为t时刻的输入,且输出时每一时刻的语义编码C不变

图4 模型读取输入句子“ABC”并生成“WXYZ”作为输出句子

  论文2提出了一种基于Lstm的编码与解码的序列到序列的方法。在Decoder的初始输入引入语义编码C,将语义编码C作为隐藏层状态值h0的初始值, p ( y t ) = f ( h t , y t − 1 ) p(y_t)=f(h_t,y_{t−1}) p(yt)=f(ht,yt1)。这是一种动态的语义C的解码方式,语义C会随着解码的每一个时刻更新变化。

至于Decoder到底使用哪一种呢,答案是两种都不建议使用!
普通的Encoder-Decoder结构还是存在很多问题地:

1.如果按照论文1解码,每一时刻的输出如上式所示,从这里可以看出,在生成目标句子的单词时,不论生成哪个单词,是y1,y2也好,还是y3也好,他们使用的语义编码C都是一样的,没有任何区别。而语义编码C是由输入序列X的每个单词经过Encoder 编码产生的,这意味着不论是生成哪个单词,y1,y2还是y3,其实输入序列X中任意单词对生成某个目标单词yi来说影响力都是相同的,没有任何区别(其实如果Encoder是RNN的话,理论上越是后输入的单词影响越大,并非等权的,估计这也是为何Google提出Sequence to Sequence模型时发现把输入句子逆序输入做翻译效果会更好的小Trick的原因)

2.将整个序列的信息压缩在了一个语义编码C中,用一个语义编码C来记录整个序列的信息,序列较短还行,如果序列是长序列,比如是一篇上万字的文章,我们要生成摘要,那么只是用一个语义编码C来表示整个序列的信息肯定会损失很多信息,而且序列一长,就可能出现梯度消失问题,这样将所有信息压缩在一个C里面显然就不合理。

既然一个C不行,那咱们就用多个C,诶~这个时候基于Encoder-Decoder的attention model就出现了。

3 Attention Model

3.1 Attention 注意力机制简介

什么是注意力机制?
就上图为例,老实告诉我当你第一眼看到上图时,你的视线停留在哪个位置?对于我这种老二次元是在妹子身上,但是对于舰船迷来说,可能注意力就是在舰船上。同一张图片,不同的人观察注意到的可能是不同的地方,这就是人的注意力机制。attention 就是模仿人的注意力机制设计地。那么究竟是如何实现的呢?咱们接着往下看。

3.2 Attention 原理

  上图就是引入了Attention 机制的Encoder-Decoder框架。咱们一眼就能看出上图不再只有一个单一的语义编码C,而是有多个C1,C2,C3这样的编码。当我们在预测Y1时,可能Y1的注意力是放在C1上,那咱们就用C1作为语义编码,当预测Y2时,Y2的注意力集中在C2上,那咱们就用C2作为语义编码,以此类推,就模拟了人类的注意力机制。
那么现在只剩下一个问题就是怎么计算出C1,C2,C3…Cn呢?如何判断我每次在做解码的时候注意力应该放在哪个位置呢?以机器翻译例子"Tom chase Jerry" - "汤姆追逐杰瑞"来说明:
当我们在翻译"杰瑞"的时候,为了体现出输入序列中英文单词对于翻译当前中文单词不同的影响程度,比如给出类似下面一个概率分布值:
(Tom,0.3)(Chase,0.2)(Jerry,0.5)
每个英文单词的概率代表了翻译当前单词“杰瑞”时,注意力分配模型分配给不同英文单词的注意力大小。这对于正确翻译目标语单词肯定是有帮助的,因为引入了新的信息。同理,目标句子中的每个单词都应该学会其对应的源语句子中单词的注意力分配概率信息。这意味着在生成每个单词Yi的时候,原先都是相同的中间语义表示C会替换成根据当前生成单词而不断变化的Ci。理解AM模型的关键就是这里,即由固定的中间语义表示C换成了根据当前输出单词来调整成加入注意力模型的变化的Ci。f2(“Tom”),f2(“Chase”),f2(“Jerry”)就是对应的隐藏层的值h(“Tom”),h(“Chase”),h(“Jerry”)。g函数就是加权求和。αi表示权值分布。因此Ci的公式就可以写成:
C i = ∑ j = 1 n α i j h j C_i = \sum_{j=1}^n \alpha_{ij}h_j

那么现在的问题就只剩下,怎么知道attention模型所需要的输入句子单词注意力分配概率分布值呢?也就是αij?

以普通的RNN-RNN Encoder-Decoder结构为例,注意上图Decoder初始输入用初始符,这里使用eos作为初始符。将输入eos与初始S0通过RNN生成h(eos),然后分别计算h(eos)与h1,h2,h3…hm的相关性,这个相关性怎么计算一会儿再介绍。得到h(eos)与h1,h2,h3…hm的相关性评分[f1,f2,f3…fm],然后跟多分类一样使用softmax,就能得到相关性的概率分布α(eos)。
推广到预测decoder的每一个输出值Yi:

decoder上一时刻的输出值Yi-1与上一时刻传入的隐藏层的值Si-1通过RNN生成Hi,然后计算Hi与h1,h2,h3…hm的相关性,得到相关性评分[f1,f2,f3…fm],然后对Fi进行softmax就得到注意力分配αij。然后将encoder的输出值h与对应的概率分布αij进行点乘求和,就能得到注意力attention值了。
注意一下,这里咱们使用的是Soft Attention是所有的数据都会注意,都会计算出相应的注意力权值,不会设置筛选条件。还有一种Hard Attention会在生成注意力权重后筛选掉一部分不符合条件的注意力,让它的注意力权值为0,即可以理解为不再注意这些不符合条件的部分。

3.3Attention 机制的本质思想

上面咱们说了Attention的原理,但是是基于Encoder-Decoder框架来介绍地,Attention机制并不是一定要基于Encoder-Decoder框架,那么他的本质思想是什么呢?以及在上面遗留下来的Hi与h1,h2,h3…hm的相关性到底应该怎么算呢?现在就来为大家讲解!

参照上图可以这么来理解Attention,将Source中的构成元素想象成是由一系列的<Key,Value>数据对构成(对应到咱们上里面的例子,key和value是相等地,都是encoder的输出值h),此时给定Target中的某个元素Query(对应到上面的例子也就是decoder中的hi),通过计算Query和各个Key的相似性或者相关性,得到每个Key对应Value的权重系数,然后对Value进行加权求和,即得到了最终的Attention数值。所以本质上Attention机制是对Source中元素的Value值进行加权求和,而Query和Key用来计算对应Value的权重系数。即可以将其本质思想改写为如下公式:

Lx表示source的长度,Similarity(Q,Ki)计算如下:

MLP多层感知机感觉在这里用得比较少,反正我没怎么用过,就不介绍了。搞懂下面这两种计算相似性的方法:
点积:就是将Query和Keyi进行点积,Transformer中就是用的这种方法。
Cosine相似性-余弦相似度:
分子就是两个向量Query与Key的点积
分母就是两个向量的L2范数,(L2范数:指向量各元素的平方和然后求平方根)

计算出Query和Keyi的相似性后,第二阶段引入类似SoftMax的计算方式对第一阶段的相似性得分进行数值转换,一方面可以进行归一化,将原始计算分值整理成所有元素权重之和为1的概率分布;另一方面也可以通过SoftMax的内在机制更加突出重要元素的权重。即一般采用如下公式计算:

第二阶段的计算结果 ai 即为 Valuei 对应的权重系数,然后进行加权求和即可得到Attention数值:

通过如上三个阶段的计算,即可求出针对Query的Attention数值,目前绝大多数的注意力机制计算方法都符合上述的三阶段计算过程。

最后对上述计算Attention值地三个阶段做一个总结:

阶段1:Query与每一个Key计算相似性得到相似性评分s
阶段2:将s评分进行softmax转换成[0,1]之间的概率分布
阶段3:将[a1,a2,a3…an]作为权值矩阵对Value进行加权求和得到最后的Attention值

3.4Attention优缺点

看到这你应该已经能够Attention的强大之处了,但是如此强大的Attention真的是无懈可击,没有一点缺点的吗?
优点:
1.速度快。Attention机制不再依赖于RNN,解决了RNN不能并行计算的问题。这里需要说明一下,基于Attention机制的seq2seq模型,因为是有监督的训练,所以咱们在训练的时候,在decoder阶段并不是说预测出了一个词,然后再把这个词作为下一个输入,因为有监督训练,咱们已经有了target的数据,所以是可以并行输入的,可以并行计算decoder的每一个输出,但是再做预测的时候,是没有target数据地,这个时候就需要基于上一个时间节点的预测值来当做下一个时间节点decoder的输入。所以节省的是训练的时间。
2.效果好。效果好主要就是因为注意力机制,能够获取到局部的重要信息,能够抓住重点。
缺点:
1.只能在Decoder阶段实现并行运算,Encoder部分依旧采用的是RNN,LSTM这些按照顺序编码的模型,Encoder部分还是无法实现并行运算,不够完美。
2.就是因为Encoder部分目前仍旧依赖于RNN,所以对于中长距离之间,两个词相互之间的关系没有办法很好的获取。

为了改进上面两个缺点,更加完美的Self-Attention出现了。

4.Self-Attention

在一般任务的Encoder-Decoder框架中,输入Source和输出Target内容是不一样的,比如对于英-中机器翻译来说,Source是英文句子,Target是对应的翻译出的中文句子,Attention机制发生在Target的元素和Source中的所有元素之间。而Self Attention顾名思义,指的不是Target和Source之间的Attention机制,而是Source内部元素之间或者Target内部元素之间发生的Attention机制,也可以理解为Target=Source这种特殊情况下的注意力计算机制。其具体计算过程是一样的,只是计算对象发生了变化而已,相当于是Query=Key=Value,计算过程与attention一样,所以这里不再赘述其计算过程细节。

例如上图是self-attention的一个例子:
我们想知道这句话中的its,在这句话里its指代的是什么,与哪一些单词相关,那么就可以将its作为Query,然后将这一句话作为Key和Value来计算attention值,找到与这句话中its最相关的单词。通过self-attention我们发现its在这句话中与之最相关的是Law和application,通过我们分析语句意思也十分吻合。
如此引入Self Attention后会更容易捕获句子中长距离的相互依赖的特征,因为如果是RNN或者LSTM,需要依次序序列计算,对于远距离的相互依赖的特征,要经过若干时间步步骤的信息累积才能将两者联系起来,而距离越远,有效捕获的可能性越小。但是Self Attention在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,所以远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征。除此外,Self Attention对于增加计算的并行性也有直接帮助作用。正好弥补了attention机制的两个缺点,这就是为何Self Attention逐渐被广泛使用的主要原因。

5 Transformer 原理

5.1 Transformer整体结构

上图是Transformer的完整结构图,小朋友你是否有很多问号???这都是些什么鬼,告辞!!!诶诶~先别走,接下来咱们就一步一步来攻克Transformer。

Transformer的结构图,拆解开来,主要分为图上4个部分,其中最重要的就是2和3Encoder-Decoder部分,对咯,Transformer是一个基于Encoder-Decoder框架的模型。
接下来我将按照1,2,3,4的顺序逐步介绍上图中Transformer的网络结构,这样既能够弄清楚结构原理,又能够方便理解Transformer模型的工作流程。

5.2 Transformer的inputs 输入

Transformer输入是一个序列数据,还是以上篇中提到的"Tom chase Jerry" 翻译成中文"汤姆追逐杰瑞"为例:
Encoder 的 inputs就是"Tom chase Jerry" 分词后的词向量。可以是任意形式的词向量,如word2vec,GloVe,one-hot编码。

假设上图中每一个词向量都是一个512维的词向量。

我们注意到,输入inputs embedding后需要给每个word的词向量添加位置编码positional encoding,为什么需要添加位置编码呢?
首先咱们知道,一句话中同一个词,如果词语出现位置不同,意思可能发生翻天覆地的变化,就比如:我欠他100W 和 他欠我100W。这两句话的意思一个地狱一个天堂。可见获取词语出现在句子中的位置信息是一件很重要的事情。但是咱们的Transformer 的是完全基于self-Attention地,而self-attention是不能获取词语位置信息地,就算打乱一句话中词语的位置,每个词还是能与其他词之间计算attention值,就相当于是一个功能强大的词袋模型,对结果没有任何影响。(一会儿在介绍Encoder的时候再详细说明)所以在我们输入的时候需要给每一个词向量添加位置编码。

问题又来了,这个positional encoding怎么获取呢?
1.可以通过数据训练学习得到positional encoding,类似于训练学习词向量,goole在之后的bert中的positional encoding便是由训练得到地。
2.《Attention Is All You Need》论文中Transformer使用的是正余弦位置编码。位置编码通过使用不同频率的正弦、余弦函数生成,然后和对应的位置的词向量相加,位置向量维度必须和词向量的维度一致。过程如上图,PE(positional encoding)计算公式如下:

解释一下上面的公式:
pos表示单词在句子中的绝对位置,pos=0,1,2…,例如:Jerry在"Tom chase Jerry"中的pos=2;dmodel表示词向量的维度,在这里dmodel=512;2i和2i+1表示奇偶性,i表示词向量中的第几维,例如这里dmodel=512,故i=0,1,2…255。
至于上面这个公式是怎么得来地,其实不重要,因为很有可能是作者根据经验自己造地,而且公式也不是唯一地,后续goole在bert中的positional encoding也没有再使用这种方法而是通过训练PE,说明这种求位置向量的方法还是存在一定问题地。
这里我就不做详细的介绍了,想要深究的朋友可以参考一下知乎上的这些回答:如何理解Transformer论文中的positional encoding,和三角函数有什么关系?

为什么是将positional encoding与词向量相加,而不是拼接呢?
拼接相加都可以,只是本身词向量的维度512维就已经蛮大了,再拼接一个512维的位置向量,变成1024维,这样训练起来会相对慢一些,影响效率。两者的效果是差不多地,既然效果差不多当然是选择学习习难度较小的相加了。

Transformer 的 Decoder的输入与Encoder的输出处理方法步骤是一样地,一个接受source数据,一个接受target数据,对应到上面例子里面就是:Encoder接受英文"Tom chase Jerry",Decoder接受中文"汤姆追逐杰瑞"。只是在有target数据时也就是在进行有监督训练时才会接受Outputs Embedding,进行预测时则不会接收。

至此,Transformer的第一块输入部分已经讲解完了,接下来就要进入重点部分Encoder和Decoder了。

5.3 Transformer的Encoder

看上图第2部分 Encoder block。Encoder block是由6个encoder堆叠而成,Nx=6。上图2中的灰框部分就是一个encoder的内部结构,从图中我们可以看出一个encoder由Multi-Head Attention 和 全连接神经网络Feed Forward Network构成。

5.3.1 Multi-Head Attention

首先回顾一下self-attention,假如输入序列是"Thinking Machines",x1,x2就是对应地"Thinking"和"Machines"添加过位置编码之后的词向量,然后词向量通过三个权值矩阵W Q , W K , W V WQ,WK,W^VW
Q
,W
K
,W
V
,转变成为计算Attention值所需的Query,Keys,Values向量。

因为咱们再实际使用中,每一个样本,也就是每一条序列数据都是以矩阵的形式输入地,故可以看到上图中,X矩阵是由"Tinking"和"Machines"词向量组成的矩阵,然后跟过变换得到Q,K,V。假设词向量是512维,X矩阵的维度是(2,512),W Q , W K , W V WQ,WK,W^VW
Q
,W
K
,W
V
均是(512,64)维,得到的Query,Keys,Values就都是(2,64)维。

得到Q,K,V之后,接下来就是计算Attention值了。
步骤1: 输入序列中每个单词之间的相关性得分,上篇中说过计算相关性得分可以使用点积法,就是用Q中每一个向量与K中每一个向量计算点积,具体到矩阵的形式:s c o r e = Q ⋅ K T score = Q\cdot K^Tscore=Q⋅K
T
,socre是一个(2,2)的矩阵
步骤2: 对于输入序列中每个单词之间的相关性得分进行归一化,归一化的目的主要是为了训练时梯度能够稳定。s c o r e = s c o r e / d k score = score/\sqrt{d_k}score=score/
d
k


,dk就是K的维度,以上面假设为例,dk=64
步骤3: 通过softmax函数,将每个单词之间的得分向量转换成[0,1]之间的概率分布,同时更加凸显单词之间的关系。经过softmax后,score转换成一个值分布在[0,1]之间的(2,2)α概率分布矩阵
步骤4: 根据每个单词之间的概率分布,然后乘上对应的Values值,α与V进行点积,Z = s o f t m a x ( s c o r e ) ⋅ V Z = softmax(score)\cdot VZ=softmax(score)⋅V,V的为维度是(2,64),(2,2)x(2,64)最后得到的Z是(2,64)维的矩阵
整体的计算图如下:

说了这么多好像都只是在说self-attention,那么Multi-Head Attention呢?

Multi-Head Attention 很简单,就是在self-attention的基础上,对于输入的embedding矩阵,self-attention只使用了一组W Q , W K , W V WQ,WK,W^VW
Q
,W
K
,W
V
来进行变换得到Query,Keys,Values。而Multi-Head Attention使用多组W Q , W K , W V WQ,WK,W^VW
Q
,W
K
,W
V
得到多组Query,Keys,Values,然后每组分别计算得到一个Z矩阵,最后将得到的多个Z矩阵进行拼接。Transformer里面是使用了8组不同的W Q , W K , W V WQ,WK,W^VW
Q
,W
K
,W
V

从上图中可以看到,在经过Multi-Head Attention得到矩阵Z之后,并没有直接传入全连接神经网络FNN,而是经过了一步:Add&Normalize。

Add&Normalize:

Add

Add,就是在Z的基础上加了一个残差块X,加入残差块X的目的是为了防止在深度神经网络训练中发生退化问题,退化的意思就是深度神经网络通过增加网络的层数,Loss逐渐减小,然后趋于稳定达到饱和,然后再继续增加网络层数,Loss反而增大。可能看到这里,小朋友你一定有很多问号???为什么深度神经网络会发生退化,为什么添加残差块能够防止退化问题,残差块又是什么?这就牵扯到ResNet残差神经网络的知识了,既然是史上最小白系列,坚决不做标题党,一定把每个问题都解释清楚!

5.3.2 ResNet 残差神经网络:

首先解答第一个问题,为什么深度神经网络会发生退化?
举个例子:假如某个神经网络的最优网络层数是18层,但是我们在设计的时候并不知道到底多少层是最优解,本着层数越深越好的理念,我们设计了32层,那么32层神经网络中有14层其实是多余地,我们要想达到18层神经网络的最优效果,必须保证这多出来的14层网络必须进行恒等映射,恒等映射的意思就是说,输入什么,输出就是什么,可以理解成F(x)=x这样的函数,因为只有进行了这样的恒等映射咱们才能保证这多出来的14层神经网络不会影响我们最优的效果。
但现实是神经网络的参数都是训练出来地,要想保证训练出来地参数能够很精确的完成F(x)=x的恒等映射其实是很困难地。多余的层数较少还好,对效果不会有很大影响,但多余的层数一多,可能结果就不是很理想了。这个时候大神们就提出了ResNet 残差神经网络来解决神经网络退化的问题。

残差块是什么?

上图就是构造的一个残差块,可以看到X是这一层残差块的输入,也称作F(X)为残差,X为输入值,F(X)是经过第一层线性变化并激活后的输出,该图表示在残差网络中,第二层进行线性变化之后激活之前,F(X)加入了这一层输入值X,然后再进行激活后输出。在第二层输出值激活前加入X,这条路径称作shortcut连接。

为什么添加了残差块能防止神经网络退化问题呢?
咱们再来看看添加了残差块后,咱们之前说的要完成恒等映射的函数变成什么样子了。是不是就变成h(X)=F(X)+X,我们要让h(X)=X,那么是不是相当于只需要让F(X)=0就可以了,这里就巧妙了!神经网络通过训练变成0是比变成X容易很多地,因为大家都知道咱们一般初始化神经网络的参数的时候就是设置的[0,1]之间的随机数嘛。所以经过网络变换后很容易接近于0。举个例子:

假设该网络只经过线性变换,没有bias也没有激活函数。我们发现因为随机初始化权重一般偏向于0,那么经过该网络的输出值为[0.6 0.6],很明显会更接近与[0 0],而不是[2 1],相比与学习h(x)=x,模型要更快到学习F(x)=0。
并且ReLU能够将负数激活为0,过滤了负数的线性变化,也能够更快的使得F(x)=0。这样当网络自己决定哪些网络层为冗余层时,使用ResNet的网络很大程度上解决了学习恒等映射的问题,用学习残差F(x)=0更新该冗余层的参数来代替学习h(x)=x更新冗余层的参数。
这样当网络自行决定了哪些层为冗余层后,通过学习残差F(x)=0来让该层网络恒等映射上一层的输入,使得有了这些冗余层的网络效果与没有这些冗余层的网络效果相同,这样很大程度上解决了网络的退化问题。

到这里,关于Add中为什么需要加上一个X,要进行残差网络中的shortcut你清楚了吗?Transformer中加上的X也就是Multi-Head Attention的输入,X矩阵。

5.3.3 Normalize

为什么要进行Normalize呢?
在神经网络进行训练之前,都需要对于输入数据进行Normalize归一化,目的有二:1,能够加快训练的速度。2.提高训练的稳定性。

为什么使用Layer Normalization(LN)而不使用Batch Normalization(BN)呢?

先看图,LN是在同一个样本中不同神经元之间进行归一化,而BN是在同一个batch中不同样本之间的同一位置的神经元之间进行归一化。
BN是对于相同的维度进行归一化,但是咱们NLP中输入的都是词向量,一个300维的词向量,单独去分析它的每一维是没有意义地,在每一维上进行归一化也是适合地,因此这里选用的是LN。

Feed-Forward Networks

全连接层公式如下:
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,xW
1

+b
1

)W
2

+b
2

这里的全连接层是一个两层的神经网络,先线性变换,然后ReLU非线性,再线性变换。
这里的x就是我们Multi-Head Attention的输出Z,还是引用上面的例子,那么Z是(2,64)维的矩阵,假设W1是(64,1024),其中W2与W1维度相反(1024,64),那么按照上面的公式:
FFN(Z)=(2,64)x(64,1024)x(1024,64)=(2,64),我们发现维度没有发生变化,这两层网络就是为了将输入的Z映射到更加高维的空间中(2,64)x(64,1024)=(2,1024),然后通过非线性函数ReLU进行筛选,筛选完后再变回原来的维度。

然后经过Add&Normalize,输入下一个encoder中,经过6个encoder后输入到decoder中,至此Transformer的Encoder部分就全部介绍完了,搞懂了Encoder那么Decoder就so easy啦,基本上结构和Encoder差不多,接下来咱们就进入Decoder部分吧~

5.4 Transformer的Decoder

看上图第3部分 Decoder block。Decoder block也是由6个decoder堆叠而成,Nx=6。上图3中的灰框部分就是一个decoder的内部结构,从图中我们可以看出一个decoder由Masked Multi-Head Attention,Multi-Head Attention 和 全连接神经网络FNN构成。比Encoder多了一个Masked Multi-Head Attention,其他的结构与encoder相同,那么咱们就先来看看这个Masked Multi-Head Attention。

Transformer Decoder的输入

Decoder的输入分为两类:
一种是训练时的输入,一种是预测时的输入。
训练时的输入就是已经对准备好对应的target数据。例如翻译任务,Encoder输入"Tom chase Jerry",Decoder输入"汤姆追逐杰瑞"。
预测时的输入,一开始输入的是起始符,然后每次输入是上一时刻Transformer的输出。例如,输入"“,输出"汤姆”,输入"汤姆",输出"汤姆追逐",输入"汤姆追逐",输出"汤姆追逐杰瑞",输入"汤姆追逐杰瑞",输出"汤姆追逐杰瑞"结束。

Masked Multi-Head Attention

与Encoder的Multi-Head Attention计算原理一样,只是多加了一个mask码。mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。为什么需要添加这两种mask码呢?

1.padding mask
什么是 padding mask 呢?因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。
具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0!

2.sequence mask
sequence mask 是为了使得 decoder 不能看见未来的信息。对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。这在训练的时候有效,因为训练的时候每次我们是将target数据完整输入进decoder中地,预测时不需要,预测的时候我们只能得到前一时刻预测出的输出。
那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。

上面可能忘记说了,在Encoder中的Multi-Head Attention也是需要进行mask地,只不过Encoder中只需要padding mask即可,而Decoder中需要padding mask和sequence mask。OK除了这点mask不一样以外,其他的部分均与Encoder一样啦~

Add&Normalize也与Encoder中一样,接下来就到了Decoder中第二个Multi-Head Attention,这个Multi-Head Attention又与Encoder中有一点点不一样。

基于Encoder-Decoder 的Multi-Head Attention
Encoder中的Multi-Head Attention是基于Self-Attention地,Decoder中的第二个Multi-Head Attention就只是基于Attention,它的输入Quer来自于Masked Multi-Head Attention的输出,Keys和Values来自于Encoder中最后一层的输出。

跟我一样的牛角尖型选手可能又要发问啦,为啥Decoder中要搞两个Multi-Head Attention呢?
我个人理解是第一个Masked Multi-Head Attention是为了得到之前已经预测输出的信息,相当于记录当前时刻的输入之间的信息的意思。第二个Multi-Head Attention是为了通过当前输入的信息得到下一时刻的信息,也就是输出的信息,是为了表示当前的输入与经过encoder提取过的特征向量之间的关系来预测输出。

经过了第二个Multi-Head Attention之后的Feed Forward Network与Encoder中一样,然后就是输出进入下一个decoder,如此经过6层decoder之后到达最后的输出层。

5.5 Transformer的输出

Output如图中所示,首先经过一次线性变换,然后Softmax得到输出的概率分布,然后通过词典,输出概率最大的对应的单词作为我们的预测输出。

5.6 结构总结

好啦,以上就是Transformer的全部结构原理啦,Transformer真的不愧是近几年来最火的模型,很多细节都很巧妙,真的想要搞懂还是需要花点心思地。不知道看到这里,小伙伴们对于Transformer的结构有没有清晰一些呢?

6 Transformer优缺点

Transformer虽然好,但它也不是万能地,还是存在着一些不足之处,接下来就来介绍一下它的优缺点:
优点:
1.效果好
2.可以并行训练,速度快
3.很好地解决了长距离依赖的问题
缺点:
1.完全基于self-attention,对于词语位置之间的信息有一定的丢失,虽然加入了positional encoding来解决这个问题,但也还存在着可以优化的地方。

7 结语

Transformer是非常有潜力的模型,在Transformer基础上后来又衍生出来了BERT和GPT这两个NLP神器,而且依旧还存在着许多可以优化的地方。目前NLP在工业上的应用远不及CV广,但是自然语言是人类文明得以延续的重要的信息。没有文字,怎么回首古人的发展历史,没有语言,人类社会又怎么能够和谐运转,你看到的任何图片,听到的任何话语都在大脑里转换成里你自己能理解地文字信息,语言信息,所以NLP的前景依旧是无比巨大地。这是最好的时代,正因为NLP还一直处于探索阶段,所以现在开始学习仍旧不晚,史上最小白系列也写了几期了,我会一直写下去地,希望史上最小白系列能够对于初入NLP的同学有所帮助吧。
本人才疏学浅,有写错或者不懂的地方欢迎指正~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值