想研究BERT模型?先看看这篇文章吧!

最近,笔者想研究BERT模型,然而发现想弄懂BERT模型,还得先了解Transformer。 本文尽量贴合Transformer的原论文,但考虑到要易于理解,所以并非逐句翻译,而是根据笔者的个人理解进行翻译,其中有一些论文没有解释清楚或者笔者未能深入理解的地方,都有放出原文,如有不当之处,请各位多多包含,并希望得到指导和纠正。

论文标题

  • Attention Is ALL You Need

论文地址

摘要

序列转换方式由基于复杂递归神经网络(RNN)和卷积神经网络(CNN)的编码器和解码器模型主导。表现最佳的模型也只是通过一个注意力机制来连接了编码器和解码器。我们提出一个新的简单网络架构——Transformer。相比表现最佳的模型,该架构仅仅基于注意力机制,完全摒弃了递归和卷积。从两个机器翻译任务的实验结果显示,Transformer的效果更优秀,同时有更好的并行性,显著的减少了训练的时间。我们的模型在WMT2014年发布的“英-德”翻译任务上达到了28.4 BLEU【注解1】,超越了该任务上现有的最好的记录2个BLEU,包括总体效果。在英-法翻译任务上,我们的模型在8块GPU上训练了3.5天,并创造了单模型最好BLEU分数——41.8。相比文献中的最佳模型,这个训练成本不高。Transformer在其它任务上也有好的泛化能力,我们将其应用于English constituency parsing(英语成分句法分析),无论在大量的训练数据上还是有限的训练数据上都获得了成功。

1 引言

RNN,LSTM和GRNN已经是序列建模、语言建模、机器翻译领域公认的最好方法。之后,仍然有很多人努力推进循环语言模型(recurrent language models)和encoder-decoder架构的边界。

循环模型(RNN)通常将输入和输出序列的符号的位置作为因素进行计算。将位置与计算时间步对齐的过程中,会根据前一个隐藏状态ht-1和位置t的输入来生成一系列的隐藏状态ht【注解2】。这种固有的相继的性质使得训练样本无法并行训练,这个问题在面对更长序列,并且内存不足以提供更大的批训练的时候尤其关键。近期,人们通过因式分解(factorization)技巧和条件计算(conditional computation),改善了计算效率(后者同时提高了模型的表现)。然而,固有的相继的性质还没有得到解决。

注意力机制在各种序列建模和转换模型的任务中,已经成为不可分割的部分。它使得可以在对符合间的依存关系进行建模的时候,不考虑符号间的距离。然而,大多数情况下,这样的注意力机制是和RNN一起使用的。

此处,我们提出Transformer,该模型架构摒弃了循环,而采用完全依赖注意力机制来绘制输入和输出之间的全局依存关系的方式。Transformer模型有着更好的并行性,在翻译质量上达到了新的高度,而这样的Transformer模型在8块P100GPU上训练仅需要12小时。

2 背景

减少循序计算(sequential computation)的目标也构成了Extended Neural GPU,ByteNet和ConvS2S的基础,这些都使用CNN作为基础构建块,为所有输入和输出的位置并行的计算隐藏表征。对于这些模型,从2个任意的输入或输出位置关联信号所需要的操作次数会随着位置之间的距离的增加而增加,在ConvS2S中是线性增加,在ByteNet中是对数增加。这使得在两个远距离的位置间的依存关系的学习变得更加困难。在Transformer中,这个问题减轻为一个常量次数的操作,这固然会因为经过平均注意力加权的位置而降低有效的信息分辨率,我们应对的策略是采用Multi-Head Attention来抵消这个问题。(大致的理解:注意力机制虽然将序列操作次数固定为一个常量,但本身会丢失一些位置信息,通过Multi-Head 的方式可以弥补这个问题)

