提交 e394780c 编写于 作者: W wizardforcel

2021-01-22 10:38:57

上级 afccc45d
......@@ -97,11 +97,11 @@
# 模型
给定如图 A 所示的有向图模型,类型 <sub>![](img/b7641550-6815-4d7a-9aac-dc70858be377.png)</sub> 的联合分布; 一组`M`令牌<sub>![](img/1817f094-1f42-4f61-95b3-1ad5b6f70912.png)</sub> ; 及其相应的原始图像 <sub>![](img/aaec2166-2d9a-421d-a9b7-1752a71ae2e5.png)</sub> 分解如下:
给定如图 A 所示的有向图模型,类型 <sub>![](img/b7641550-6815-4d7a-9aac-dc70858be377.png)</sub> 的联合分布; 一组`M`标记<sub>![](img/1817f094-1f42-4f61-95b3-1ad5b6f70912.png)</sub> ; 及其相应的原始图像 <sub>![](img/aaec2166-2d9a-421d-a9b7-1752a71ae2e5.png)</sub> 分解如下:
![](img/a87b8aac-2728-4f0f-bfb7-9e588762ceca.png)
这三个生成过程分别是类型生成( <sub>![](img/6bf841f2-edcd-468b-a4a0-e7948217f921.png)</sub> ),令牌生成( <sub>![](img/551af09e-137b-4333-b68b-0038d9eefb47.png)</sub> )和图像生成( <sub>![](img/f0ad5c1b-7255-4e7c-8dfe-01808162a236.png)</sub> ),分别是 在下图中用其伪代码进行了讨论:
这三个生成过程分别是类型生成( <sub>![](img/6bf841f2-edcd-468b-a4a0-e7948217f921.png)</sub> ),标记生成( <sub>![](img/551af09e-137b-4333-b68b-0038d9eefb47.png)</sub> )和图像生成( <sub>![](img/f0ad5c1b-7255-4e7c-8dfe-01808162a236.png)</sub> ),分别是 在下图中用其伪代码进行了讨论:
![](img/16ff2f50-55be-44fd-8da5-661c7c7ea3a6.png)
......@@ -116,7 +116,7 @@
# 标记生成
字符标记 <sub>![](img/64c5d9e3-84b6-4eb5-bc34-815982591e9c.png)</sub> 是通过对墨水从笔到纸的流动方式进行建模而由零件和关系生成的。 用于令牌生成的伪代码在上图的 B 侧进行了描述。 首先,将噪声(此处称为运动方差)添加到子零件的比例尺和控制点,以定义冲程(或零件)轨迹 <sub>![](img/2f393738-87bd-4110-aa8a-111d12ad37ee.png)</sub> 。 轨迹的精确开始位置 <sub>![](img/e50475f0-4cb3-4366-b921-914e606d0e42.png)</sub> 由关系 <sub>![](img/3d4cd9b5-2fcd-4be5-9b8d-33bdd263c77b.png)</sub> 决定。 最后,将变换 <sub>![](img/92d0def5-ef1f-4670-a510-e5d83f77e0ac.png)</sub> 用于减轻概率推断。
字符标记 <sub>![](img/64c5d9e3-84b6-4eb5-bc34-815982591e9c.png)</sub> 是通过对墨水从笔到纸的流动方式进行建模而由零件和关系生成的。 用于标记生成的伪代码在上图的 B 侧进行了描述。 首先,将噪声(此处称为运动方差)添加到子零件的比例尺和控制点,以定义冲程(或零件)轨迹 <sub>![](img/2f393738-87bd-4110-aa8a-111d12ad37ee.png)</sub> 。 轨迹的精确开始位置 <sub>![](img/e50475f0-4cb3-4366-b921-914e606d0e42.png)</sub> 由关系 <sub>![](img/3d4cd9b5-2fcd-4be5-9b8d-33bdd263c77b.png)</sub> 决定。 最后,将变换 <sub>![](img/92d0def5-ef1f-4670-a510-e5d83f77e0ac.png)</sub> 用于减轻概率推断。
# 图像生成
......
......@@ -780,6 +780,6 @@ This is a small giraffe
# 总结
在本章中,我们更深入地研究了词嵌入及其应用。 我们已经展示了如何使用连续词袋模型来训练它们,以及如何结合 N 元组语言模型来更好地理解句子中词之间的关系。 然后,我们研究了将文档拆分为单独的令牌以进行轻松处理的方法,以及如何使用标记和分块来识别语音部分。 最后,我们展示了如何使用 TF-IDF 权重更好地以嵌入形式表示文档。
在本章中,我们更深入地研究了词嵌入及其应用。 我们已经展示了如何使用连续词袋模型来训练它们,以及如何结合 N 元组语言模型来更好地理解句子中词之间的关系。 然后,我们研究了将文档拆分为单独的标记以进行轻松处理的方法,以及如何使用标记和分块来识别语音部分。 最后,我们展示了如何使用 TF-IDF 权重更好地以嵌入形式表示文档。
在下一章中,我们将看到如何使用 NLP 进行文本预处理,词干提取和词义化。
\ No newline at end of file
......@@ -174,7 +174,7 @@ data = data.sample(frac=1)
## 预处理数据
首先,我们创建一个函数标记数据,将每个评论分为单个预处理词的列表。 我们遍历数据集,并为每条评论删除所有标点符号,将字母转换为小写字母,并删除任何尾随空格。 然后,我们使用 NLTK 令牌生成器根据此预处理文本创建单个令牌
首先,我们创建一个函数标记数据,将每个评论分为单个预处理词的列表。 我们遍历数据集,并为每条评论删除所有标点符号,将字母转换为小写字母,并删除任何尾随空格。 然后,我们使用 NLTK 标记生成器根据此预处理文本创建单个标记
```py
def split_words_reviews(data):
......@@ -230,7 +230,7 @@ print(np.mean([len(x) for x in reviews]))
图 5.14 –长度值
我们可以看到最长的句子是`70`个字长,平均句子长度是`11.78`。 为了捕获所有句子中的所有信息,我们希望填充所有句子,使它们的长度为 70。但是,使用更长的句子意味着更长的序列,这会使我们的 LSTM 层变得更深。 这意味着模型训练需要更长的时间,因为我们必须通过更多层反向传播梯度,但是这也意味着我们输入的很大一部分只是稀疏并且充满了空令牌,这使得从数据中学习的效率大大降低 。 我们的最大句子长度远大于我们的平均句子长度,这说明了这一点。 为了捕获我们大部分的句子信息而不会不必要地填充我们的输入并使它们太稀疏,我们选择使用`50`的输入大小。 您可能希望尝试在`20``70`之间使用不同的输入大小,以了解这如何影响模型性能。
我们可以看到最长的句子是`70`个字长,平均句子长度是`11.78`。 为了捕获所有句子中的所有信息,我们希望填充所有句子,使它们的长度为 70。但是,使用更长的句子意味着更长的序列,这会使我们的 LSTM 层变得更深。 这意味着模型训练需要更长的时间,因为我们必须通过更多层反向传播梯度,但是这也意味着我们输入的很大一部分只是稀疏并且充满了空标记,这使得从数据中学习的效率大大降低 。 我们的最大句子长度远大于我们的平均句子长度,这说明了这一点。 为了捕获我们大部分的句子信息而不会不必要地填充我们的输入并使它们太稀疏,我们选择使用`50`的输入大小。 您可能希望尝试在`20``70`之间使用不同的输入大小,以了解这如何影响模型性能。
我们将创建一个函数,使我们能够填充句子,使它们的大小相同。 对于短于序列长度的评论,我们用空标记填充它们。 对于长度超过序列长度的评论,我们只需丢弃超过最大序列长度的所有标记:
......@@ -256,7 +256,7 @@ padded_sentences[0]
图 5.15 –填充句子
我们必须进行进一步的调整,以允许在模型中使用空令牌。 当前,我们的词汇词典不知道如何将空令牌转换为整数以在我们的网络中使用。 因此,我们将它们手动添加到索引为`0`的字典中,这意味着当将空令牌输入模型时,它们的值将为`0`
我们必须进行进一步的调整,以允许在模型中使用空标记。 当前,我们的词汇词典不知道如何将空标记转换为整数以在我们的网络中使用。 因此,我们将它们手动添加到索引为`0`的字典中,这意味着当将空标记输入模型时,它们的值将为`0`
```py
int_to_word_dict[0] = ''
......@@ -518,7 +518,7 @@ def preprocess_review(review):
    return final
