神经机器翻译(NMT)是一种机器翻译方法,它使用人工神经网络来预测一个单词序列的可能性,通常在一个单一的集成模型中建模整个句子。
对于计算机来说,用一个简单的基于规则的系统从一种语言转换成另一种语言是最困难的问题之一,因为它们无法捕捉到过程中的细微差别。不久之后,我们开始使用统计模型,但在进入深度学习之后,这个领域被统称为神经机器翻译,现在已经取得了最先进的成果。
因此,本文中的序列对序列(seq2seq)模型使用了一种编码器-解码器架构,它使用一种名为LSTM(长短期记忆)的RNN,其中编码器神经网络将输入的语言序列编码为单个向量,也称为上下文向量。
这个上下文向量被称为包含输入语言序列的抽象表示。
然后将这个向量传递到解码器神经网络中,用解码器神经网络一个词一个词地输出相应的输出语言翻译句子。
这里我正在做一个德语到英语的神经机器翻译。但同样的概念可以扩展到其他问题,如命名实体识别(NER),文本摘要,甚至其他语言模型,等等。
为了以我们想要的最佳方式获取数据,我使用了SpaCy(词汇构建)、TorchText(文本预处理)库和multi30k dataset,其中包含英语、德语和法语的翻译序列
让我们看看它能做的一些过程,
因此,一旦我们了解了torch文本可以做什么,让我们谈谈如何在torch text模块中实现它。在这里,我们将利用torchtext下的3个类。
Fields :这是torchtext下的一个类,在这里我们指定如何在我们的数据库里进行预处理。
TabularDataset:我们实际上可以定义以CSV、TSV或JSON格式存储的列数据集,并将它们映射为整数。
BucketIterator:我们可以填充我们的数据以获得近似,并使用我们的数据批量进行模型训练。
这里我们的源语言(SRC - Input)是德语,目标语言(TRG - Output)是英语。为了有效的模型训练,我们还额外增加了两个令牌“序列开始”<sos>和“序列结束”<eos>。
在设置了语言预处理标准之后,下一步是使用迭代器创建成批的训练、测试和验证数据。
创建批是一个详尽的过程,幸运的是我们可以利用TorchText的迭代器库。
这里我们使用BucketIterator来有效填充源句和目标句。我们可以使用.src属性访问源(德语)批数据,使用.trg属性访问对应的(英语)批数据。同样,我们可以在标记之前看到数据。
我刚刚试验了一批大小为32和样本批如下所示。这些句子被标记成一个单词列表,并根据词汇索引。“pad”标记的索引值为1。
每一列对应一个句子,用数字索引,在单个目标批处理中有32个这样的句子,行数对应于句子的最大长度。短句用1来填充以弥补其长度。
下表包含批处理的数字索引,这些索引稍后被输入到嵌入的单词中,并转换为密集表示,以便进行Seq2Seq处理。
下表包含与批处理的数字索引映射的对应单词。
但简单地说,传统RNN和门控(GRU)是无法捕捉的长期依赖性因其自然消失的梯度设计和遭受严重的问题,这使得权重和偏置值的变化率可以忽略不计,导致器泛化性的降低。
但是LSTM有一些特殊的单元称为门(记忆门,忘记门,更新门),这有助于克服前面提到的问题。
在LSTM细胞内,我们有一堆小型神经网络,在最后一层有sigmoid 和TanH激活和少量矢量加法,连接,乘法操作。
Sigmoid NN→压缩0到1之间的值。说接近0的值表示忘记,而接近1的值表示记住。
EmbeddingNN→将输入的单词索引转换为单词嵌入。
TanH NN→压缩-1和1之间的值。有助于调节矢量值,使其免于爆炸至最大值或缩小至最小值。
隐藏状态和单元状态在此称为上下文向量,它们是LSTM单元的输出。输入则是输入到嵌入NN中的句子的数字索引。
在开始构建seq2seq模型之前,我们需要创建一个Encoder,Decoder,并在seq2seq模型中创建它们之间的接口。
让我们通过德语输入序列“ Ich Liebe Tief Lernen”,该序列翻译成英语“ I love deep learning”。
为了便于说明,让我们解释上图中的过程。Seq2Seq模型的编码器一次只接受一个输入。我们输入的德语单词序列为“ ich Liebe Tief Lernen”。
另外,我们在输入句子的开头和结尾处附加序列“ SOS”的开头和句子“ EOS”标记的结尾。
因此在
编码器体系结构中的第一个块是单词嵌入层(以绿色块显示),该层将输入的索引词转换为被称为词嵌入的密集向量表示(大小为100/200/300)。
然后我们的词嵌入向量被发送到LSTM单元,在这里它与隐藏状态(hs)组合,并且前一个时间步的单元状态(cs)组合,编码器块输出新的hs和cs到下一个LSTM单元。可以理解,到目前为止,hs和cs捕获了该句子的某些矢量表示。
然后,在我们发送完所有输入的德语单词序列之后,最终获得上下文向量[以黄色块显示](hs,cs),该上下文向量是单词序列的密集表示形式,可以发送到解码器的第一个LSTM(hs ,cs)进行相应的英语翻译。
在上图中,我们使用2层LSTM体系结构,其中将第一个LSTM连接到第二个LSTM,然后获得2个上下文向量,这些向量堆叠在顶部作为最终输出。
我们必须在seq2seq模型中设计相同的编码器和解码器模块。
以上可视化适用于批处理中的单个句子。
假设我们的批处理大小为5,然后一次将5个句子(每个句子带有一个单词)传递给编码器,如下图所示。
解码器一次也执行单个步骤。
提供来自编码器块的上下文向量,作为解码器的第一个LSTM块的隐藏状态(hs)和单元状态(cs)。
句子“ SOS”令牌的开头被传递到嵌入的NN,然后传递到解码器的第一个LSTM单元,最后,它经过一个线性层[以粉红色显示],该层提供输出的英语令牌预测 概率(4556个概率)[4556 —如英语的总词汇量一样],隐藏状态(hs),单元状态(cs)。
选择4556个值中概率最高的输出单词,将隐藏状态(hs)和单元状态(cs)作为输入传递到下一个LSTM单元,并执行此过程,直到到达句子“ EOS”的结尾 ”。
除其他块外,您还将在Seq2Seq架构的解码器中看到以下所示的块。
在进行模型训练时,我们发送输入(德语序列)和目标(英语序列)。从编码器获得上下文向量后,我们将它们和目标发送给解码器进行翻译。
但是在模型推断期间,目标是根据训练数据的一般性从解码器生成的。因此,将输出的预测单词作为下一个输入单词发送到解码器,直到获得<EOS>令牌。
因此,在模型训练本身中,我们可以使用 teach force ratio(暂译教力比)控制输入字到解码器的流向。
我们可以在训练时将实际的目标词发送到解码器部分(以绿色显示)。
我们还可以发送预测的目标词,作为解码器的输入(以红色显示)。
此方法的作用类似于正则化。因此,在此过程中,模型可以快速有效地进行训练。
以上可视化适用于批处理中的单个句子。假设我们的批处理大小为4,然后一次将4个句子传递给编码器,该编码器提供4组上下文向量,它们都被传递到解码器中,如下图所示。
单个输入语句的最终seq2seq实现如下图所示。
以上可视化适用于批处理中的单个句子。假设我们的批处理大小为4,然后一次将4个句子传递给编码器,该编码器提供4组上下文向量,它们都被传递到解码器中,如下图所示。
例句训练进度:
训练损失:
现在,让我们将我们训练有素的模型与SOTA Google Translate的模型进行比较。
不错,但是很明显,该模型不能理解复杂的句子。因此,在接下来的系列文章中,我将通过更改模型的体系结构来提高上述模型的性能,例如使用双向LSTM,添加注意力机制或将LSTM替换为Transformers模型来克服这些明显的缺点。