Transformer:隐藏的机器翻译高手,效果赶超经典 LSTM!


雷锋网 AI 科技评论按:在自然语言处理任务中,循环神经网络是一种常见的方法,但近来,一种只依赖于注意力机制的特定神经网络模型已被证明它对于常见的自然语言处理任务的效果甚至优于循环神经网络模型,这个模型被称为变换器(Transformer)。同时,数据科学家 Maxime Allard 发表了相应的文章对变换器的原理机制作了介绍与讲解,并用相应的实验帮助大家更好的理解这种神经网络模型,雷锋网 AI 科技评论将其编译如下。

第 1 部分:序列到序列学习和注意力机制

论文《Attention Is All You Need》(https://arxiv.org/abs/1706.03762  )描述了变换器以及序列到序列学习的架构。序列到序列(Seq2Seq)是一种神经网络,它将给定的元素序列(例如句子中的单词序列)转换为另一个序列。

Seq2Seq 模型很适用于翻译,它可以将一种语言的单词序列转换为另一种语言中的单词序列。通常 Seq2Seq 模型是基于长短期记忆(LSTM)而建立,LSTM 模块通过序列的相关数据,可以赋予序列意义,同时记住(或忘记)它判定为重要(或不重要)的部分。正因为句子依赖于序列,单词的顺序对于理解句子至关重要,所以 LSTM 是处理此类数据的不二选择。

Seq2Seq 模型由编码器和解码器组成。编码器获取输入序列并将其映射到更高维空间(n 维向量)。该抽象矢量被送入解码器,再由解码器将其转换为输出序列。输出序列可以是另一种语言、符号、输入的副本等。

我们可以将编码器和解码器理解为只会两种语言的人工翻译者。他们的第一语言是母语,但两者的母语是不同的,比如一个是德语,另一个是法语;而他们的第二语言则是他们共有的一种虚构语言。为了将德语翻译成法语,编码器将德语句子转换为它所掌握的另一种语言,我们在这里称为「虚构语言」。同时,由于解码器能够读取该虚构语言,因此它现在可以把这个语言翻译成法语。于是,这个模型(由编码器和解码器组成)就可以合力将德语翻译成法语。

假设一开始,编码器或解码器对于虚构语言都不是非常流利,为了很好的掌握它,我们将使用很多例子对它们(模型)进行训练。对于 Seq2Seq 模型的编码器和解码器,一般情况下,其基础配置各带一个 LSTM 模块。那么变换器在什么时候发挥作用呢?

我们需要一个技术细节来让变换器更容易理解,即注意力机制。注意力机制通过查看输入序列,然后在每个步骤确定序列中某一部分是否重要。这看似抽象,但举个例子就很好理解了:在阅读本文时,你会总是把注意力集中在你阅读的单词上,但同时你的脑海仍然保留了一些重要关键词,以便联系上下文。

所以,注意机制对于给定序列的工作方式与我们的阅读方式类似。对于上文提到的拟人编码器和解码器的,我们可以想象为,编码器不仅用虚构语言写下句子的翻译,而且还写了对句子语义理解很重要的关键词,并将这些关键词以及常规翻译都提供给解码器。通过这些关键词,以及一些关键术语所给到的句子上下文,解码器就可以识别出句子的重要部分,因此这些新的关键字就能够帮助解码器更容易的进行翻译。

换而言之,对于 LSTM(编码器)读取的每个输入,注意力机制会同时考虑其他几个输入,并通过对这些输入赋予不同的权重来决定哪些输入是重要的。然后,解码器将编码的句子和注意力机制提供的权重作为输入。

要了解更多有关的注意力,可以参考这篇文章(https://skymind.ai/wiki/attention-mechanism-memory-network  )。如果想了解更科学的方法,并且阅读关于基于不同注意力机制的序列到序列模型方法,可以参考这篇《基于注意力的神经机器翻译的有效方法》的论文(https://nlp.stanford.edu/pubs/emnlp15_attn.pdf  )。

第 2 部分:变换器

《Attention Is All You Need》一文中引入了一种名为变换器的新型架构,正如标题所示,其中使用到了上文提到的注意力机制。

与 LSTM 一样,变换器是一种在两个部分(编码器和解码器)的帮助下将一个序列转换为另一个序列的架构,但它与先前描述的「现有序列到序列模型」不同,因为它不包含任何循环神经网络(Recurrent Networks),如 GRU,LSTM 等。

到目前为止,循环神经网络是捕获序列及时依赖性的最佳方法之一。然而,提交这篇论文的团队证明,一个只有注意力机制而没有任何循环神经网络的架构能够对翻译任务和其他任务的结果进行优化。其中,在自然语言任务方面的一个改进是由引入 Bert 的团队提出的:《BERT:用于语言理解的深度双向变换器的预训练》(https://arxiv.org/abs/1810.04805  )。

那么,变换器究竟是什么?我们将从下面这张图片开始讲解。

图 1:变换器模型架构,来自 Vaswani 等人的《Attention Is All You Need》

编码器位于左侧,解码器位于右侧,编码器和解码器都由可以多次堆叠在一起的模块组成,这展示在图中的 Nx 部分。

我们看到模块主要由多头注意力机制(Multi-Head Attention)和前馈层组成。因为不能直接使用字符串,所以我们首先将输入和输出(目标句子)嵌入到 n 维空间中。模型中有一个很小但非常重要的部分,即对不同单词的位置编码。这是由于我们没有可以存储序列如何被输入模型的循环网络,而序列由其元素顺序决定,所以我们需要以某种方式给出序列中每个单词/部分的相对位置。这些位置被添加到每个单词的嵌入表示(n 维向量)中。

让我们仔细看看模型中的这些多头注意力机制模块:

图 2:左图为点积注意力机制,右图为包含多个注意力层的并行多头注意力机制,来自 Vaswani 等人的《Attention Is All You Need》

我们从注意力机制的左侧描述开始,它不是很复杂,可以用下面的等式来描述:

其中,Q 是一个包含查询(query,即序列中一个单词的向量表示)的矩阵;K 是所有键(key,序列中所有单词的向量表示);V 是值(value,包含所有序列中单词的向量表示)。在编码器和解码器的多头注意力机制模块中,V 与 Q 具有相同的单词序列。但对于反馈给编码器和解码器序列的注意力机制模块,V 与 Q 具有不同的单词序列。

为了简化这个公式,我们可以将其表述为 V 与注意力权重 a 的乘积,其中的权重 a 由下式定义:

这意味着权重 a 由序列中的每个单词(由 Q 表示)如何受序列中所有其他单词(由 K 表示)的影响来定义。另外,SoftMax 函数能使权重 a 分布在 0 和 1 之间;然后我们再将这些权重应用于 V 中引入的所有单词序列(在编码器和解码器中,V 与 Q 相同;但在编码器和解码器的输入模块之间,V 与 Q 则不同)。

右图描述了如何将这种注意力机制转化为多个可以并行使用的机制。通过 Q、K 和 V 的线性投影多次重复注意力机制,这使得系统可以从 Q、K 和 V 的不同表示中学习,这对模型是有益的。这些线性表示则通过将 Q、K 和 V 乘以在训练期间所学的加权矩阵 W 来实现。

矩阵 Q、K 和 V 对于注意力机制模块结构中的每个位置是不同的,这取决于它们是在编码器、解码器中,还是在编码器和解码器之间。这是因为注意力机制要参与整个编码器输入序列或解码器输入序列的一部分,连接编码器和解码器的多头注意力模块将确保编码器输入序列与解码器输入序列的给定位置都被同时考虑在其中。

在编码器和解码器中的多头注意力机制后,我们连接了一个点态前馈层。这个小的前馈网络对于序列的每个位置都具有相同的参数,即对来自给定序列的每个元素进行了单独的、相同的线性变换。

训练

如何训练这样的「野兽」模型呢?Seq2Seq 模型的训练和推断与平时的分类问题略有不同,转换器也是如此。

我们知道,为了训练翻译任务的模型,我们需要两种不同语言的句子进行双向翻译。一旦我们有大量的句子对,就可以对模型进行训练。假设我们想将法语翻译成德语,我们的编码输入是法语句子,而解码器的输入将是德语句子。但是,在这里解码器输入将向右移动一个位置。

其中一个原因是我们不希望这个模型在训练期间去单纯的学习对解码器输入的复制,而是希望模型在给定编码器序列和特定的解码器序列的情况下,对下一个字或者字符进行预测。

如果我们不移位解码器序列,则模型将会学习简单地「复制」解码器输入,因为位置 i 的目标字(字符)将是解码器输入中对应位置 i 的字(字符)。因此,通过将解码器输入移位一个位置,我们的模型则需要通过解码器序列中已知位置 1,...,i-1 的字(字符)来预测位置 i 的目标字(字符)。这可以防止我们的模型学习复制、粘贴的任务。我们将句子开始的标记填充进解码器输入的第一个位置,否则由于右移该位置将是空的。类似地,我们将一个句子结尾标记附加到解码器输入序列来标记该序列的结束,并且这个标记也将附加到目标输出句子中。在后文中,我们将看到这种方法对于推断结果有何用处。

对于 Seq2Seq 模型和变换器,我们都做相同的处理。除了右移之外,变换器还将在第一个多头注意力模块的输入端加入一个掩码,以避免泄露潜在的「未来」序列元素。这是变换器架构中特有的,因为这里面没有循环神经网络可以用来事模型按照顺序输入序列。如果没有掩码,当我们将所有内容一起输入时,多头注意力机制需要检测整个解码器中每一个输入序列的位置。

将正确的移位输入馈送到解码器的过程也称为教师强制(Teacher-Forcing),详情可参考该博客内容(https://machinelearningmastery.com/teacher-forcing-for-recurrent-neural-networks/  )。

我们想要进行损失计算的目标序列是有一个带有序列结束标记的解码器输入(德语句子),而非移位后的句子。

推理

这些模型的推理和训练不同,并且非常具有意义,因为我们希望模型在最终实现没有对应德语句子的情况下翻译法语句子。这里的诀窍是为输出序列的每个位置重新输入我们的模型,直到检测到句末的标记为止。

具体步骤是:

  • 输入完整的编码器序列(法语句子),并作为解码器输入;然后我们在第一个位置上加入一个空序列,这个空序列只有一个句子开头标记。这将输出一个序列,其中我们只需要第一个元素。

  • 该元素将被填充到我们的解码器输入序列的第二个位置,该序列现在具有句子的开头标记和其中的第一个字(字符)。

  • 将编码器序列和新的解码器序列输入到模型中,取输出的第二个元素并将其放入解码器输入序列。

  • 重复此操作,直到预测到句末的标记,这标志着翻译结束。

我们看到,这个方法需要通过多次运行模型来翻译该句子。

第 3 部分:用于时间序列预测的变换器

我们已经看到了变换器的架构,并且从论文《Attention Is All You Need》

及它的作者那里知道该模型在语言任务中表现非常出色,现在我们在一个实例中来测试变换器的效果。

这里我们不用翻译任务,而是使用德克萨斯州电力可靠性委员会(ERCOT)提供的德克萨斯州每小时电力流量的时间序列预测。每小时的数据可以在此获得(http://www.ercot.com/gridinfo/load/load_hist/  )。如果你想深入了解架构,harvardnlp(http://nlp.seas.harvard.edu/2018/04/03/attention.html  )提供了对变换器及其实现的详细解释。

既然我们可以使用基于 LSTM 的序列到序列模型来进行多步预测,那么让我们来看看变换器做预测的能力。这里因为我们使用的不是单词序列而是数值,所以我们首先需要对架构进行一些更改;此外我们进行的是自动回归实验,而不是单词/字符的分类。

数据

现有数据为我们提供了整个 ERCOT 控制区域的每小时负载。我使用了 2003 年至 2015 年的数据作为训练集,2016 年作为测试集。因为只有负载值和负载的时间戳,所以我将时间戳扩展出了其它特性。从时间戳中,我提取了它对应的工作日并对其进行了一次热编码;另外,我使用年份(2003 年,2004 年,...,2015 年)和相应的小时(1,2,3,...,24)作为值本身(value),这为每天的每小时提供了 11 项特性值。出于收敛目的,我还将 ERCOT 负载除以 1000 进行了标准化操作。

为了预测给定的序列,我们需要一个过去的序列。在我们的示例中,我使用了前 24 小时的每小时数据来预测接下来的 12 小时的数据,其中我们可以根据需要调整数据属性。例如,我们可以将其更改为每日数据而不是每小时数据。

从论文中更改模型

第一步,我们需要删除嵌入。因为我们的输入中已经有 11 个数值,而嵌入通常将给定的整数映射到 n 维空间;所以这里不使用嵌入,而是简单地使用线性变换将 11 维数据转换为 n 维空间,这类似于嵌入单词。

然后,我们需要从变换器输出中删除 SoftMax 层,因为我们的输出节点不是概率而是实际值;接着,就可以开始进行训练了。

我使用了教师强制来进行训练,这意味着编码器由 24 个数据点的集合组成作为输入,解码器输入是 12 个数据点的集合。其中第一个是「序列开始」值,后面的数据点是目标序列。在开始时引入「序列开始」值后,我将解码器输入相对于目标序列移动了一个位置。

我使用了一个只有「-1」的 11 维向量作为「序列开始」值。当然这可以改变,根据用例实际情况使用其它值是有益的;但是对于这个例子,这样的设置非常有用,因为这可以使我们在输入或输出序列的任何一个维度中都没有负值。

此示例的损失函数是均方误差(the mean squared error)。

结果

下面的两个图显示了结果。我取每天每小时值的平均值并将其与正确值进行比较。第一个图显示了前 24 小时的 12 小时预测;对于第二个图,我们预测了一小时前的 24 小时数据。我们看到该模型能够很好地捕捉到一些波动,训练集的根均方误差(the root mean squared error)为 859;对于验证集,12 小时预测根均方误差为 4,106,1 小时预测根均方误差为 2,583。模型预测的平均绝对百分比误差对应于第一个图表为 8.4%,第二个图表为 5.1%。

图 3:一年前 24 小时的 12 小时预测

图 4:一年前 24 小时的 1 小时预测

总结

结果表明,我们可以使用变换器进行时间序列预测。但在评估期间,结果显示如果我们想要预测的步骤越多,错误就越高。上面的第一张图(图 3)是通过使用 24 小时预测接下来的 12 小时来实现的。如果我们只预测一个小时,结果会好得多,正如我们在第二个图上看到的那样(图 4)。

对于变换器的参数,如解码器和编码器层的数量等,还有很大的优化空间。上述实验不是一个完美的模型,它通过更好的调整和训练,可将结果起到一定的改善作用。

使用 GPU 来加速训练可能也会有很大帮助,本次实验我并没有在我的本地机器上运行,而是在 Watson Studio Local Platform 上用 GPU 来训练了这个模型。你也可以使用 Watson 的机器学习 GPU 来加速训练。

原文链接:

https://medium.com/inside-machine-learning/what-is-a-transformer-d07dd1fbec04 

雷锋网 AI 科技评论

分享到