来源 | Natural Language Processing with PyTorch
作者 | Rao,McMahan
译者 | Liangchu
校对 | gongyouliu
编辑 | auroral-L
全文共5056字,预计阅读时间30分钟。
第八章 自然语言处理的高级序列模型
8.1 序列到序列模型,编码器-解码器模型,和条件生成
8.2 从序列中捕获更多:双向递归模型
8.3 从序列中捕获更多:注意力
8.3.1 深度神经网络中的注意力
8.4 评估序列生成模型
8.5 示例:神经机器翻译
8.5.1 机器翻译数据集
8.5.2 NMT 向量化管道
8.5.3 NMT 模型的编码和解码
8.5.3.1 注意力的详细解释
8.5.3.2 学习搜索和定时采样
8.5.4 训练例程和结果
8.6 总结
在本章中,我们基于第六章和第七章讨论的序列建模概念来拓展学习序列到序列建模(sequence-to-sequence modeling),该模型以一个序列作为输入,并产生另一个可能不同长度的序列作为输出。序列到序列的例子随处可见,例如,给定一封电子邮件,我们可能希望预测其回复;给出一个法语句子,我们可能希望预测它的英语翻译;给定一篇文章,我们可能希望得到一篇摘要。我们还会在本章中讨论序列模型的结构变体,特别是双向模型。为了最大限度地利用序列表示,我们将介绍注意力机制并对其进行深入讨论。本章最后会详细介绍神经机器翻译(neural machine translation,NMT),它实现了本文所描述的相关概念。
8.1 序列到序列模型,编码器-解码器模型,条件生成
序列到序列(Sequence-to-sequence,S2S)模型是一种称为编码器-解码器(encoder–decoder)模型的一般模型家族的一种特殊情况。编码器-解码器模型是两个模型(见下图 8-1)的组合,分别是“编码器”和“解码器”,它们通常是一起训练的。编码器模型需要输入并产生一个编码或输入的表示ϕ,通常是一个向量。编码器的目标是捕获与当前任务相关的输入的重要属性,解码器的目标是获取编码输入并产生所需的输出,由此理解,我们将S2S模型定义为编码器-解码器模型,其中编码器和解码器是序列模型,输入和输出都是长度可能不相同的序列。
查看编码器-解码器模型的一种方法是查看作为模型特例的条件生成模型(conditioned generation model),在条件生成中,影响解码器产生输出的是一般条件上下文c而不是输入表示ϕ。当条件上下文c来自编码器模型时,条件生成与编码器-解码器模型相同。并非所有的条件生成模型都是编码器-解码器模型,这是因为条件上下文可能来自结构化的源。以天气报告生成器为例:温度、湿度、风速和风向值会影响解码器产生文本天气报告。在“模型 2:有条件的SurnameGenerationModel”一节中,我们看到了一个基于国籍有条件地生成姓氏的例子。下图(8-2)展示了一些条件生成模型的实际示例:
在本章中,我们会深入学习S2S模型,并以机器翻译任务为例解释其用法。考虑一个“智能”的iOS/Android键盘,它可以在你打字时自动将文本转换成表情符号,比如,如果你输入omg the house is on fire,你可能希望键盘输入如下:
注意,输出的长度(4 个token)与输入的长度(6 个token)不同。输出和输入之间的映射称为对齐(alignment),如下图(8-3)所示:
传统上,许多S2S问题的解决方法都尝试使用工程和启发式统计方法,尽管有关这些方法的内容超出了本章乃至本书的范畴,但我们仍建议你阅读Koehn(2009)并参考statmt.org中的资源。我们在第六章学习过序列模型是如何将任意长度的序列编码成向量的,在第七章中知道了单个向量是如何使RNN有条件地生成不同姓氏的,而本章中的S2S模型正是这些概念的自然延伸。
下图(8-4)展示了编码器将整个输入“编码”为表示ϕ,它影响解码器生成正确输出。你可以使用任何RNN模型(不管是Elman RNN、LSTM还是GRU)作为编码器。在下面两节中,我们将介绍现代S2S模型的两个重要构件。我们会首先介绍双向递归模型,该模型将前向传递和后向传递一起在一个序列上组合,以创建更丰富的表示。接着,我们会在“从序列中捕获更多:注意力”一节中介绍注意力机制,该机制在关注与任务相关输入的不同部分时很有用。这两部分对于构建基于S2S模型的解决方案至关重要。
8.2 从序列中捕获更多:双向递归模型
理解递归模型的一种方法是把它看作一个将序列编码为向量的黑盒子。建模序列时,结合观察过去和未来的单词是有用的。考虑下面的句子:
The man who hunts ducks out on the weekends.
如果模型仅仅从左向右观察,那么其“duck”的表示将与从右到左观察单词的模型所得“duck”的表示不同。人类一直在做这种回溯性的更新。
综上所述,结合使用来自过去和未来的信息将能够有力地表示一个单词在一个序列中的含义,这就是双向递归模型的目标。递归家族的所有模型(如Elmann RNN、LSTM或GRU)都可用于这种双向表示。与前两章的单向模型一样,双向模型可用于分类和序列标记情境,为此,我们需要预测输入中每个单词的一个标签。
下图(8-5以及8-6)详细说明了这一点:
在上图(8-5)中,请注意模型是如何双向读入句子并产生一个句子的表示ϕ的,该表示是前向和后向表示法的组合。此处未显示的是由Linear层和softmax组成的最终分类层。
在上图(8-6)中是网络“隐藏状态”的表示或编码,此时输入为“love”一词。在“从序列中捕获更多:注意力”一节中,当我们讨论注意力时,该状态信息变得非常重要。
请注意,输入中的每个单词都有一个“前向”表示和一个“后向”表示,这两种表示法被连接起来,以生成所讨论单词的最终表示法。此处未显示的是最终的分类层,它在每个时间步由一个Linear层和一个softmax组成。
8.3 从序列中捕获更多:注意力
8.1节中所引入S2S模型公式的一个问题是:它将整个输入句子填充(“编码”)为单个向量ϕ并使用该编码生成输出,如下图(8-7)所示。虽然这可能适用于非常短的句子,但是对于长句,这样的模型无法捕获整个输入中的信息,这就是仅使用最终的隐藏状态作为编码的局限性。长输入的另一个问题是,当随反向传播时,梯度会消失,使训练变得困难。
对于那些曾经尝试翻译的双语/多语种读者来说,这种先编码后解码的过程可能有点奇怪。人类通常不会提取句子的含义,并根据含义生成翻译。对于上图(8-7)中的示例,当我们看到法语单词pour就知道对应的英语是for,当我们看到petit-déjeuner就想到了breakfast。也就是说,我们的大脑在产生输出的同时还关注输入的相关部分,这种现象叫做注意力(attention)。注意力已经在神经科学和其他相关领域得到了广泛的研究,而这正是使得我们尽管记忆有限却能取得相当大的成功的原因。注意力无处不在,其实作为读者正在阅读本书的你的注意力就在这些文字上,即便你记忆力超常,你也不会把整本书的内容作为一个字符串读入。当你阅读单词时,你会注意邻近单词,可能正是章节和小节的主题等等。
类似地,我们希望序列生成模型将注意力集中到输入的不同部分,而不仅仅是整个输入的最终摘要,这就是注意力机制(attention mechanism)。顺便说一句,Bahdanau等人(2015)提出的机器翻译模型是第一个将注意力概念纳入自然语言处理的模型,自此以后,人们又提出了几种注意力机制和提高注意力的方法。在本节中,我们将回顾一些基本的注意力机制,并介绍一些与注意力相关的术语。事实证明,注意力对于提高具有复杂输入和复杂输出的深度学习系统的性能非常有用。事实上,Bahdanau等人表明,由“BLEU score”(将在“评估序列生成模型”中介绍)衡量的机器翻译系统的性能会随着输入变长而在没有注意力机制的情况下下降,如下图(8-8)所示。添加注意力能解决这个问题。
8.3.1 深度神经网络中的注意力
注意力是一种通用机制,它可以用于本书前面讨论过的所有模型,但我们在这里用编码器-解码器模型描述它,因为该模型才是注意力机制真正发挥作用的地方。我们回想一个S2S模型,典型情况下,它在每个时间步生成一个隐藏的状态表示,特定于该时间步的编码器。要使用注意力,我们不仅要考虑编码器的最终隐藏状态,还要考虑每个中间步的隐藏状态。这些编码器隐藏状态在某种程度上是无信息的,称为值value(或在某些情况下称为键key),注意力还取决于解码器的先前隐藏状态,称为查询(query),下图(8-9)说明了对于时间步0的所有这些内容。时间步t=0的查询向量是一个固定的超参数。注意力由一个向量来表示,这个向量的维度与它所关注的值的数目相同,这称为注意力向量(attention vector),或注意力权重(attention weight),有时也称为对齐(alignment)。注意力权重与编码器状态(“值”)相结合,生成一个有时也称为glimpse的上下文向量(context vector)。这个上下文向量成为解码器的输入,而不是完整的句子编码。使用兼容性函数(compatibility function)更新下一个时间步的注意力向量,兼容性函数的具体性质取决于所使用的注意力机制。
有几种方法可以实现注意力。最简单和最常用的是内容感知机制(content-aware mechanism),你可以在“示例:神经机器翻译”一节中看到内容感知注意力。另一种流行的注意机制是位置感知(location-aware)注意力,它仅依赖于查询向量和键。注意权重通常是0到1之间的浮点值,这称为软注意力(soft attention)。相比之下,注意力也可以学习二进制0/1向量,这被称为硬注意力(hard attention)。
下图(8-9)中所示的注意机制取决于输入中所有时间步的编码器状态,这也被称为全局注意力(global attention)。相比之下,对于局部注意力(local attention),你可以设计一种仅依赖于当前时间步周围输入窗口的注意机制。
有时,特别是在机器翻译中,可以明确地提供对齐信息作为训练数据的一部分。在这种情况下,可以设计一种有监督的注意机制(supervised attention),使用单独的、经过共同训练的神经网络来学习注意力功能。对于诸如文档的大型输入,可以设计一种从粗粒度到细粒度(或分层的)的注意力机制,该机制不仅关注即时输入,还考虑文档段落、章节等结构。
Vaswani等人(2017)在transformer网络的研究中引入了多头注意力(multiheaded attention),其中多个注意力向量被用于跟踪输入的不同区域。他们还介绍了自注意力(self-attention)的概念,这是一种机制,通过这种机制,模型可以了解输入的哪些区域相互影响。
当输入是多模式时——例如,图像和语音——可以设计多模式(multimodal)注意力。有关注意力的文献虽新但广泛,正能说明其重要性。详细介绍每一种方法超出了本书的范围,作为开始,我们将向你介绍Luong、Pham和Manning(2015)以及Vaswani等人(2017)的工作。
8.4 评估序列生成模型
当可能有多个有效答案时,如生成任务中所示——一个法语句子可以有多个英语翻译,在这种情况下,分类指标(如精度、召回率、准确度和F1)对模型是没有帮助的。序列模型根据称为参考输出(reference output)的预期输出进行评估。在比较不同模型时,我们使用分数来表示模型输出的“goodness”与参考值的接近程度。例如,在像机器翻译这样的任务中,如果模型只差一个词,我们可能不想像惩罚另一个产生完全无法理解答案的模型一样惩罚那个模型。一个输入示例可能有多个参考输出,对于一个特定的法语句子,可能有多个有效的英语翻译,单词略微不同。序列生成模型有两种评估方式:人工评估和自动评估。
人工评估需要一个或多个人的参与,要么↑或↓该模型,以此对模型进行评级,要么进行编辑以纠正翻译。这会产生一个简单的“错误率”,它非常接近系统输出与人工任务相关的最终目标。人类评估尽管重要,然而很少使用,这是因为人工注解往往进度缓慢、成本昂贵和难以获得。人们给出的评估可能不一致,并且与其他任何标准一样,人工评估与注释间一致率(inter-annotator agreement rate)相配对。评估注释间一致率也很昂贵,一种常见的人类评估指标是human-targeted translation error rate(HTER),它是一个加权编辑距离,通过计算人类为“固定”翻译输出达到合理的意义和流利性而进行的插入、删除和转置次数得出,见下图(8-10):
另一方面,自动评估操作简单快捷。生成序列的自动评估有两种度量方式:基于n-gram重叠的度量(n-gram overlap–based metrics),困惑度(perplexity)。基于n-gram重叠的度量往往通过使用n-gram重叠统计来计算分数以衡量输出与参考的接近程度。BLEU,ROUGE和METEOR都是基于n-gram重叠的度量的示例,其中,BLEU(BiLingual Evaluation Understudy)经受了时间的考验,成为机器翻译文献中的衡量标准。这里我们并不详细介绍BLEU,详情请参见Papineni 等人(2002)。出于实际目的,我们使用像NLTK7或SacreBLEU8这样的包来计算得分。当参考数据可用时,BLEU本身的计算非常快速和简单。
困惑度是另一种自动评估指标,它基于信息论,你可以将之应用于可以衡量输出序列概率的任何情况。对于序列x,如果P(x)是序列的概率,则困惑度定义如下:
这为我们提供了一种比较不同序列生成模型的简单方法——基于数据集衡量模型的困惑度。尽管易于计算,然而当困惑度应用于序列评估时也会产生很多问题:首先,它是一个膨胀的指标,注意到困惑度的表达式涉及取幂。因此,模型性能(可能性)的微小差异可能导致困惑度的巨大差异,从而产生显著进步的错觉;其次,困惑度的变化可能不会转化为通过其他指标观察到的模型错误率的相应变化;最后,就像BLEU和其他基于ngram的指标一样,困惑度的提升可能不会导致人感觉到明显的改进。
在下一节中,我们将学习一个机器翻译示例,并通过PyTorch实现将这些概念巧妙地结合在一起。