```
我们删除标点符号和尾随空格,将字母转换为小写,并像以前一样对输入句子进行分词。 我们将句子填充到长度为`50`的序列上,然后使用我们的预先计算的字典将的标记转换为数值。 请注意,我们的输入内容可能包含我们的网络从未见过的新词。 在这种情况下,我们的函数会将它们视为空令牌
我们删除标点符号和尾随空格,将字母转换为小写,并像以前一样对输入句子进行分词。 我们将句子填充到长度为`50`的序列上,然后使用我们的预先计算的字典将的标记转换为数值。 请注意,我们的输入内容可能包含我们的网络从未见过的新词。 在这种情况下,我们的函数会将它们视为空标记
接下来,我们创建实际的`predict()`函数。 我们预处理输入检查,将其转换为张量,然后将其传递给数据加载器。 然后,我们遍历该数据加载器(即使它仅包含一个句子),并通过我们的网络进行审查以获得预测。 最后,我们评估我们的预测并打印出正面还是负面的评价:
......
......@@ -227,7 +227,7 @@ questions.build_vocab(train_data,
labels.build_vocab(train_data)
```
在这里,我们可以看到,通过使用`build_vocab`函数并将我们的问题和标签作为训练数据进行传递,我们可以构建由 200 维 GLoVe 向量组成的词汇表。 请注意,`torchtext`软件包将自动下载并获取 GLoVe 向量,因此在这种情况下无需手动安装 GLoVe。 我们还定义了我们希望如何处理词汇表中未知的值(即,如果模型传递了不在预训练词汇表中的令牌,则模型将如何处理)。 在这种情况下,我们选择将它们视为具有未指定值的普通张量,尽管稍后会进行更新。
在这里,我们可以看到,通过使用`build_vocab`函数并将我们的问题和标签作为训练数据进行传递,我们可以构建由 200 维 GLoVe 向量组成的词汇表。 请注意,`torchtext`软件包将自动下载并获取 GLoVe 向量,因此在这种情况下无需手动安装 GLoVe。 我们还定义了我们希望如何处理词汇表中未知的值(即,如果模型传递了不在预训练词汇表中的标记,则模型将如何处理)。 在这种情况下,我们选择将它们视为具有未指定值的普通张量,尽管稍后会进行更新。
现在,通过调用以下命令,我们可以看到我们的词汇表由一系列预先训练的 200 维 GLoVe 向量组成:
......@@ -522,7 +522,7 @@ def predict_class(model, sentence, min_len = 5):
    tensor = tensor.unsqueeze(0)