Self-attention,有时候又称为intra-attention,是一种关联单一序列的不同位置的注意力机制,为了计算该序列的表征。Self-attention 已经被用在各种任务上,包括阅读理解,抽象式摘要,文本蕴含(textual entailment),学习独立于任务的句子表征。

端到端的记忆网络是基于一个循环的注意力机制,而不是按序列对齐(sequence-aligned)的序列循环,并且在简单语言问答和语言建模任务上表现的不错。

然而,据我们所知,Transformer是第一个完全依赖self-attention来计算输入和输出表征的转换模型,它没有使用序列对齐(sequence-aligned)的RNN或者卷积。下面的章节我们将对Transformer进行阐述,进一步讨论self-attention的优势。

3 模型架构

大多数有竞争力的神经序列转换模型都有一个encoder-decoder结构。这里,编码器将一个用符号(一般是向量)表示的输入序列(x1,...,xn)映射到一个连续的表征序列z=(z1,...,zn)。解码器拿到z后,生成一个符号表示的输出序列(y1,...,yn),这里是每个时间步生成一个yi,i表示从1到n任意一个数字。每一步,模型都自动消费前一步生成的符号,比如生成y2的时候会以y1作为额外的输入。

Transformer使用堆叠的self-attention层和明确的指向性来遵循上面这个架构,图1的左半部分和右半部分分别展出了编码器和解码器的完整连接。

3.1 堆叠的编码器和解码器

编码器: 编码器由6个相同的层堆叠而成。每一层包含2个子层。第一个子层是multi-head self-attention 机制,第二个子层是一个简单的,位置分明的全连接前馈网络。我们在每个子层都使用了一个残差连接(residual connection)【注解3】,并跟上一个归一化层(normalization layer)。也就是说,每个子层的输出是LayerNorm(x + Sublayer(x)),其中的Sublayer(x)表示各子层自己实现的函数,比如self-attention层有自己的一套实现,而feed-forward层也有自己的实现。为了方便使用这些残差链接,所有子层包括词嵌入层的输出维数都为512。这里因为残差连接会用到矩阵加法,所以要保持维数统一,至于为什么是512,估计是应为选择了维数是512的词嵌入向量。具体参考下图:

解码器: 解码器也是由6个相同的层堆叠而成。每一层除了和编码器那样有两个子层外,解码器插入了第三个子层,用于在编码器最后的输出上执行multi-head attention。和编码器一样,我们也在解码器的各子层中引入了残差连接,并跟上一个归一化层。我们还修改了解码器的self-attention子层,来防止其将注意力扩散到当前处理位置的后续的位置上。笔者理解这里的意思是,编码器的self-attention子层的注意力机制是关联到当前处理词和其他词的,因为输入的序列的所有词都是明确的,而解码器的self-attention子层只关联到当前处理词之前的词,因为当前处理词还没预测出来,之后的词当然更还没预测出来。所以解码器的self-attention子层的当前处理位置的后续位置都是用-inf来标识的,又称之为mask。这里放上论文中本段落最后的原文:This masking, combined with fact that the output embeddings are offset by one position, ensures that the predictions for position i can depend only on the known outputs at positions less than i.这样应该比较好理解了。

3.2 注意力(Attention)

注意力函数可以描述为将一个查询(query)和一组键值对(key-value)映射到一个输出(output),这里的query,keys,values和output都是向量。output是通过values的加权求和来计算的,这里的权重是通过一个query和对应的key的兼容函数来计算的。

3.2.1 Scaled Dot-Product Attention

我们称我们特殊的attention为“Scaled Dot-Product Attention”(下图左)。 其输入由dk维数的queries和keys以及dv维数的values构成。 我们计算query和所有keys的点积,然后除以dk的平方根,然后通过一个softmax函数,其输出就是values的权重。

实际上,我们是在一组queries上同时计算注意力(attention),具体是将queries打包到一个矩阵Q中。keys和values也是分别打包到K和V矩阵中。我们进行矩阵计算的输出公式如下:

两个最常用的attention 函数是additive attention和dot-product(multiplicative)attention。Dot-product attention和我们的算法一样,除了我们的算法多了一个缩放因子1/(dk的平方根)。Additive attention计算使用一个feed-forward 网络,该网络仅有一个隐藏层。两个算法在理论上具有相同的复杂度,然而,实践中,dot-product attention更快并且更省空间,因为它可以利用到高度优化的矩阵乘法代码。

虽然在dk不大的时候,这两个算法的执行是效率是相似的,但是对于较大的dk值,additive attention 优于不带缩放的dot-product attention算法。我们猜想dk越大,点积的量级也会增长【注解4】,这会将softmax函数值推向非常小的梯度所在的区域,为了弥补这点,我们才引入缩放因子1/(dk的平方根),将其与点积相乘【注解5】。

3.2.2 Multi-Head Attention

我们发现,相比使用keys,values和queries执行一个单一的注意力函数,线性投影h次不同的keys,values和queries,分别学习到dk,dk,dv维数上的线性投影会更有优势。(原句:Instead of performing a single attention function with dmodel-dimensional keys, values and queries, we found it beneficial to linearly project the queries, keys and values h times with different, learned linear projections to dk, dk and dv dimensions, respectively。) 每一个queries,keys,values的投影版本上,我们并行的执行注意力函数,然后各自得到一个dv维数的输出值。然后将这些输出值(其实就是h个矩阵)拼接(concatenated)起来,在做一次投影【注释6】,得到最后的结果,就像图2的右半部分展示的那样。

Multi-head attention让模型可以连带注意到不同位置上的来自不同表征子空间的信息。用一个attention head,会抑制这种能力。 (原句:Multi-head attention allows the model to jointly attend to information from different representation subspaces at different positions.With a single attention head, averaging inhibits this.)

这里介绍了公式中矩阵W的含义和形状。笔者的理解是所有出现的W都是一种投影矩阵。

此处,我们采用h=8个并行attention层,或称为头。对于每一层我们使用dk=dv=dmodel/h = 64。这里dmodel是指词嵌入向量的维数,可以推出其值为64* 8=512。由于每个头减少了维数,总计算成本和用一个采用完整维数的attention头是差不多的。

3.2.3 Attention在我们的模型中的应用

Transformer 以三种不同的方式使用multi-head attention :

  • 在“encoder-decoder attention”层,queries来自前一个decoder层,keys和values来自encoder的输出。这使得decoder的每个位置能够考虑到输入序列的所有位置。这模拟了sequence-to-sequence模型中采用的经典的encoder-decoder注意力机制。
  • encoder包含self-attention层。在一个self-attention层,所有的keys,values和queries来自相同的地方,这里是来自encoder的前一层的输出。当前encoder层的每个位置都可以关注到前一层encoder的所有位置。
  • 类似的,decoder中的self-attention层允许decoder层每个位置关注到decoder层的所有位置,包括当前位置。为了保证自回归性(auto-regressive property)【注解 8】,我们需要阻止解码器中向左的信息流动。我们在点积注意力算法内部实现了这一点,具体是通过屏蔽(set to -∞)softmax层的输入中的所有符合非法连接的值来实现的,见图2左。(笔者的理解就是将当前decoder中self-attention层当前处理词的后面的位置设置为负无穷大)。

3.3 Position-wise Feed-Forward Networks 位置前馈网络

除了attention子层外,每个编码器和解码器层还包含一个全连接前馈网络,该网络以相同的状态分别应用于每个位置。该网络由两个线性变换构成,在这两个变换中间有一个ReLU激活。公式表达如下:

虽然不同的位置做的是一样的线性变换,但是不同的层使用了不同的参数。另一个描述这个的方法是就像使用了size为1的卷积核做了2次卷积。该网络的输入和输出的维数都是512,内部层的维数dff = 2048。(这里作者没有详细解释,所以笔者也不太确定,貌似是说这里利用1* 1的卷积核做了一次升维和一次降维。) 附上原句:

3.4 Embeddings and Softmax

和其他的序列转换模型相似,我们使用经过学习的词嵌入模型来将输入词和输出词转换成dmodel维数的向量。我们也使用经过学习的线性变换和softmax函数来转换decoder输出为预测的下一个词的概率。在我们的模型中,我们在2个embedding层和softmax前的线性变换层共享相同的权重矩阵 。在embedding层,我们会将权重乘以dmodel的平方根。

3.5 Positional Encoding 位置编码

既然我们的模型没有包含循环(recurrence)和卷积(convolution),为了让模型确定序列的顺序,我们必须给模型注入序列中各个词的相对或绝对的位置信息。为此,我们将encoder和decoder栈的底层的embeddings分别与一个“positional encodings”做加法 。positional encodings和embeddings具有相同的维数,以便执行相加操作。有许多做positional encodings的方法,包括经过学习的方式和固定的方式。

此处,我们使用不同频率的sine和cosine函数:

这里pos是词在句子中的位置,比如句子长度是L,则pos=0,1,2,3,...,L-1。 i是positional encoding向量的某一维度,positional encoding向量的维数=dmodel,所以当dmodel维数=512时,i=0,1,...,255。 也就是说,每个positional encoding的维度对应一个正弦曲线(具体说是每个偶数维对应一个正弦曲线,每个奇数维对应一个余弦曲线)。 每个维度对应的曲线的波长的取值范围可以是一个从2Π到10000* 2Π的等比数列。 我们选择这个函数,是因为我们猜测,既然对任意固定的偏移量k,PEpos+k都能用PEpos的线性函数来表示,那么这可以让模型更容易通过相对位置来学习注意力。

注:要理解上面这句话需先回顾一下三角函数的"和角"公式: 这里,可以把α看作pos位置,把β看作k位置,则α+β可以看成是位置pos+k,由于PE(pos,2i)和PE(pos,2i+1)公式分别是用的sin和cos,所以PE公式也满足这个和角公式。则可以得到如下推导: 由此公式可以看出,对任意固定的偏移量k,PEpos+k确实都能用PEpos的线性函数来表示。 至于为什么这样可以表示相对位置信息,如果把上面的公式看成当计算pos和pos+k的位置编码维度(2i)时,公式表示(2i)和(2i+1)的线性加权求和;当计算pos和pos+k的位置编码(2i+1)时,公式表示(2i+1)和(2i)的线性加权求和,也就是说位置编码就是(2i)与(2i+1)的线性变换。所以可以表示相对位置信息就比较好理解了。

另外,作者也实验了使用经过学习的位置嵌入来代替上面的方案,然后发现这两个方案产生了几乎相同的结果。作者选择正弦曲线方案是因为即使序列的长度比训练期间的任何序列的长度长,模型也能够支持对该序列的推测(extrapolate)。

可以在下面的函数中查看生成positional encoding的代码: get_timing_signal_1d

更贴合论文公式的代码实现如下:

4 为什么使用Self-Attention

本节我们从各个方面比较self-attention和recurrent、convolutional层,recurrent和convolutional层通常用来做不定长度的符号表征序列 (x1, ..., xn)到另一个相同长度的序列( (z1, ..., zn))的映射,诸如一个典型的序列转换编码器或解码器中的隐藏层。让我们更想选择self-attention的原因有三个。

第一个是每层总的计算复杂度。第二个是可以并行计算的数量,通过需要的序列操作的最小次数来度量。 第三个是网络中远距离依存的路径长度。在许多序列转换任务中,远距离依存的学习都是一个关键挑战。影响这种能力的关键因素是前向和反向信号在网络中需要经过的的路径长度。输入和输出序列中,任意位置的组合间的路径越短,越容易学习到远距离依存关系。因此我们也比较了不同类型的层的任意两个输入和输出中的位置的最大路径长度。如下图:

图中所示,self-attention层用一个恒定的循序执行操作的次数来连接所有的位置,而recurrent层需要O(n)复杂度的循序操作。从计算复杂度来看,当序列的长度n比表征维数d小的时候,self-attention层比recurrent层更快,这种情况在最好的机器翻译模型使用的表征例子中是常见的,比如word-piece和byte-pair表征。为了改善涉及很长序列任务的计算性能,可以限制self-attention只考虑输入序列中以各自的输出位置为中心的一个大小为r的邻域。(笔者注:应该是相对默认的self-attention机制会考虑所有的输入的位置来说的)这会增加最大路径长度为O(n/r)。我们计划在将来的工作中进一步研究这种方法。

一个单一的卷积层,使用k<n大小的卷积核,不能连接所有的输入和输出位置对。... 这段主要是讲采用卷积层的代价比recurrent和self-attention层都大,具体细节可以自行参考原文,由于笔者未能全部理解,就不翻译了。

self-attention有附加的优势,就是模型的可解释性更强。我们从模型中观察注意力分布,并在附录中呈现和讨论了一个示例。单个注意力头不仅清晰的学会了执行不同的任务,还呈现出许多和句子的语义结构、句法有关的行为。

5 Training 训练

本节描述模型的训练机制。

5.1 Training Data and Batching

我们在标准的WMT 2014 English-German数据集上训练,其包含450w句子对。句子用包含37000个词的原目标词汇表的byte-pair encoding来编码。对于English-French,我们使用大的多的WMT 2014 English-French数据集,其由3600万个句子组成,并将单词分割成32000个不同单词组成的词汇表。句子对按照相近序列长度进行批次划分。每个训练批次包含一组含有接近25000原始单词(source tokens)和25000目标单词(target tokens)的句子对。

5.2 Hardware and Schedule

我们在8块NVIDIA P100 GPU上训练我们的模型。我们的基础模型使用了本论文描述的超参数,每个训练步耗时0.4秒。我们训练基础模型用了总共100000步,花费12小时。对于我们的大型模型,(table3的最后一行有描述),每步耗时1秒。大型模型训练了300000步,耗时3.5天。

5.3 Optimizer 优化器

我们使用Adam优化器,采用β1 = 0.9, β2 = 0.98 and epsilon= 10−9 。我们根据如下公式随着训练过程而改变学习率: 这里,我们在首个warmup_step训练步线性增加学习率,然后按照step_num平方根的倒数成比例降低学习率。我们设置warmup_steps=4000。

5.4 Regularization 正则化

我们在训练期间采用了三种正则化方法。

Residual Dropout 我们在每个子层的输出加入下一个子层的输入和归一化之前上应用了dropout。 (原句:We apply dropout [33] to the output of each sub-layer, before it is added to the sub-layer input and normalized.) 另外,我们在encoder和decoder栈的embeddings和positional encodings相加后,应用了dropout。对于基础模型,我们使用的比率Pdrop = 0.1。

Label Smoothing 在训练期间,我们采用label smoothing,值如下: 这使得模型学到了更多的不确定因素,但是改善了准确度和BLEU得分。

6 Results

6.1 Machine Translation 机器翻译

在 WMT 2014 English-German 翻译任务上,大型transformer模型(Transformer(big) in Table 2) 胜过之前最好的模型(包括 ensembles)2.0个BLEU,创造了新的BLEU分数记录——28.4。这个模型的配置在Table3的末行有展示。训练在8块P100GPU上耗时3.5天。甚至我们的基础模型也优于所有先前发布的模型和集成(ensembles),并且训练成本比其他任何模型的成本都低。

在 WMT 2014 English-to-French 翻译任务上,我们的大型模型达到了41.0的BLEU分数,胜过所有发布的单个模型,并且只使用了最好模型的1/4的训练成本。Transformer(big) 在训练English-to-French的时候使用了Pdrop = 0.1的dropout rate(失活率),而不是0.3。

