导读:编码器和解码器模型与语言模型中的循环神经网络相似,同时训练阶段均通过遍历每个输出单词来建立动态计算图。
作者:菲利普·科恩
来源:华章计算机(hzbook_jsj)
从很多方面讲,神经翻译模型都是神经语言模型的一种扩展,因此它们的实现方式很相似。编码器和解码器模型与语言模型中的循环神经网络相似,同时训练阶段均通过遍历每个输出单词来建立动态计算图。
本节给出的代码是根据PyTorch官方教程中有关序列到序列翻译模型的部分经过改进后的结果。
1.编码器
编码器与7.8.1节中的循环神经网络相差无几:
由于编码器实际上并不预测单词,因此这里只需去掉softmax的计算。需要注意的是,该实现返回的是门控循环单元的输出状态。本章大部分内容描述了一种更为简单的模型,它采用前馈网络,将隐藏状态用于改进输入表示。
我们向这个编码器的类中添加一个额外的函数,即处理整个输入句子的函数:
函数返回整个输入句子的编码器表示encoder_outputs,它是一个矩阵或一个单词表示向量序列。上述循环遍历整个句子,并将GRU的输出状态存储在这个矩阵中。该循环与第7章循环神经语言模型的训练循环非常相似,不同之处在于该循环不计算任何损失。当然,我们在这里只是生成中间状态,这些状态无法进行评价。这也意味着输出状态不用预测下一个单词,而是由解码器在后续使用。
2.解码器
解码器的核心也是循环神经网络,但是模型进行了改进,使其能够利用输入句子的信息,涉及注意力的计算和编码器输出状态的加权。图8.9给出了解码器的完整代码。下面我们介绍代码中的关键部分。
▲图8.9 神经翻译模型的解码器。
解码器在每个时刻计算对编码器状态的注意力并预测一个输出单词
解码器不仅需要考虑前一时刻的输出单词和隐藏状态,也需要考虑编码器的输出,正如forward函数的参数所示。解码器还需要利用源句子长度实现注意力掩码:
首先,前一时刻的输出单词被映射为词嵌入prev_output。接下来需要计算注意力,它包括两个步骤:注意力权重的计算和利用权重衡量输入单词编码表示的贡献。
我们按照公式(8.6)计算注意力得分:
公式需要线性变换矩阵Wa、Ua和参数向量va:
forward函数实现了上述公式。为了清楚起见,将其分为两个步骤:
然后,利用softmax将注意力得分转化为权重。由于注意力得分是根据批训练中最大输入序列的长度计算的,因此需要屏蔽与实际单词不对应的值:
接下来,利用注意力权重对编码器的输出状态进行加权求和,计算源端输入的上下文:
解码器隐藏状态的更新与编码器类似,不同之处在于它不仅取决于前一时刻的隐藏状态,同时取决于前一时刻的输出单词:
最后,使用得到的源端输入的上下文和解码器隐藏状态信息对下一个目标单词进行预测:
3.训练
得到模型的所有基本组件后,训练就应该非常熟悉了。我们首先读取平行语料库(分两部分进行,源端和目标端,见https://opus.nlpl.eu/Tanzil.php,这里使用前20000行):
然后需要设定一些超参数,尤其是损失函数、隐藏状态的大小和学习率:
在具备上述条件之后,我们就可以实例化编码器和解码器。需要注意的是,这里有两个模型,因此需要定义两个优化器,每个模型一个优化器:
接下来是训练循环。首先对训练数据集进行多次遍历,每一次遍历对训练样本进行循环,开始下次循环之前先重置优化器:
之前定义了一个计算编码器状态的函数,这里只需调用它即可:
现在,我们可以遍历目标句子的单词。这与语言模型的训练循环基本相同,不同之处在于forward函数还需将encoder_output作为参数:
最后,运行反向传播算法并触发优化器:
知识点拓展:
注意力模型起源于序列到序列模型。文献(Cho et al.,2014)利用循环神经网络实现了序列到序列模型。文献(Sutskever et al.,2014)则使用了LSTM网络,并在解码前翻转了源语言语序。
文献(Bahdanau et al.,2015)开创性地增加了一种对齐模型(所谓的注意力机制),它能够将生成的输出单词与源端单词建立联系,同时输出单词也取决于前一时刻产生目标单词的隐藏状态。源语言单词由两个循环神经网络的隐藏状态表示,它们分别从左到右和从右到左编码源语言句子。文献(Luong et al.,2015b)改进了注意力机制(称为“全局”注意力模型),同时提出了一种硬约束的注意力模型(称为“局部”注意力模型),将注意力分布约束为围绕某个输入单词的高斯分布。
为了明确地平衡源端上下文(输入单词)和目标端上下文(已经产生的目标单词)之间的影响,(Tu et al.,2016a)介绍了一种基于插值权重(称为“上下文门”)的方法,该权重能够在预测解码器下一个隐藏状态时调节下列因素的影响:1)源端上下文状态;2)解码器前一时刻的隐藏状态和输出单词。
深度模型
人们在增加神经翻译模型的编码器和解码器的层数时提出了多种方法。文献(Wu et al.,2016)首先利用传统的双向循环神经网络计算输入单词的表示,然后使用多个堆叠循环层对其进行改进。文献(Shareghi et al.,2016)提出了前向和后向交替的循环神经网络模型。文献(Miceli Barone et al.,2017b)发现编码器和解码器使用4个堆叠层和两个深度转移层,同时在编码器上采用交替网络,可以取得很好的效果。在各种数据条件下,目前仍需要根据经验探索各种不同的选择(包括跳跃连接的使用、LSTM与GRU的选择,以及各种类型的层数选择等)。