```
我们首先将输入语句传递到令牌生成器中以获取令牌列表。 然后,如果此句子的长度小于最小句子长度,则将其添加到该句子中。 然后,在最终创建由这些索引的向量组成的张量之前,我们将使用词汇表获取所有这些单独标记的索引。 我们将其传递给我们的 GPU(如果可用),然后取消压缩输出,因为我们的模型需要三维张量输入而不是单个向量。
我们首先将输入语句传递到标记生成器中以获取标记列表。 然后,如果此句子的长度小于最小句子长度,则将其添加到该句子中。 然后,在最终创建由这些索引的向量组成的张量之前,我们将使用词汇表获取所有这些单独标记的索引。 我们将其传递给我们的 GPU(如果可用),然后取消压缩输出,因为我们的模型需要三维张量输入而不是单个向量。
接下来,我们做出预测:
......
......@@ -65,19 +65,19 @@
图 7.6 –检查编码器
我们使用最终的隐藏状态`h[n]`作为上下文向量,然后使用训练过的解码器对其进行解码。 也值得观察,在我们的序列到序列模型的上下文中,我们分别在输入句子的开头和结尾添加了`start``end`标记。 这是因为我们的输入和输出没有有限的长度,并且我们的模型需要能够学习句子何时结束。 我们的输入语句将始终以`end`令牌结尾,该令牌向编码器发出信号,表明此时的隐藏状态将用作此输入语句的最终上下文向量表示形式。 类似地,在解码器步骤中,我们将看到我们的解码器将继续生成单词,直到它预测到`end`令牌为止。 这使我们的解码器可以生成实际的输出语句,而不是无限长的令牌序列。
我们使用最终的隐藏状态`h[n]`作为上下文向量,然后使用训练过的解码器对其进行解码。 也值得观察,在我们的序列到序列模型的上下文中,我们分别在输入句子的开头和结尾添加了`start``end`标记。 这是因为我们的输入和输出没有有限的长度,并且我们的模型需要能够学习句子何时结束。 我们的输入语句将始终以`end`标记结尾,该标记向编码器发出信号,表明此时的隐藏状态将用作此输入语句的最终上下文向量表示形式。 类似地,在解码器步骤中,我们将看到我们的解码器将继续生成单词,直到它预测到`end`标记为止。 这使我们的解码器可以生成实际的输出语句,而不是无限长的标记序列。
接下来,我们将研究解码器如何获取此上下文向量,并学习将其转换为输出语句。
## 解码器
我们的解码器从我们的编码器层获取最终隐藏状态,并将其解码为另一种语言的句子。 我们的解码器是 RNN,类似于我们的编码器,但是我们的编码器会根据当前的隐藏状态和句子中的当前单词来更新其隐藏状态,而解码器会在每次迭代时更新其隐藏状态并输出令牌, 当前隐藏状态和句子中的先前预测单词。 在下图中可以看到:
我们的解码器从我们的编码器层获取最终隐藏状态,并将其解码为另一种语言的句子。 我们的解码器是 RNN,类似于我们的编码器,但是我们的编码器会根据当前的隐藏状态和句子中的当前单词来更新其隐藏状态,而解码器会在每次迭代时更新其隐藏状态并输出标记, 当前隐藏状态和句子中的先前预测单词。 在下图中可以看到:
![Figure 7.7 – Examining the decoder ](img/B12365_07_07.jpg)
图 7.7 –检查解码器
首先,我们的模型将上下文向量作为编码器步骤`h0`的最终隐藏状态。 然后,我们的模型旨在根据给定的当前隐藏状态预测句子中的下一个单词,然后预测句子中的前一个单词。 我们知道我们的句子必须以“开始”标记开头,因此,在第一步中,我们的模型会尝试根据给定的先前隐藏状态`h0`来预测句子中的第一个单词, 句子(在这种情况下,是“开始”标记)。 我们的模型进行预测(`"pienso"`),然后更新隐藏状态以反映模型的新状态`h1`。 然后,在下一步中,我们的模型将使用新的隐藏状态和最后的预测单词来预测句子中的下一个单词。 这一直持续到模型预测出`end`令牌为止,这时我们的模型停止生成输出字。
首先,我们的模型将上下文向量作为编码器步骤`h0`的最终隐藏状态。 然后,我们的模型旨在根据给定的当前隐藏状态预测句子中的下一个单词,然后预测句子中的前一个单词。 我们知道我们的句子必须以“开始”标记开头,因此,在第一步中,我们的模型会尝试根据给定的先前隐藏状态`h0`来预测句子中的第一个单词, 句子(在这种情况下,是“开始”标记)。 我们的模型进行预测(`"pienso"`),然后更新隐藏状态以反映模型的新状态`h1`。 然后,在下一步中,我们的模型将使用新的隐藏状态和最后的预测单词来预测句子中的下一个单词。 这一直持续到模型预测出`end`标记为止,这时我们的模型停止生成输出字。
该模型背后的直觉与到目前为止我们所学的关于语言表示的知识一致。 给定句子中的单词取决于其前面的单词。 因此,要预测句子中的任何给定单词而不考虑之前已被预测的单词,这将是没有意义的,因为任何给定句子中的单词都不是彼此独立的。
......@@ -347,13 +347,13 @@ def forward(self, input, h, cell):
h, cell = self.encoder(src)
```
4. 然后,我们必须在解码器模型中循环,为输出序列中的每一步生成一个输出预测。我们输出序列的第一个元素将始终是`<start>`令牌。我们的目标序列已经包含这个作为第一个元素,所以我们只需通过取列表中的第一个元素来设置我们的初始输入等于此。
4. 然后,我们必须在解码器模型中循环,为输出序列中的每一步生成一个输出预测。我们输出序列的第一个元素将始终是`<start>`标记。我们的目标序列已经包含这个作为第一个元素,所以我们只需通过取列表中的第一个元素来设置我们的初始输入等于此。
```py
input = trg[0,:]
```
5. 接下来,我们遍历并做出预测。 我们将隐藏状态(从编码器的输出)传递到解码器,以及初始输入(即`<start>`令牌)。 这将返回我们序列中所有单词的预测。 但是,我们只对当前步骤中的单词感兴趣。 也就是说,序列中的下一个单词。 请注意,我们是如何从 1 而不是 0 开始循环的,所以我们的第一个预测是序列中的第二个单词(因为预测的第一个单词将始终是起始标记)。
5. 接下来,我们遍历并做出预测。 我们将隐藏状态(从编码器的输出)传递到解码器,以及初始输入(即`<start>`标记)。 这将返回我们序列中所有单词的预测。 但是,我们只对当前步骤中的单词感兴趣。 也就是说,序列中的下一个单词。 请注意,我们是如何从 1 而不是 0 开始循环的,所以我们的第一个预测是序列中的第二个单词(因为预测的第一个单词将始终是起始标记)。
6. 这个输出由一个目标词汇长度的向量组成,并对词汇中的每个单词进行预测。我们采取`argmax`函数来确定模型预测的实际单词。
然后,我们需要为下一步选择新的输入。 我们将教师强制率设置为 50%,这意味着 50% 的时间,我们将使用刚刚做出的预测作为解码器的下一个输入,而其他 50% 的时间,我们将采用真正的目标 。 正如我们之前所讨论的,这比仅依赖模型的预测可以帮助我们的模型更快地学习。
......
......@@ -612,7 +612,7 @@ for line in lines[:3]:
## 定义训练过程
训练过程的第一步是为我们的模型定义损失的度量。 由于我们的输入张量可能由填充序列组成,由于我们输入的句子都具有不同的长度,因此我们不能简单地计算真实输出和预测输出张量之间的差。 为了解决这个问题,我们将定义一个损失函数,该函数将布尔掩码应用于输出,并且仅计算未填充令牌的损失:
训练过程的第一步是为我们的模型定义损失的度量。 由于我们的输入张量可能由填充序列组成,由于我们输入的句子都具有不同的长度,因此我们不能简单地计算真实输出和预测输出张量之间的差。 为了解决这个问题,我们将定义一个损失函数,该函数将布尔掩码应用于输出,并且仅计算未填充标记的损失:
1. 在下面的函数中,我们可以看到,我们计算的是整个输出张量的交叉熵损失。然而,为了得到总损失,我们只对被布尔掩码选中的张量元素进行平均。
......@@ -819,7 +819,7 @@ for line in lines[:3]:
    decoder_hidden = encoder_hidden[:decoder.n_layers]