下面这段,笔者也有不明白的地方,笔者会尝试解释,但是未必准确,所以放出原句: For the base models, we used a single model obtained by averaging the last 5 checkpoints, which were written at 10-minute intervals. For the big models, we averaged the last 20 checkpoints. We used beam search with a beam size of 4 and length penalty α = 0.6 [38]. These hyperparameters were chosen after experimentation on the development set. We set the maximum output length during inference to input length + 50, but terminate early when possible [38].

对于基础模型,我们使用一个单一的从最新的5个训练检查点平均求出的模型,这些检查点的写入间隔是10分钟。对于大型models,我们用的是最新的20个检查点。我们使用beam search算法,beam的大小=4,长度的惩罚系数α = 0.6 。这些超参数是在开发集上实验之后得出的。我们设置推理过程中的最大的输出长度为输入长度+50,但是会在可以终止的时候尽早终止。(笔者注:不明白为什么这么做。)

Table 2 中比较了我们的模型和其他模型架构的表现,包括翻译质量和训练成本。我们通过乘以训练时间,GPU的使用数量,以及对各GPU持续单精度浮点容量的估计(我们对K80, K40, M40 and P100型号的GPU分别使用 2.8, 3.7, 6.0 和 9.5 TFLOPS , respectively),来评估用于训练模型的浮点运算的数量。

6.2 Model Variations

为了评估Transformer不同部分的重要性,我们将基础模型进行不同方式的变化,以此度量在开发集和测试集上模型表现的改变。我们使用beam search算法(和上节提到的一样,但是没有对检查点取平均)。我们在Table 3中呈现了这些。

在Table 3的A行,我们改变attention heads的数量,以及attention key和value的维数,以此保持总计算量的不变,就像3.2.2小节中描述的那样。虽然单头注意力比最佳设置(8个头)差0.9个BLEU,但过多的头也会降低质量。

在Table 3的B行,我们观察到,较小k的维数,会降低模型的表现。这暗示着确定兼容性并不容易,而且一个比点积更复杂的兼容性函数可能是有益的。我们进一步观察C行和D行,如预料的那样,大型模型更好,dropout对避免过拟合非常有用。在E行,我们用经过学习的位置嵌入方式来代替正弦曲线位置编码的方式,对于基础模型来说效果几乎是一样的。

6.3 English Constituency Parsing 英语成分解析

为了评估Transformer是否可以泛化到其他任务上,我们在English constituency parsing上做了实验。此任务有着特别的挑战:输出受强结构约束,并且比输入长的多。此外,基于RNN的sequence-to-sequence的模型还没有在小数据集上达到过最先进的结果。

我们在Wall Street Journal (WSJ) portion of the Penn Treebank数据集上训练了一个4层的transformer,维数dmodel =1024,大概有40K个训练句子。我们还在半监督的环境中对其进行了训练,使用了更大的高置信度和BerkleyParser语料库,语料库中有大约1700万句话。我们在WSJ only 设置中使用了包含16K个唯一单词的词汇表,在半监督设置中使用了32K个唯一单词的词汇表。

我们只用了少量的实验来选择droput,不论是attention、residual、学习率、beam size 都是如此,所有其他剩余的参数和English-to-German的基础翻译模型的一样。在推理阶段,我们增加了最大输出长度为输入的长度+300。对于WSj only 和半监督设置,我们使用beam size=21,α = 0.3。

Table 4 显示,尽管我们的模型缺少特定任务的调优,其仍然执行的非常好,除了Recurrent Neural Network Grammar( Dyer等人提出)以外,比其他模型都好。

与RNN序列到序列模型相比,即使只在 WSJ 的40K句训练集上进行训练,Transformer的性能也优于BerkeleyParser[29]。

7 总结

