提交 1ecd7f1b 编写于 作者: W wizardforcel

2021-01-16 17:27:14

上级 e5907688
......@@ -4,7 +4,7 @@
在上一章中,我们研究了如何构建序列到序列模型以将句子从一种语言翻译成另一种语言。 能够进行基本交互的对话型聊天机器人的工作方式几乎相同。 当我们与聊天机器人交谈时,我们的句子将成为模型的输入。 输出是聊天机器人选择回复的内容。 因此,我们正在训练它如何响应,而不是训练我们的聊天机器人来学习如何解释输入的句子。
我们将在上一章中扩展序列到序列模型,在模型中增加**注意**。 对序列到序列模型的这种改进意味着我们的模型可以学习输入句子中要查找的位置以获得所需信息的方式,而不是使用整个输入句子决策。 这项改进使我们能够创建具有最先进性能的效率更高的序列到序列模型。
我们将在上一章中扩展序列到序列模型,在模型中增加**注意**。 对序列到序列模型的这种改进意味着我们的模型可以学习输入句子中要查找的位置以获得所需信息的方式,而不是使用整个输入句子决策。 这项改进使我们能够创建具有最先进性能的效率更高的序列到序列模型。
在本章中,我们将研究以下主题:
......@@ -27,25 +27,31 @@
考虑以下示例:
我将于 3 月 2 日前往法国首都巴黎。 我的航班从伦敦希思罗机场出发,大约需要一个小时。
```py
I will be traveling to Paris, the capital city of France, on the 2nd of March. My flight leaves from London Heathrow airport and will take approximately one hour.
```
假设我们正在训练一种模型来预测句子中的下一个单词。 我们可以先输入句子的开头:
法国的首都是 _____。
```py
The capital city of France is _____.
```
在这种情况下,我们希望我们的模型能够检索单词 **Paris** 。 如果要使用基本的序列到序列模型,我们会将整个输入转换为隐藏状态,然后我们的模型将尝试从中提取相关信息。 这包括有关航班的所有无关信息。 您可能会在这里注意到,我们只需要查看输入句子的一小部分即可确定完成句子所需的相关信息:
在这种情况下,我们希望我们的模型能够检索单词`Paris`。 如果要使用基本的序列到序列模型,我们会将整个输入转换为隐藏状态,然后我们的模型将尝试从中提取相关信息。 这包括有关航班的所有无关信息。 您可能会在这里注意到,我们只需要查看输入句子的一小部分即可确定完成句子所需的相关信息:
我将于 3 月 2 日前往法国首都巴黎**。 我的航班从伦敦希思罗机场出发,大约需要一个小时。**
```py
I will be traveling to Paris, the capital city of France, on the 2nd of March. My flight leaves from London Heathrow airport and will take approximately one hour.
```
因此,如果我们可以训练模型以仅使用输入句子中的相关信息,则可以做出更准确和相关的预测。 为此,我们可以在网络中实现**注意**
因此,如果我们可以训练模型以仅使用输入句子中的相关信息,则可以做出更准确和相关的预测。 为此,我们可以在网络中实现**注意**
我们可以采用两种主要的注意力机制:局部和全局注意力。
## 比较本地和全球关注
## 比较本地和全局注意力
我们可以在网络中通过实现的两种注意形式与非常相似,但存在细微的关键区别。 我们将从关注本地开始。
**局部关注**中,我们的模型仅查看编码器的一些隐藏状态。 例如,如果我们正在执行句子翻译任务,并且我们正在计算翻译中的第二个单词,则模型可能希望仅查看与输入中第二个单词相关的编码器的隐藏状态 句子。 这意味着我们的模型需要查看编码器的第二个隐藏状态(`h`2),但也可能需要查看它之前的隐藏状态(`h`1)。
**局部注意力**中,我们的模型仅查看编码器的一些隐藏状态。 例如,如果我们正在执行句子翻译任务,并且我们正在计算翻译中的第二个单词,则模型可能希望仅查看与输入中第二个单词相关的编码器的隐藏状态 句子。 这意味着我们的模型需要查看编码器的第二个隐藏状态(`h`2),但也可能需要查看它之前的隐藏状态(`h`1)。
在下图中,我们可以在实践中看到这一点:
......@@ -57,13 +63,13 @@
然后,我们获取上下文向量,并将其转发给解码器以进行预测。 在我们基于非注意力的序列到序列模型中,我们只会向前传递最终的隐藏状态`h`n,但在这里我们看到的是,我们仅考虑了我们的相关隐藏状态 模型认为做出预测是必要的。
**全球关注**模型的运作方式与非常相似。 但是,我们不仅要查看所有隐藏状态,还希望查看模型的所有隐藏状态,因此命名为 global。 我们可以在此处看到全球关注层的图形化图示:
**全局注意力**模型的运作方式与非常相似。 但是,我们不仅要查看所有隐藏状态,还希望查看模型的所有隐藏状态,因此命名为 global。 我们可以在此处看到全局注意力层的图形化图示:
![Figure 8.3 – Global attention model ](img/B12365_08_3.jpg)
图 8.3 –全球关注模型
图 8.3 –全局注意力模型
我们在前面的图中可以看到,尽管这看起来与我们的本地关注框架非常相似,但是我们的模型现在正在查看所有隐藏状态,并计算所有隐藏状态的全局权重。 这使我们的模型可以查看它认为相关的输入句子的任何给定部分,而不必局限于由本地关注方法确定的本地区域。 我们的模型可能只希望看到一个很小的局部区域,但这在模型的能力范围内。 考虑全球关注框架的一种简单方法是,它实质上是学习一个掩码,该掩码仅允许通过与我们的预测相关的隐藏状态:
我们在前面的图中可以看到,尽管这看起来与我们的本地关注框架非常相似,但是我们的模型现在正在查看所有隐藏状态,并计算所有隐藏状态的全局权重。 这使我们的模型可以查看它认为相关的输入句子的任何给定部分,而不必局限于由本地关注方法确定的本地区域。 我们的模型可能只希望看到一个很小的局部区域,但这在模型的能力范围内。 考虑全局注意力框架的一种简单方法是,它实质上是学习一个掩码,该掩码仅允许通过与我们的预测相关的隐藏状态:
![Figure 8.4 – Combined model ](img/B12365_08_4.jpg)
......@@ -83,13 +89,13 @@
电影脚本由两个或更多角色之间的对话组成。 尽管此数据不是我们希望的自然格式,但我们可以轻松地将其转换为所需的格式。 以两个字符之间的简单对话为例:
* **第 1 行**您好 Bethan。
* **第 2 行**汤姆你好,你好吗?
* **第 3 行**非常感谢,您今天晚上在做什么?
* **第 4 行**我还没有任何计划。
* **第 5 行**您想和我一起吃晚饭吗?
* **第 1 行**`Hello Bethan.`
* **第 2 行**`Hello Tom, how are you?`
* **第 3 行**`I'm great thanks, what are you doing this evening?`
* **第 4 行**`I haven't got anything planned.`
* **第 5 行**`Would you like to come to dinner with me?`
现在,我们需要将其转换为调用和响应的输入和输出对,其中输入是脚本中的一行(调用),预期输出是脚本的下一行(响应)。 我们可以将`n`行的脚本转换为 *n-1* 对输入/输出:
现在,我们需要将其转换为调用和响应的输入和输出对,其中输入是脚本中的一行(调用),预期输出是脚本的下一行(响应)。 我们可以将`n`行的脚本转换为`n-1`对输入/输出:
![Figure 8.5 – Table of input and output ](img/B12365_08_05.jpg)
......@@ -123,7 +129,7 @@ corpus_name = "movie_corpus"
图 8.6 –检查数据集
首先,您会注意到我们的行与预期的一样,因为第一行的下半部分成为下一行的前半部分。 我们还可以注意到,每行的通话和响应半部分由制表符分隔符(**/ t**)分隔,我们的每行均由新的行分隔符(**/ n**)。 在处理数据集时,我们必须考虑到这一点。
首先,您会注意到我们的行与预期的一样,因为第一行的下半部分成为下一行的前半部分。 我们还可以注意到,每行的通话和响应半部分由制表符分隔符(`\t`)分隔,我们的每行均由新的行分隔符(`\n`)。 在处理数据集时,我们必须考虑到这一点。
第一步是创建一个词汇表或语料库,其中包含我们数据集中的所有唯一单词。
......@@ -337,7 +343,7 @@ corpus_name = "movie_corpus"
如前所述,仅在数据集中出现几次的单词会增加模型的维数,从而增加模型的复杂度以及训练模型所需的时间。 因此,最好将其从我们的训练数据中删除,以使我们的模型尽可能简化和高效。
您可能还记得我们在词汇表中内置了**修剪**函数,这使我们能够从词汇表中删除不经常出现的单词。 现在,我们可以创建一个函数来删除这些稀有单词,并从词汇表中调用 **trim** 方法,这是我们的第一步。 您将看到,这从我们的词汇表中删除了大部分单词,这表明我们词汇表中的大多数单词很少出现。 这是可以预期的,因为任何语言模型中的单词分布都会遵循长尾分布。 我们将使用以下步骤删除单词:
您可能还记得我们在词汇表中内置了`trim`函数,这使我们能够从词汇表中删除不经常出现的单词。 现在,我们可以创建一个函数来删除这些稀有单词,并从词汇表中调用`trim`方法,这是我们的第一步。 您将看到,这从我们的词汇表中删除了大部分单词,这表明我们词汇表中的大多数单词很少出现。 这是可以预期的,因为任何语言模型中的单词分布都会遵循长尾分布。 我们将使用以下步骤删除单词:
1. We first calculate the percentage of words that we will keep within our model:
......@@ -547,7 +553,7 @@ corpus_name = "movie_corpus"
self.embeddding =嵌入
接下来,我们创建我们的**循环** **神经** **网络**(**RNN**)模块。 在此聊天机器人中,我们将使用**门控循环单元**(**GRU**)代替 **Long** **短期** **内存 我们之前看到的**(**LSTM**)模型。 尽管 GRU 仍然控制通过 RNN 的信息流,但其的复杂度比 LSTM 小,但它们没有像 LSTM 这样的单独的门和更新门。 我们在这种情况下使用 GRU 的原因有几个:
接下来,我们创建我们的**循环神经网络**(**RNN**)模块。 在此聊天机器人中,我们将使用**门控循环单元**(**GRU**)代替我们之前看到的**长短期记忆**(**LSTM**)模型。 尽管 GRU 仍然控制通过 RNN 的信息流,但其的复杂度比 LSTM 小,但它们没有像 LSTM 这样的单独的门和更新门。 我们在这种情况下使用 GRU 的原因有几个:
a)由于需要学习的参数较少,因此 GRU 已被证明具有更高的计算效率。 这意味着我们的模型使用 GRU 进行训练要比使用 LSTM 进行训练更快。
......@@ -935,17 +941,17 @@ corpus_name = "movie_corpus"
对于聊天机器人,有多个不同的有效输出。 从与聊天机器人进行的一些对话中获取以下三行内容:
**输入***“您好”*
**输入**`Hello`
**输出***“您好”*
**输出**`Hello`
**输入***“您好”*
**输入**`Hello`
**输出***“你好。你好吗?”*
**输出**`Hello. How are you?`
**输入***你好”*
**输入**`Hello`
**输出***“您想要什么?”*
**输出**`What do you want?`
在这里,我们有三个不同的响应,每个响应都同样有效。 因此,在与聊天机器人进行对话的每个阶段,都不会出现任何“正确”的响应。 因此,评估要困难得多。 测试聊天机器人是否产生有效输出的最直观方法是与之对话! 这意味着我们需要以一种使我们能够与其进行对话以确定其是否运行良好的方式来设置聊天机器人:
......@@ -1269,7 +1275,7 @@ corpus_name = "movie_corpus"
图 8.17 –用于输入文本的 UI 元素
在此处输入您的文本,然后按*输入*,会将您的输入发送到聊天机器人。 使用我们训练有素的模型,我们的聊天机器人将创建一个响应并将其打印到控制台:
在此处输入您的文本,然后按`Enter`,会将您的输入发送到聊天机器人。 使用我们训练有素的模型,我们的聊天机器人将创建一个响应并将其打印到控制台:
![Figure 8.18 – Output for the chatbot ](img/B12365_08_18.jpg)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册