```
3. 然后,用 SOS 令牌创建解码器输入,并初始化附加解码词的令牌(初始化为单个零值)。
3. 然后,用 SOS 标记创建解码器输入,并初始化附加解码词的标记(初始化为单个零值)。
```py
decoder_input = torch.ones(1, 1, device=device, dtype=torch.long) * SOS_token
......@@ -856,7 +856,7 @@ for line in lines[:3]:
    input_batch = torch.LongTensor(indices).transpose(0, 1)
```
6. 然后,我们将我们的长度和输入时序分配给相关设备。接下来,通过搜索器(`GreedySearchDecoder`)运行输入,以获得预测输出的词索引。最后,我们将这些词索引转化回词令牌,再作为函数输出返回。
6. 然后,我们将我们的长度和输入时序分配给相关设备。接下来,通过搜索器(`GreedySearchDecoder`)运行输入,以获得预测输出的词索引。最后,我们将这些词索引转化回词标记,再作为函数输出返回。
```py
input_batch = input_batch.to(device)
......
......@@ -45,13 +45,13 @@ BERT 是作为预训练的模型发布的,这意味着用户可以下载和实
"His poor performance meant they had no choice but to fire him"
```
使用双向语言模型来形成与上下文相关的单词表示形式,确实使 BERT 脱颖而出,成为最先进的模型。 对于任何给定的令牌,我们通过组合令牌,位置和分段嵌入来获得其输入表示:
使用双向语言模型来形成与上下文相关的单词表示形式,确实使 BERT 脱颖而出,成为最先进的模型。 对于任何给定的标记,我们通过组合标记,位置和分段嵌入来获得其输入表示:
![Figure 9.1 – BERT architecture ](img/B12365_09_1.jpg)
图 9.1 – BERT 架构
但是,重要的是要了解模型如何到达这些初始的上下文相关的令牌嵌入。
但是,重要的是要了解模型如何到达这些初始的上下文相关的标记嵌入。
### 遮罩语言建模
......@@ -232,7 +232,7 @@ x0 + t0 = E0
图 9.9 –堆叠式解码器
在每个时间步,我们的解码器都使用句子中先前生成的单词和`K, V`注意向量的组合来生成句子中的下一个单词。 反复重复此过程,直到解码器生成< END >令牌,表明它已完成生成最终输出。 转换器解码器上的给定时间步长可能看起来像这样:
在每个时间步,我们的解码器都使用句子中先前生成的单词和`K, V`注意向量的组合来生成句子中的下一个单词。 反复重复此过程,直到解码器生成< END >标记,表明它已完成生成最终输出。 转换器解码器上的给定时间步长可能看起来像这样:
![Figure 9.10 – Transformer decoder ](img/B12365_09_10.jpg)
......@@ -263,7 +263,7 @@ x0 + t0 = E0
## GPT-2
GPT-2 与 BERT 类似,但在一些细微的方面有所不同。 虽然这两种模型都基于先前概述的转换器架构,但是 BERT 使用一种称为自我注意力的注意力形式,而 GPT-2 使用屏蔽的自我注意力。 两者之间的另一个细微差别是 GPT-2 的构造方式使其可以一次输出一个令牌
GPT-2 与 BERT 类似,但在一些细微的方面有所不同。 虽然这两种模型都基于先前概述的转换器架构,但是 BERT 使用一种称为自我注意力的注意力形式,而 GPT-2 使用屏蔽的自我注意力。 两者之间的另一个细微差别是 GPT-2 的构造方式使其可以一次输出一个标记
这是因为 GPT-2 实际上在其工作方式上是自回归的。 这意味着当它生成输出(句子中的第一个单词)时,该输出将递归添加到输入中。 然后,此输入用于预测句子中的下一个单词,并重复进行直到生成完整的句子为止。 您可以在以下示例中看到这一点:
......@@ -295,7 +295,7 @@ GPT-2 与 BERT 类似,但在一些细微的方面有所不同。 虽然这两
**输出**`blue`
就 BERT 和 GPT-2 之间的性能而言,这是关键的权衡之一。 BERT 被双向训练的事实意味着这种单令牌生成是不可能的。 但是,GPT-2 不是双向的,因此在进行预测时只考虑句子中的先前单词,这就是为什么 BERT 在预测句子中缺少的单词时胜过 GPT-2 的原因。
就 BERT 和 GPT-2 之间的性能而言,这是关键的权衡之一。 BERT 被双向训练的事实意味着这种单标记生成是不可能的。 但是,GPT-2 不是双向的,因此在进行预测时只考虑句子中的先前单词,这就是为什么 BERT 在预测句子中缺少的单词时胜过 GPT-2 的原因。
## 比较自我注意和遮罩的自我注意
......@@ -305,7 +305,7 @@ GPT-2 与 BERT 类似,但在一些细微的方面有所不同。 虽然这两
图 9.11 –自我注意力机制
另一方面,不是双向的,因此屏蔽的自我关注机制只能查看已经看到的令牌,而不能“向前看”:
另一方面,不是双向的,因此屏蔽的自我关注机制只能查看已经看到的标记,而不能“向前看”:
![Figure 9.12 – Masked self-attention mechanism ](img/B12365_09_12.jpg)
......
......@@ -10,8 +10,8 @@ PyTorch 与 Python 深度集成,具有命令式风格,使用类似 Python
* 安装 PyTorch
* 在 PyTorch 中创建张量
* 互操作的 NumPy 桥
* 梯度无梯度
* 互操作的 NumPy 桥
* 梯度无梯度
* 在 PyTorch 中查看张量
# 技术要求
......
......@@ -19,7 +19,7 @@ CNN 使用过滤器从输入图像中拾取特征; 具有足够数量的滤镜
在本章中,我们将介绍以下秘籍:
* 探索卷积
* 探索池
* 探索池
* 探索转换
* 执行数据扩充
* 加载图像数据
......@@ -199,7 +199,7 @@ Conv2d(3, 16, kernel_size=(3, 4), stride=(3, 3), padding=(1, 2))
[8., 1., 0., 5., 4.]]])
```
4. 现在,我们将池应用于张量:
4. 现在,我们将池应用于张量:
```py
>>max_pool(a)
......@@ -350,10 +350,10 @@ PyTorch 无法直接处理图像像素,需要将其内容作为张量。 为
另一个重要任务是填充图像以匹配特定尺寸。 为此,我们使用`Pad()`方法。 我们将填充大小作为整数表示,用于在所有面上进行均等大小的填充,或者将序列作为由两个元素组成的序列,用于填充大小分别对应于左/右和上/下。 此外,我们可以将左侧,顶部,右侧和底部的填充大小作为由四个元素组成的序列传递。 然后,我们将填充值作为整数提供,如果它是三个元素的元组,则分别用作 R,G 和 B 通道的填充值。 除此之外,`Pad()`方法还具有`padding_mode`参数,该参数具有以下可能性:
* `constant`提供填充值的填充
* `edge`:在图像边缘填充数值
* `reflect`带有图像反射的填充,边缘像素除外
* `symmetric`带有图像反射的焊盘,包括边缘像素
* `constant`使用提供的填充值来填充
* `edge`:在图像边缘使用数值来填充
* `reflect`使用图像反射来填充,边缘像素除外
* `symmetric`使用图像反射来填充,包括边缘像素
最后,我们研究了`Compose()`转换,该转换通过将一系列转换对象作为参数传递来组合各种转换以构建转换管道。
......
......@@ -150,7 +150,7 @@ pip install torchtext
>>SequenceField = Field(tokenize=tokenizer, init_token='<sos>', eos_token='<eos>', lower=True, fix_length=50)
```
6. 我们可以设置一个未知的令牌
6. 我们可以设置一个未知的标记
```py
>>SequenceField = Field(tokenize=tokenizer, init_token='<sos>', eos_token='<eos>', unk_token='<unk>')
......@@ -168,13 +168,13 @@ pip install torchtext
在此秘籍中,我们根据手头的特定任务,使用`field`类对给定的输入文本执行了各种文本处理任务。 在审阅分类的示例中,在`review`字段中,我们将`sequential`参数设置为`True`,因为它是序列数据。 对于标签字段,我们将其设置为`False`,因为它们不是顺序的。 我们可以将文本设置为小写,这样就不会根据标记的大小写为相同的单词分配单独的标记 ID。 在评论分类的情况下,这不会影响含义; 这可以通过将`lower`设置为`True`来实现。
对于数字字段,我们将`use_vocab`设置为`False`,这是我们为审阅标签所做的,因为我们假设标签的负数值为`0`,正数的值为`1`。 我们从分词部分传递了`tokenizer`函数作为`tokenize`参数; 我们甚至可以通过设置`tokenize="spacy"`使用`spacy`的标记器。 对于某些任务,例如,使用`Sequence`对模型进行排序,我们可能需要特殊的标记来指示序列的开始和结束。 可以通过设置`init_token``eos_token`参数轻松完成。 这对于序列到序列的模型是正确的,并且如果在模型评估期间用于训练模型的词汇表中不存在令牌(词汇表外),则可以使用自定义令牌来替换这些令牌, 设置`unk_token`参数。
对于数字字段,我们将`use_vocab`设置为`False`,这是我们为审阅标签所做的,因为我们假设标签的负数值为`0`,正数的值为`1`。 我们从分词部分传递了`tokenizer`函数作为`tokenize`参数; 我们甚至可以通过设置`tokenize="spacy"`使用`spacy`的标记器。 对于某些任务,例如,使用`Sequence`对模型进行排序,我们可能需要特殊的标记来指示序列的开始和结束。 可以通过设置`init_token``eos_token`参数轻松完成。 这对于序列到序列的模型是正确的,并且如果在模型评估期间用于训练模型的词汇表中不存在标记(词汇表外),则可以使用自定义标记来替换这些标记, 设置`unk_token`参数。
然后,将`batch_first`设置为`True`,以使输出张量的第一维为批量维,如果`fix_length`参数设置为整​​数值,则将对输入设置固定长度 使用此字段。
# 更多
我们可以为特定于某种语言的分词设置用于分词的语言,该语言支持 spacy 支持的语言。 我们可以使用`pad_token`参数设置自定义填充令牌。 我们可以在分词之后但在数字化之前使用该字段定义将应用于示例的处理管道,在数字化之后但使用`preprocessing``postprocessing`参数将数字转换为张量之前,我们可以执行相同的操作。 `stop_words`参数可用于删除在预处理时需要删除的令牌。 此外,还有一种专门用于标签字段的字段类型`LabelField`,它可以代替普通字段使用。
我们可以为特定于某种语言的分词设置用于分词的语言,该语言支持 spacy 支持的语言。 我们可以使用`pad_token`参数设置自定义填充标记。 我们可以在分词之后但在数字化之前使用该字段定义将应用于示例的处理管道,在数字化之后但使用`preprocessing``postprocessing`参数将数字转换为张量之前,我们可以执行相同的操作。 `stop_words`参数可用于删除在预处理时需要删除的标记。 此外,还有一种专门用于标签字段的字段类型`LabelField`,它可以代替普通字段使用。
# 另见
......@@ -325,7 +325,7 @@ pip install torchtext
单词嵌入是单词的学习表示。 它们是单词的密集表示,其中为每个单词分配一个向量,即预定义向量空间中的实值向量,而不是数字标识符。 例如,一个单词将表示为![](img/e8ab6120-79d8-46fd-aa75-470d721ff4e5.png)`n`维向量-例如,语料库中的单词`book`可能表示为`[0.22, 0.242, ..., ..., 1.234]`而不是`[0, 0, 1, ..., 0]`的单引号表示。
数字表示只是单词的表示; 但是,单词嵌入是令牌的表示,其中该表示也包含令牌/单词的含义。 模型从单词出现的上下文中获悉了此含义。 在词嵌入中,具有相似含义的词具有相似的表示形式,我们可以对这些词向量执行向量算术,如下所示:
数字表示只是单词的表示; 但是,单词嵌入是标记的表示,其中该表示也包含标记/单词的含义。 模型从单词出现的上下文中获悉了此含义。 在词嵌入中,具有相似含义的词具有相似的表示形式,我们可以对这些词向量执行向量算术,如下所示:
![](img/c4fc9f6e-bc00-4e90-a9e6-00637c82c64d.png)
......@@ -357,7 +357,7 @@ pip install torchtext
# 工作原理
`torchtext`具有用于处理嵌入的`vocab`模块。 我们可以通过在此秘籍中提及需要的嵌入名称来下载预训练的嵌入。 我们使用了预先训练的 GloVe(GloVe 是词向量技术)模型,该模型使用 60 亿个​​令牌和 100 个嵌入维向量`glove.6B.50d`进行训练。
`torchtext`具有用于处理嵌入的`vocab`模块。 我们可以通过在此秘籍中提及需要的嵌入名称来下载预训练的嵌入。 我们使用了预先训练的 GloVe(GloVe 是词向量技术)模型,该模型使用 60 亿个​​标记和 100 个嵌入维向量`glove.6B.50d`进行训练。
然后,我们从缓存位置加载向量。 如果所需的嵌入不在高速缓存中,那么它将自动从 URL 下载并作为嵌入向量传递。 然后,我们使用`Review`字段对象的`build_vocab`方法从这些预训练的嵌入中建立词汇表,然后将其添加到训练数据的词汇表中。
......@@ -517,7 +517,7 @@ class MultiLSTMClassifier(nn.Module):
return self.fc(hidden[-1])
```
3. 接下来,我们向超参数添加一些层
3. 接下来,我们向超参数添加层数量
```py
>>NUM_LAYERS = 2
......@@ -547,7 +547,7 @@ class MultiLSTMClassifier(nn.Module):
# 双向 LSTM
该秘籍以多层 LSTM 秘籍为基础。 在正常的 LSTM 中,LSTM 会从头到尾读取输入序列。 但是,在双向 LSTM 中,有第二个 LSTM 从最后到第一个读取序列,即反向 RNN。 当当前时间戳的预测取决于序列中进一步输入时,这种类型的 LSTM 可以提高模型性能。 考虑示例“我看过漫画”和“我昨天看过漫画”。 在这种情况下,基于将来出现的令牌,相同的令牌(即`read`)具有不同的含义。 我们将在本秘籍中探讨其实现。
该秘籍以多层 LSTM 秘籍为基础。 在正常的 LSTM 中,LSTM 会从头到尾读取输入序列。 但是,在双向 LSTM 中,有第二个 LSTM 从最后到第一个读取序列,即反向 RNN。 当当前时间戳的预测取决于序列中进一步输入时,这种类型的 LSTM 可以提高模型性能。 考虑示例“我看过漫画”和“我昨天看过漫画”。 在这种情况下,基于将来出现的标记,相同的标记(即`read`)具有不同的含义。 我们将在本秘籍中探讨其实现。
# 准备
......
......@@ -116,7 +116,7 @@ torch.Size([1, 300])
如今,嵌入层还用于所有类型的分类输入,而不仅仅是嵌入自然语言。 例如,如果您要为英超联赛预测获胜者,则最好嵌入球队名称或地名,而不是将它们作为一站式编码向量传递给您的网络。
但是对于我们的用例,`torchtext`将前面的方法包装为一种将输入转换为嵌入的简单方法。 下面是一个示例,其中我们转移了从 GloVe 向量获得的学习信息,以从 Google 新闻中获得对 60 亿个令牌进行训练的预训练嵌入:
但是对于我们的用例,`torchtext`将前面的方法包装为一种将输入转换为嵌入的简单方法。 下面是一个示例,其中我们转移了从 GloVe 向量获得的学习信息,以从 Google 新闻中获得对 60 亿个标记进行训练的预训练嵌入:
```py
inputs = data.Field(lower=True)
......
......@@ -10,7 +10,7 @@ PyTorch 1.2 版本包括一个基于[论文](https://arxiv.org/pdf/1706.03762.pd
## 定义模型
在本教程中,我们将在语言建模任务上训练`nn.TransformerEncoder`模型。 语言建模任务是为给定单词(或单词序列)遵循单词序列的可能性分配概率。 令牌序列首先传递到嵌入层,然后传递到位置编码层以说明单词的顺序(有关更多详细信息,请参见下一段)。 `nn.TransformerEncoder`由多层[`nn.TransformerEncoderLayer`](https://pytorch.org/docs/master/nn.html?highlight=transformerencoderlayer#torch.nn.TransformerEncoderLayer)组成。 与输入序列一起,还需要一个正方形的注意掩码,因为`nn.TransformerEncoder`中的自注意层仅允许出现在该序列中的较早位置。 对于语言建模任务,应屏蔽将来头寸上的所有标记。 为了获得实际的单词,将`nn.TransformerEncoder`模型的输出发送到最终的`Linear`层,然后是对数 Softmax 函数。
在本教程中,我们将在语言建模任务上训练`nn.TransformerEncoder`模型。 语言建模任务是为给定单词(或单词序列)遵循单词序列的可能性分配概率。 标记序列首先传递到嵌入层,然后传递到位置编码层以说明单词的顺序(有关更多详细信息,请参见下一段)。 `nn.TransformerEncoder`由多层[`nn.TransformerEncoderLayer`](https://pytorch.org/docs/master/nn.html?highlight=transformerencoderlayer#torch.nn.TransformerEncoderLayer)组成。 与输入序列一起,还需要一个正方形的注意掩码,因为`nn.TransformerEncoder`中的自注意层仅允许出现在该序列中的较早位置。 对于语言建模任务,应屏蔽将来头寸上的所有标记。 为了获得实际的单词,将`nn.TransformerEncoder`模型的输出发送到最终的`Linear`层,然后是对数 Softmax 函数。
```py
import math
......@@ -53,7 +53,7 @@ class TransformerModel(nn.Module):
```
`PositionalEncoding`模块注入一些有关令牌在序列中的相对或绝对位置的信息。 位置编码的尺寸与嵌入的尺寸相同,因此可以将两者相加。 在这里,我们使用不同频率的`sine``cosine`函数。
`PositionalEncoding`模块注入一些有关标记在序列中的相对或绝对位置的信息。 位置编码的尺寸与嵌入的尺寸相同,因此可以将两者相加。 在这里,我们使用不同频率的`sine``cosine`函数。
```py
class PositionalEncoding(nn.Module):
......@@ -78,7 +78,7 @@ class PositionalEncoding(nn.Module):
## 加载和批量数据
本教程使用`torchtext`生成 Wikitext-2 数据集。 `vocab`对象是基于训练数据集构建的,用于将标记数字化为张量。 从序列数据开始,`batchify()`函数将数据集排列为列,以修剪掉数据分成大小为`batch_size`的批量后剩余的所有令牌。 例如,以字母为序列(总长度为 26)并且批大小为 4,我们将字母分为 4 个长度为 6 的序列:
本教程使用`torchtext`生成 Wikitext-2 数据集。 `vocab`对象是基于训练数据集构建的,用于将标记数字化为张量。 从序列数据开始,`batchify()`函数将数据集排列为列,以修剪掉数据分成大小为`batch_size`的批量后剩余的所有标记。 例如,以字母为序列(总长度为 26)并且批大小为 4,我们将字母分为 4 个长度为 6 的序列:
![](img/tex27-1.gif)
......
......@@ -333,7 +333,7 @@ plt.plot(all_losses)
## 网络采样
为了示例,我们给网络一个字母,询问下一个字母是什么,将其作为下一个字母输入,并重复直到 EOS 令牌
为了示例,我们给网络一个字母,询问下一个字母是什么,将其作为下一个字母输入,并重复直到 EOS 标记
* 为输入类别,起始字母和空隐藏状态创建张量
* 用起始字母创建一个字符串`output_name`
......@@ -346,7 +346,7 @@ plt.plot(all_losses)
注意
不必给它起一个开始字母,另一种策略是在训练中包括一个“字符串开始”令牌,并让网络选择自己的开始字母。
不必给它起一个开始字母,另一种策略是在训练中包括一个“字符串开始”标记,并让网络选择自己的开始字母。
```py
max_length = 20
......
......@@ -290,7 +290,7 @@ class EncoderRNN(nn.Module):
在最简单的 seq2seq 解码器中,我们仅使用编码器的最后一个输出。 该最后的输出有时称为*上下文向量*,因为它从整个序列中编码上下文。 该上下文向量用作解码器的初始隐藏状态。
在解码的每个步骤中,为解码器提供输入令牌和隐藏状态。 初始输入令牌是字符串开始`<SOS>`令牌,第一个隐藏状态是上下文向量(编码器的最后一个隐藏状态)。
在解码的每个步骤中,为解码器提供输入标记和隐藏状态。 初始输入标记是字符串开始`<SOS>`标记,第一个隐藏状态是上下文向量(编码器的最后一个隐藏状态)。
![](img/34b376e0c7299810f7349ab99c2c5497.png)
......@@ -378,7 +378,7 @@ class AttnDecoderRNN(nn.Module):
### 准备训练数据
为了训练,对于每一对,我们将需要一个输入张量(输入句子中单词的索引)和目标张量(目标句子中单词的索引)。 创建这些向量时,我们会将`EOS`令牌附加到两个序列上。
为了训练,对于每一对,我们将需要一个输入张量(输入句子中单词的索引)和目标张量(目标句子中单词的索引)。 创建这些向量时,我们会将`EOS`标记附加到两个序列上。
```py
def indexesFromSentence(lang, sentence):
......@@ -398,7 +398,7 @@ def tensorsFromPair(pair):
### 训练模型
为了训练,我们通过编码器运行输入语句,并跟踪每个输出和最新的隐藏状态。 然后,为解码器提供`<SOS>`令牌作为其第一个输入,为编码器提供最后的隐藏状态作为其第一个隐藏状态。
为了训练,我们通过编码器运行输入语句,并跟踪每个输出和最新的隐藏状态。 然后,为解码器提供`<SOS>`标记作为其第一个输入,为编码器提供最后的隐藏状态作为其第一个隐藏状态。
“教师强制”的概念是使用实际目标输出作为每个下一个输入,而不是使用解码器的猜测作为下一个输入。 使用教师强制会导致其收敛更快,但是当使用受过训练的网络时,[可能会显示不稳定](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.378.4095&rep=rep1&type=pdf)
......@@ -551,7 +551,7 @@ def showPlot(points):
## 评估
评估与训练基本相同,但是没有目标,因此我们只需将解码器的预测反馈给每一步。 每当它预测一个单词时,我们都会将其添加到输出字符串中,如果它预测到`EOS`令牌,我们将在此处停止。 我们还将存储解码器的注意输出,以供以后显示。
评估与训练基本相同,但是没有目标,因此我们只需将解码器的预测反馈给每一步。 每当它预测一个单词时,我们都会将其添加到输出字符串中,如果它预测到`EOS`标记,我们将在此处停止。 我们还将存储解码器的注意输出,以供以后显示。
```py
def evaluate(encoder, decoder, sentence, max_length=MAX_LENGTH):
......
......@@ -97,7 +97,7 @@ print(torch.__config__.parallel_info())
* 标记输入序列;
* 在开头插入[CLS];
* 在第一句和第二句之间并在最后插入[SEP];
* 生成令牌类型 ID,以指示令牌是属于第一序列还是第二序列。
* 生成标记类型 ID,以指示标记是属于第一序列还是第二序列。
[`gum_compute_metrics`](https://github.com/huggingface/transformers/blob/master/transformers/data/processors/glue.py)函数的计算指标为 [F1 得分](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html),可以将其解释为精度和召回率的加权平均值,其中 F1 得分在 1 和最差处达到最佳值 得分为 0。精度和召回率对 F1 得分的相对贡献相等。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册