在本次工作中,我们展示了Transformer,首个完全依赖注意力机制的序列转化模型,用multi-headed self-attention替换了encoder-decoder架构中常用的recurrent层。

在翻译任务中,Transformer 的训练比基于recurrent或convolutional层的架构的模型都要快的多。在WMT 2014 English-to-German 和 WMT 2014 English-to-French 翻译任务上,我们创造了新的记录。在前一个任务中,我们的最佳模型甚至优于所有先前报告的模型的集成。

我们对基于注意力的模型的未来感到兴奋,并计划将其应用于其他任务。我们计划将Transformer扩展到涉及文本以外的输入和输出模式的问题上,并研究局部的、受限的注意机制,以便有效地处理大量输入和输出,如图像、音频和视频。Making generation less sequential is another research goals of ours。(注:这句没翻译,是因为不知道“Making generation less sequential ”具体是指什么。)

我们用于训练和评估我们模型的代码可通过这个地址获取: https://github.com/ tensorflow/tensor2tensor

致谢 我们感谢Nal Kalchbrenner和Stephan Gouws富有成效的评论、纠正和启发。

参考文献

请从原论文末尾查找。

Attention Visualizations 注意力可视化

图3:可以看到,在编码making的时候,注意力的关注情况。上面的图只将making的注意力展示出来了。颜色越深的头注意力越集中。

图4:Top: head 5的完整注意力。Bottom: 仅是从head 5 和head 6中剥离出来的对单词‘its’的注意力。

图5:许多注意力头表现出的行为看起来都和句子的结构有些关系。我们给出了2个例子,来自编码器中不同的注意力头。注意力头显然学会了执行不同的任务。

注解

  1. BLEU:全称 bilingual evaluation understudy。是一种使用机器代替人工评估翻译结果好坏的方法。评估思路是将模型翻译的結果和一组人工翻译的结果进行比较得出一个综合分数,分数越高的模型越好。

  2. ht: 第t个时间步的激活值,如果不理解,请先了解神经网络结构中的激活函数。

  3. residual connection: 残差连接.引入残差连接,一般是为了避免梯度爆炸和弥散问题,这里估计也是为了解决这个问题。

  4. 为什么维数越大,点积越大?看下面的公式,其中dk是维数,q·k是点积 : 根据图中的公式,直觉上觉得dk越大q·k就越大是显然的,然而,论文中作者对此的解释提到了均值和方差,这里笔者还没能弄明白为什么要通过均值和方差来说明点积会随着维数的增加而增加。 原句如下:

  5. 要理解“我们猜想dk越大,点积的量级也会增长,这会将softmax函数值推向非常小的梯度所在的区域,为了弥补这点,我们才引入缩放因子1/(dk的平方根),将其与点积相乘”这句话,需要看下面三个图: x轴显示的是输入的向量中的各个分量,y轴表示输入的向量中的各个分量对应的softmax的输出。 笔者将第一幅图的输入向量的各个分量设置为从0到19,步长为1,则输入维数为20,;第二幅图的输入向量的各个分量增大到从0到59,步长为3,则输入维数同样是20。对比两幅图,明显第二幅图中有更多的梯度非常小的区域。而在深度学习神经网络中,我们知道非常小的梯度将导致非常慢的学习速度。所以作者引入了一个缩放因子,那么第三幅图就是笔者将第二幅图的输入除以其维数的平方根后的图,可以看到落在非常小的梯度的区域的值变少了。 绘制曲线的代码如下,大家可以自行调整参数以做测试:

import matplotlib.pyplot as plt
import numpy as np

def softmax(inputs):
    return np.exp(inputs) / float(sum(np.exp(inputs)))

def line_graph(x, y, x_title, y_title):
    plt.plot(x, y, markerfacecolor='blue',marker='o')
    plt.xlabel(x_title)
    plt.ylabel(y_title)
    plt.show()

