赞
踩
Transformer是近几年来在深度学习领域中又一项重大的突破,被誉为是继MLP、RNN、CNN之后的第四大基础模型。接下来我们将以Transformer的模型架构为核心,跟着输入数据的脚步,一步步解析Transformer是如何构建和学习的,以及它的亮点与创新性在哪里,解决了过往模型中的哪些痛点。
目录
2.2.1 Input Embedding/Output Embedding
2.2.2 Positional Encoding(位置编码)
2.2.3 self-attention、 Multi-Head Attention与Masked Multi-Head Attention
2.2.5 Add&Norm(BatchNorm与LayerNorm)
Transformer也是序列转录(Seq2seq)模型的一种(序列转录模型:输入是一组序列,输出也是一组序列)。以往的序列转录模型大多都是依靠较为复杂的RNN和CNN来实现的。那么想了解Transformer是如何突破的,我们先简单了解CNN与RNN存在的问题与不足之处。
(1):RNN(循环神经网络)
1.并行度低:我们知道循环神经网络(RNN)是一个有记忆的网络,在此基础上改进的LSTM上也有不错的表现。但这也产生了一些难以改进的问题,即想要处理T时刻的信息,就必须先处理完T-1时刻的信息。无法实现并行处理,这在当前多卡训练的场合下是很吃亏的。
2.早前的记忆丢失:当输入数据较为庞大的时候,早期的信息将会被遗弃(除非我们存储记忆的数据序列足够大,但这会降低效率)。
(2):CNN(卷积神经网络)
1.CNN对于比较长的序列难以建模:卷积神经网络是通过卷积核进行窗口滑动的方式进行卷积运算,从而提取需要的特征。这的确可以很好你的保存相邻元素之间的关系,那么如果第一个元素和最后一个元素的关系十分重要。我们就只能通过很多层卷积才可以实现(当feature_map大小远大于卷积核时)。
了解完RNN与CNN存在的问题之后,我们不难发现,如果我们能看到完整的输入数据并且能灵活使用就能解决以上问题。这也正是Transformer的核心:将所有的循环层RNN替换成了Mutle-head self-attention(多头的自注意力机制,后面会详细介绍)。也就是说,Transformer是纯基于注意力机制的模型(注意力机制并不是首次使用,但是Transformer是首个基于纯注意力机制的模型)。
上文说到Transformer是基于纯注意力机制的模型,以下就是它的模型结构示意图。整体的框架结构是encoder-decoder(编码器与解码器)模型,左半边为encoder,右边为decoder,Nx的意思是有N个这样的模块进行堆叠。
在挨个模块详细介绍之前,我么先简单了解各个模块是什么。对整体体的认知有助于对局部的理解和记忆。
(1): Input Embedding/Output Embedding:将输入传入Embedding层使之转换为模型可以理解的张量(tensor)形式。
(2):Positional Encoding(位置编码)(长得像太极图标的):添加了对每个输入值的位置信息。用一个维度dim=512的向量表示,之后与输入的input Embedding相连。
(3):Multi-Head Attention(橙色方框):这就是Transformer的核心,多头注意力机制。而Masked Multi-Head Attention则是带掩码的多头注意力机制(后面会详解)。
(4):Add&Norm(黄色框):这里使用了残差连接和Layer norm正则化,将Multi-Head Attention的输出和输入直接相连。这里的重点在于,正则化不再使用过往的Batch norm,而是Layer norm(后面会详细介绍)。
(5):Feed Forward(蓝色框):这里其实就是一个MLP,其本身是没有什么特别的。特别之处在于它是单独作用于每个输入(经过残差连接之后的输出)。
对每个方框有大致的了解之后,我们来看看整体流程。编码器(encoder)的输出作为解码器(decoder)的输入。[说明:细心的小伙伴会发现,在解码器和编码器对接位置的Multi-Head Attention中只有部分输入(两个箭头)来自于encoder,说明此处的Multi-Head Attention是非自注意力机制。而其余的(Masked)Multi-Head Attention则是自注意力机制(self-attention)] 当前解码器的输出又将成为下一次解码器的输入,我们称这中模式为自回归(auto-regressive)。
我们将会按照输入数据所经过的层的顺序对上述局部网络架构进行解析。
Embedding层在许多模型中都有使用。它的作用是可以对输入对象进行升维和降维的操作。这类似于CNN中的1X1卷积操作。在输入数据进行one-hot编码之后形成的稀疏矩阵过大的话,可以通过Embedding层进行降维。这里Transformer将输入转化为512。
我们之前说过,Transformer中attention机制的亮点在于可以观察到整个输入,这样就可以进行并行计算了,大大提升了模型训练的效率。但是问题也随之而来,我们也同时需要关注每个输入的具体位置信息。Positional Encoding由此而生。
此处的pos表示的是当前输入张量的元素位置(“深度学习”,这里“深”的pos=0).dmodel表示经过Embedding层之后的张量长度,此处为512。两条式子是在i等于奇数和偶数两种情况时分别使用。
终于来到Transformer的网络核心啦。首先我们先来讲述self-attention机制的工作原理,Multi-Head只是在其基础之上进行多头输出模式,而Masked Multi-Head Attention则是带掩码的多头注意力机制。
我们不难发现,每当数据到达Multi-Head Attention(self-attention也是如此)的网络架构时,都会分为三部分输入(如下图所示)。 三部分输入分别为k、v、q。这三部分都是张量,都是通过输入向量本身✖相应权重W(q)、W(k)、W(v)获得的。v表示输入特征的向量,k和q是用于计算输入向量之间彼此的关联程度。
那么在讲解之前我们要先明白为什么要使用多头的注意力机制。这里是受到了CNN的启发,CNN每一层卷积都能获取不同的feature-map。我们可以这样理解,一组k、q、v得到的输出就是等价于一张feature-map。那么为了获得更多不同的特征,我们需要等多组的q、k、v。那么就需要多个输出头进行输出。
接下来就让我们看看k、q、v之间是如何进行计算从而得到输出的。
我们在这里针对词性对应的情况讲解self-attention,即输入tensor数量等于输出的tensor数量,它们拥有一一对应的关系(transformer是Seq2seq模式,即输入n,输出m。m和n并没有明确的关系)。attention被称为注意力机制,解释起来就是,它能关注整体的输入从中找到值得我们关注的点。所以实现的关键点在于找了输入彼此之间的关系(通过k、q、v),才能知道哪些是值得关注和保留的地方。self-attention则是q除了和其他输入的k进行计算时,还会同自身的k进行计算。
计算输入tensor(a1~a4)彼此相关性的方法流程如下(当我们求输入a1与a2~an之间的关系,并得到a1对应输出b1):
q和k之间的具体计算过程如下图。这里计算的方法不唯一,Transformer是使用左边点积的方式(Dot-product),通常点积之后输出之后还会经过softmax层。
我么可以发现,其实self-attention实现的就是找到一组正确的W(q)、W(k)、W(v),从而找到正确的q、k、v,所以训练过程其实就是在计算W(q)、W(k)、W(v)的过程。上述解释了得到输入a1对应的输出b1。输出b2~bn也是如法炮制。但需要注意的是,我们并不是将b1到bn的每一组的W(q)、W(k)、W(v)单独计算,而是将其放到一个矩阵中共同计算,其示意图如下所示(其中I是输入向量组成的矩阵,O是输出向量组成的矩阵):
这就是self-attention的内部实现过程。那么Multi-Head Attention只是在self-attention的基础之上在每个输入a上配备了多组q、k、v。如下图所示(需要注意的是,qi1只会和ki1进行计算,不会和ki2~kin进行计算,也就是说,多头之间的计算彼此之间是互不影响的):
接下来就是Masked Multi-Head Attention。在简述中说过它的作用就是在Multi-Head Attention的基础上添加掩码,使得在计算t位置的输出时(假设为b4),那么网络只能看见t0~t-1位置上的输入(看见a0~a4,看不到a5~an)。
那我们就会你有一个疑惑,attention机制的优势不就是看到全局输入吗?这样做的目的是什么呢?其实这是为了模拟网络在预测时候的情形。预测过程中输出(b1~bn)是一个一个输出的,而不是一起输出的。所以Masked Multi-Head Attention被放在解码器上 ,而编码器上没有Masked。
在上文中我们提到,其实这里的Feed Forward就是MLP。但是我们并不是将所有Multi-Head Attention的输出一起放入一个MLP的。而是每个Multi-Head Attention输出单独分配一个相同的MLP,原因在于我们经过Multi-Head Attention之后的输出已经计算好了输入之间彼此的相关性。下图展示了Transformer和RNN中MLP和记忆过往信息的不同之处
上文中说到Norm使用的是LayerNorm, 不同于以往CNN中的BatchNorm。两者都是正则化的方式,计算公式都相同,不同之处在于计算均值和方差的方式和对象不同。在弄清问什么要使用LayerNorm而不用BatchNorm之前,我们先来看看它们的不同之处。以下是两者的计算公式:
E[x]是均值,Var[x]为方差。其余的参数都是可学习的,在这里不多赘述。以下分别是两者计算均值和方差的方式:
我们在这里举个栗子,我们将上述的W和H看作是书中的一页纸的长和宽。C表示页数,那么上述就有N本书(一批次的序列数量),每本书有C页(feature_map的数量),每页的大小为WxH(feature_map的大小)。
(1)BatchNorm:计算均值和方差的对象是每个序列相同的feature(每本书的同一页)
(2)LayerNorm:计算均值和方差的对象是单个序列的所有feature_map(同一本书的所有页数)
总结起来如下图所示:
那我们为什么要使用LayerNorm而不用BatchNorm呢?我们还是可以通过上述书本的那个栗子说明。在CNN中,每本书的页数是默认相同的。但是在Transformer中(以NLP为例)我们输入的序列是长短不一的。并且,我们同一序列中的信息关系可能更为紧密(毕竟是在同一本书中)。
总的来说,也是有实验说明在Transformer中使用LayerNorm的效果更好。
这里单独抽出来来讲讲encoder与decoder两者连接的地方,方便我们从细节处回到整体,加深对模型结构的印象和理解。
我们来详细解析一下,这里有几个值得注意的地方。
(1):这里连接encoder和decoder的 Multi-Head Attention是非自注意力机制。原因在于这里的k、v、q并不是来源于同一个输出。这里的q是来源于上一个Output经过一个Masked Multi-Head Attention和Add&Norm层之后的输出,而k、v来源于encoder编码器。
(2):在图上画的三种颜色(蓝、绿、红)的序列中,我们可以看到输出和输入之间已经有明显的对应关系了。我们以输入为英文,输出为中文举例。明显“好”与“Hello”之间的关系(attention-顺score)最高。
本篇博客是以Transformer的架构为核心,数据流动顺序为思路进行解析的。其中还有许多未提及的知识,比如模型的参数配置,训练过程。这些都是在原论文上有详细的讲解。Transformer从起初用于NLP,到现在被广泛用于各个领域,并且经过调整之后也有衍生出许多以Transformer为backbone的优秀模型,如segformer,VIT等等。更详细的解读希望大家可以去阅读原论文。
如果本篇博客对你有所帮助,期待你的一键三连哈~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。