提交 e5907688 编写于 作者: W wizardforcel

2021-01-16 17:23:08

上级 b6761f57
......@@ -2,7 +2,7 @@
在前两章中,我们使用神经网络对文本进行分类并执行情感分析。 两项任务都涉及获取 NLP 输入并预测一些值。 就我们的情感分析而言,这是一个介于 0 和 1 之间的数字,代表我们句子的情感。 就我们的句子分类模型而言,我们的输出是一个多类预测,其中我们的句子属于多个类别。 但是,如果我们不仅希望做出单个预测,还希望做出整个句子,该怎么办? 在本章中,我们将构建一个序列到序列模型,该模型将一种语言的句子作为输入,并输出另一种语言的句子翻译。
我们已经探索了用于 NLP 学习的几种类型的神经网络架构,即 “第 5 章” *中的循环神经网络,循环神经网络和情感分析*,以及卷积 “第 6 章” *中的神经网络,使用 CNN 的文本分类*。 在本章中,我们将再次使用这些熟悉的 RNN,而不仅仅是构建简单的 RNN 模型,我们还将 RNN 用作更大,更复杂的模型的一部分,以执行序列到序列的翻译。 通过使用我们在前几章中了解到的 RNN 的基础,我们可以展示如何扩展这些概念,以创建适合目的的各种模型。
我们已经探索了用于 NLP 学习的几种类型的神经网络架构,即 “第 5 章”,“循环神经网络和情感分析”中的循环神经网络,以及“第 6 章”,“使用 CNN 的文本分类”中的卷积神经网络。 在本章中,我们将再次使用这些熟悉的 RNN,而不仅仅是构建简单的 RNN 模型,我们还将 RNN 用作更大,更复杂的模型的一部分,以执行序列到序列的翻译。 通过使用我们在前几章中了解到的 RNN 的基础,我们可以展示如何扩展这些概念,以创建适合目的的各种模型。
在本章中,我们将介绍以下主题:
......@@ -77,27 +77,27 @@
图 7.7 –检查解码器
首先,我们的模型将上下文向量作为编码器步骤 *h0* 的最终隐藏状态。 然后,我们的模型旨在根据给定的当前隐藏状态预测句子中的下一个单词,然后预测句子中的前一个单词。 我们知道我们的句子必须以“开始”标记开头,因此,在第一步中,我们的模型会尝试根据给定的先前隐藏状态 *h0* 来预测句子中的第一个单词, 句子(在这种情况下,是“开始”标记)。 我们的模型进行预测(“ pienso”),然后更新隐藏状态以反映模型的新状态 *h1* 。 然后,在下一步中,我们的模型将使用新的隐藏状态和最后的预测单词来预测句子中的下一个单词。 这一直持续到模型预测出“ end”令牌为止,这时我们的模型停止生成输出字。
首先,我们的模型将上下文向量作为编码器步骤`h0`的最终隐藏状态。 然后,我们的模型旨在根据给定的当前隐藏状态预测句子中的下一个单词,然后预测句子中的前一个单词。 我们知道我们的句子必须以“开始”标记开头,因此,在第一步中,我们的模型会尝试根据给定的先前隐藏状态`h0`来预测句子中的第一个单词, 句子(在这种情况下,是“开始”标记)。 我们的模型进行预测(`"pienso"`),然后更新隐藏状态以反映模型的新状态`h1`。 然后,在下一步中,我们的模型将使用新的隐藏状态和最后的预测单词来预测句子中的下一个单词。 这一直持续到模型预测出“ end”令牌为止,这时我们的模型停止生成输出字。
该模型背后的直觉与到目前为止我们所学的关于语言表示的知识一致。 给定句子中的单词取决于其前面的单词。 因此,要预测句子中的任何给定单词而不考虑之前已被预测的单词,这将是没有意义的,因为任何给定句子中的单词都不是彼此独立的。
我们像以前一样学习模型参数:通过向前传递,根据预测句子计算目标句子的损失,并通过网络反向传播此损失,并随即更新参数。 但是,使用此过程进行学习可能会非常缓慢,因为首先,我们的模型具有很小的预测能力。 由于我们对目标句子中单词的预测不是彼此独立的,因此,如果我们错误地预测目标句子中的第一个单词,则输出句子中的后续单词也不太可能是正确的。 为了帮助完成此过程,我们可以使用一种称为**教师强制**的技术。
## 使用老师强迫
## 使用教师强制
由于我们的模型最初并未做出良好的预测,因此我们会发现任何初始误差都会成倍增加。 如果我们在句子中的第一个预测单词不正确,那么句子的其余部分也可能不正确。 这是因为我们的模型所做的预测取决于之前所做的预测。 这意味着我们的模型所遭受的任何损失都可以成倍增加。 因此,我们可能会遇到爆炸梯度问题,这使得我们的模型很难学习任何东西:
![Figure 7.8 – Using teacher forcing ](img/B12365_07_08.jpg)
图 7.8 –使用教师强
图 7.8 –使用教师强
但是,通过使用**老师强迫**,我们使用正确的先前目标词来训练我们的模型,以便一个错误的预测不会抑制我们的模型从正确的预测中学习的能力。 这意味着,如果我们的模型在句子中的某一点做出了错误的预测,那么它仍然可以使用后续单词来做出正确的预测。 尽管我们的模型仍然会错误地预测单词,并且会损失损耗以更新梯度,但是现在,我们没有遭受梯度爆炸的困扰,并且我们的模型将更快地学习:
但是,通过使用**教师强制**,我们使用正确的先前目标词来训练我们的模型,以便一个错误的预测不会抑制我们的模型从正确的预测中学习的能力。 这意味着,如果我们的模型在句子中的某一点做出了错误的预测,那么它仍然可以使用后续单词来做出正确的预测。 尽管我们的模型仍然会错误地预测单词,并且会损失损耗以更新梯度,但是现在,我们没有遭受梯度爆炸的困扰,并且我们的模型将更快地学习:
![Figure 7.9 – Updating for losses ](img/B12365_07_09.jpg)
图 7.9 –更新损失
您可以考虑使用教师强作为一种帮助我们的模型在每个时间步上独立于其先前预测进行学习的方式。 这样一来,早期阶段错误预测所导致的损失就不会转移到后续阶段。
您可以考虑使用教师强作为一种帮助我们的模型在每个时间步上独立于其先前预测进行学习的方式。 这样一来,早期阶段错误预测所导致的损失就不会转移到后续阶段。
通过组合编码器和解码器步骤,并应用教师强制来帮助我们的模型学习,我们可以构建一个序列到序列模型,该模型将允许我们将一种语言的序列翻译成另一种语言。 在下一节中,我们将说明如何使用 PyTorch 从头开始构建它。
......@@ -107,11 +107,11 @@
## 准备数据
到现在为止,我们对机器学习有了足够的了解,知道对于这样的任务,我们将需要一组带有相应标签的训练数据。 在这种情况下,我们将需要一种语言的**句子以及另一种语言**的相应翻译。 幸运的是,我们在上一章中使用的 **Torchtext** 库包含一个数据集,可让我们获取此信息。
到现在为止,我们对机器学习有了足够的了解,知道对于这样的任务,我们将需要一组带有相应标签的训练数据。 在这种情况下,我们将需要一种语言的句子以及另一种语言的相应翻译。 幸运的是,我们在上一章中使用的`Torchtext`库包含一个数据集,可让我们获取此信息。
**Torchtext** 中的 **Multi30k** 数据集由大约 30,000 个句子以及相应的多种语言翻译组成。 对于此翻译任务,我们的输入句子将使用英语,而我们的输出句子将使用德语。 因此,我们经过全面训练的模型将允许我们**将英语句子翻译成德语**
`Torchtext`中的 **Multi30k** 数据集由大约 30,000 个句子以及相应的多种语言翻译组成。 对于此翻译任务,我们的输入句子将使用英语,而我们的输出句子将使用德语。 因此,我们经过全面训练的模型将允许我们**将英语句子翻译成德语**
我们将从提取数据并对其进行预处理开始。 我们将再次使用 **spacy** ,其中包含内置词汇表,可用于标记数据:
我们将从提取数据并对其进行预处理开始。 我们将再次使用`spacy`,其中包含内置词汇表,可用于标记数据:
1. We start by loading our **spacy** tokenizers into Python. We will need to do this once for each language we are using since we will be building two entirely separate vocabularies for this task:
......@@ -121,7 +121,7 @@
重要的提示
您可能需要通过执行以下操作从命令行安装德语词汇表(我们在上一章中安装了英语词汇表): **python3 -m spacy download de**
您可能需要通过执行以下操作从命令行安装德语词汇表(我们在上一章中安装了英语词汇表):`python3 -m spacy download de`
2. Next, we create a function for each of our languages to tokenize our sentences. Note that our tokenizer for our input English sentence reverses the order of the tokens:
......@@ -139,7 +139,7 @@
图 7.10 –反转输入字
在这里,我们可以看到,为了正确预测第一个输出单词 *y0* ,我们从 *x0* 开始的第一个英语单词必须经过三个 RNN 层才能进行预测。 就学习而言,这意味着我们的梯度必须通过三个 RNN 层进行反向传播,同时保持通过网络的信息流。 现在,我们将其与的情况进行比较,在该情况下我们反转了输入句子:
在这里,我们可以看到,为了正确预测第一个输出单词`y0`,我们从`x0`开始的第一个英语单词必须经过三个 RNN 层才能进行预测。 就学习而言,这意味着我们的梯度必须通过三个 RNN 层进行反向传播,同时保持通过网络的信息流。 现在,我们将其与的情况进行比较,在该情况下我们反转了输入句子:
![Figure 7.11 – Reversing the input sentence ](img/B12365_07_101.jpg)
......@@ -357,10 +357,10 @@ pred = self.fc_out(output.squeeze(0))
输入= trg [0 ,:]
5. 接下来,我们遍历并做出预测。 我们将隐藏状态(从编码器的输出)传递到解码器,以及初始输入(即 **<起始>** 令牌)。 这将返回我们序列中所有单词的预测。 但是,我们只对当前步骤中的单词感兴趣。 也就是说,序列中的下一个单词。 请注意,我们是如何从 1 而不是 0 开始循环的,所以我们的第一个预测是序列中的第二个单词(因为预测的第一个单词将始终是起始标记)。
5. 接下来,我们遍历并做出预测。 我们将隐藏状态(从编码器的输出)传递到解码器,以及初始输入(即`<start>`令牌)。 这将返回我们序列中所有单词的预测。 但是,我们只对当前步骤中的单词感兴趣。 也就是说,序列中的下一个单词。 请注意,我们是如何从 1 而不是 0 开始循环的,所以我们的第一个预测是序列中的第二个单词(因为预测的第一个单词将始终是起始标记)。
6. This output consists of a vector of the target vocabulary’s length, with a prediction for each word within the vocabulary. We take the **argmax** function to identify the actual word that is predicted by the model.
然后,我们需要为下一步选择新的输入。 我们将教师强率设置为 50%,这意味着 50% 的时间,我们将使用刚刚做出的预测作为解码器的下一个输入,而其他 50% 的时间,我们将采用真正的目标 。 正如我们之前所讨论的,这比仅依赖模型的预测可以帮助我们的模型更快地学习。
然后,我们需要为下一步选择新的输入。 我们将教师强率设置为 50%,这意味着 50% 的时间,我们将使用刚刚做出的预测作为解码器的下一个输入,而其他 50% 的时间,我们将采用真正的目标 。 正如我们之前所讨论的,这比仅依赖模型的预测可以帮助我们的模型更快地学习。
然后,我们继续执行此循环,直到对序列中的每个单词有完整的预测为止:
......@@ -560,13 +560,13 @@ pred = self.fc_out(output.squeeze(0))
图 7.18 –翻译输出第一部分
在其他情况下,我们的模型仅需一个词即可完成。 在这种情况下,我们的模型会预测单词**hüten**而不是**mützen**; 但是,**hüten**实际上是**mützen**可接受的翻译,尽管这些词在语义上可能并不相同:
在其他情况下,我们的模型仅需一个词即可完成。 在这种情况下,我们的模型会预测单词`hüten`而不是`mützen`; 但是,`hüten`实际上是`mützen`可接受的翻译,尽管这些词在语义上可能并不相同:
![Figure 7.19 – Translation output part two ](img/B12365_07_19.jpg)
图 7.19 –翻译输出第二部分
我们还可以看到一些似乎被误解的示例。 在下面的示例中,我们预测的德语句子的英语等同词为**一名妇女爬过一个**”,这不等于“ **年轻女子攀岩面**。 但是,该模型仍然设法翻译了英语句子(女性和攀岩)的关键要素:
我们还可以看到一些似乎被误解的示例。 在下面的示例中,我们预测的德语句子的英语等同词为`A woman climbs through one`,这不等于`Young woman climbing rock face`。 但是,该模型仍然设法翻译了英语句子(女性和攀岩)的关键要素:
![Figure 7.20 – Translation output part three ](img/B12365_07_20.jpg)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册