# graph_x = range(0, 20) #数值小的时候
graph_x = range(0, 60,3) # 维数相同,数值大的时候
print(len(graph_x))
graph_x = np.array(graph_x)/(float(len(graph_x)) ** 0.5) # 加入缩放因子
graph_y = softmax(graph_x)
print("GraphXreadings: {}".format(graph_x))
print("GraphYreadings: {}".format(graph_y))
line_graph(graph_x, graph_y, "Inputs", "SoftmaxScores")

  1. projected: 投影。具体的操作是用当前矩阵乘以另一个矩阵,另一个矩阵通常就是一个权重矩阵,其中的值一开始是随机初始化的,然后通过不断的学习得到合适的值。

  2. Auto-regressive : 简称AR,核心思想是: 下一个观测值约等于前n个观测值的某种线性加权和。所以作者需要将decoder中上一个预测词的左向信息流给 mask 掉(即右侧所有位置的值设置为负无穷)。

笔者总结

ok,终于翻译完成了。让我们来回顾一下论文作者的思路以做个总结。 本论文中,作者提出了Transformer模型架构,该架构用在序列到序列的转换领域,比如机器翻译,可以是语言到语言的翻译,也可以是任何序列到另一个序列的转换。

Transformer中用到了一种注意力机制,直观上理解就是在编码句子中的某个词的时候,会同时注意句子中的"其他词","其他词"中各个词越和当前词相关,得到的注意力越多。

Transformer利用这种注意力机制来给相关词打分,来得到最终的输出,然后通过训练样本集和相应的损失函数不断更新网络的权重系数来得到一个有效的序列到序列转换的模型。 也就是说,训练好的模型会知道如何将一个句子序列映射到另一个句子序列,比如英文到中文的翻译。

在这个过程中,作者提出了query,key,value的概念,注意力分数就是用这三个概念参与计算出来的,其中还用到了query和key的点积。而这三个概念作者只用了一段话描述:”注意力函数可以描述为将一个查询(query)和一组键值对(key-value)映射到一个输出(output),这里的query,keys,values和output都是向量。output是通过values的加权求和来计算的,这里的权重是通过一个query和对应的key的兼容函数来计算的。“。 笔者的尝试直观的解释一下(不一定准确,仅作参考,请大佬指正。),就是作者把 query当作当前词的词嵌入向量在某个注意力空间的投影; key 当作句子中所有词在注意力空间上的键投影; value当作句子中所有词在注意力空间上的值投影。 而编码器中query和key做点积,就是为了找到注意力空间中其他词和当前编码词的注意力相关性,这些相关性将作为value的权重,也就是其他词对当前编码词的注意力集中度。 解码器中的query和编码器的key做点积,是为了在计算注意力的时候再加入对已经解码的词的考量。 为了让模型在注意力上考虑的更全面,作者使用了8个注意力头,也就是计算了8次上面涉及q,k,v的过程,然后将结果拼接在一起。 但是这个过程并没有考虑到句子中词和词之间的位置关系,所以为了弥补,作者引入了positional encoding,就是要让Transormer能够考虑到位置信息。不至于打乱一个句子的词汇后,得到的转换结果和没打乱一样。

相比基于注意力机制的循环或卷积的架构模型,Transformer的显著特点是其完全依赖注意力机制,而摒弃了循环和卷积。由此得到的好处包括:计算复杂度降低了,并行计算的数量增加了,句子中任意两个词离得越远,越不容易学习其依存关系的问题被减轻了。

如果你还是隐隐觉得不能完全搞懂论文的所有思想也不要紧,因为论文本身确实比较难读懂,毕竟是论文,不是教学为目的。但是至少通过本文,你应该大致明白了论文在讨论什么,其提出的attention机制是为了解决什么问题。

ok,本篇就这么多内容啦~,感谢阅读O(∩_∩)O,88~

posted @ 2019-09-23 16:03  程序员一一涤生  阅读(...)  评论(...编辑  收藏