提交 2af7c240 编写于 作者: W wizardforcel

2021-01-23 22:07:42

上级 0c354932
......@@ -2,9 +2,9 @@
我们的世界拥有丰富的自然语言数据。 在过去的几十年中,我们彼此之间的通信方式已经转变为数字领域,因此,这些数据可用于构建可改善我们在线体验的模型。 从在搜索引擎中返回相关结果,到自动完成您在电子邮件中输入的下一个单词,从自然语言中提取见解的好处显而易见。
尽管我们作为人类的语言理解方式与模型或*人工智能*理解语言的方式明显不同,但通过阐明机器学习及其用途,我们可以开始理解 这些深度学习模型*理解*语言,以及模型从数据中学习时发生的根本变化。
尽管我们作为人类的语言理解方式与模型或*人工智能*理解语言的方式明显不同,但通过阐明机器学习及其用途,我们可以开始理解,这些深度学习模型如何*理解*语言,以及模型从数据中学习时发生的根本变化。
在本书中,我们将探讨人工智能和深度学习对自然语言的这种应用。 通过使用 PyTorch,我们将逐步学习如何构建模型,使我们能够执行情感分析,文本分类和序列翻译,从而使我们构建一个基本的聊天机器人。 通过介绍这些模型背后的理论,并演示如何实际实现它们,我们将使**自然语言处理****NLP**)的领域神秘化,并为您提供足够的背景知识 让您开始构建自己的模型。
在本书中,我们将探讨人工智能和深度学习对自然语言的这种应用。 通过使用 PyTorch,我们将逐步学习如何构建模型,使我们能够执行情感分析,文本分类和序列翻译,从而使我们构建一个基本的聊天机器人。 通过介绍这些模型背后的理论,并演示如何实际实现它们,我们将使**自然语言处理****NLP**)的领域神秘化,并为您提供足够的背景知识让您开始构建自己的模型。
在第一章中,我们将探讨机器学习的一些基本概念。 然后,我们将通过研究深度学习,神经网络的基础知识以及深度学习方法相对于基本机器学习技术所具有的一些优势,将这一步骤进一步向前发展。 最后,我们将更深入地研究深度学习,特别是针对特定于 NLP 的任务,以及我们如何使用深度学习模型从自然语言中获得见解。 具体来说,我们将涵盖以下主题:
......
......@@ -203,7 +203,7 @@ PyTorch 与其他深度学习框架之间的另一个主要区别是语法。 Py
train = train.drop("label",axis=1).values.reshape(len(test),1,28,28)
```
请注意,我们将输入重塑为`[1, 1, 28, 28]`,每个张量为 1,000 张图像 由`28x28`像素组成。
请注意,我们将输入重塑为`[1, 1, 28, 28]`,是 1,000 张图像的张量,每个图像由`28x28`像素组成。
2. 接下来,我们将我们的训练数据和训练标签转换为 PyTorch 张量,以便它们可以被输入到神经网络中。
......@@ -212,7 +212,7 @@ PyTorch 与其他深度学习框架之间的另一个主要区别是语法。 Py
y = torch.Tensor(train_labels).long()
```
注意这两个张量的数据类型。 浮点张量由 32 位浮点数组成,而长张量由 64 位整数组成。 为了使 PyTorch 能够计算梯度,我们的`X`函数必须为浮点数,而我们的标签必须为该分类模型中的整数(因为我们正在尝试预测 1、2、3 等等),因此 1.5 的预测就没有意义。
注意这两个张量的数据类型。 浮点张量由 32 位浮点数组成,而长张量由 64 位整数组成。 为了使 PyTorch 能够计算梯度,我们的`X`函数必须为浮点数,而我们的标签必须为该分类模型中的整数(因为我们正在尝试预测 1、2、3 等等),因此 1.5 的预测就没有意义。
## 构建分类器
......@@ -283,7 +283,7 @@ opt = optim.Adam(model.parameters(), lr=0.001)
Loss(y) = -log(y)
```
假设我们的图像为 7。如果我们以概率 1 预测类别 7,则损失为`-log(1) = 0`,但是如果我们仅以概率 0.7 预测类别 7,则损失将是`-log(0.7) = 0.3`。 这意味着我们与正确预测的距离越远,损失就越接近无穷大:
假设我们的图像为 7。如果我们以概率 1 预测类别 7,则损失为`-log(1) = 0`,但是如果我们仅以概率 0.7 预测类别 7,则损失将是`-log(0.7) = 0.3`。 这意味着我们与正确预测的距离越远,损失就越接近无穷大:
![Figure 2.13 – Representation of loss for our network ](img/B12365_02_13.jpg)
......@@ -444,7 +444,7 @@ print((correct/preds)*100)
图 2.18 –设置分类器
请注意,在这里,我们遍历了所有训练数据和测试数据。 如果我们只是在训练数据上创建单词索引,则在评估测试集时,我们将拥有在原始训练中看不到的新单词,因此我们将无法创建真正的单词袋 这些单词的表示形式。
请注意,在这里,我们遍历了所有训练数据和测试数据。 如果我们只是在训练数据上创建单词索引,则在评估测试集时,我们将拥有在原始训练中看不到的新单词,因此我们将无法创建这些单词的真正的词袋表示形式。
3. 现在,我们以类似于上一节中构建神经网络的方式来构建我们的分类器,即通过构建一个新的类,该类继承自`nn.Module`
......
......@@ -372,7 +372,7 @@ The dog sat on the cat -> [1,1,0,1,1,1]
## N 元组语言建模
N 元组帮助我们做的一件事是了解自然语言是如何形成的。 如果我们认为一种语言是由较小的单词对(二元图)的一部分而不是单个单词代表的,则可以开始将语言建模为概率模型,其中单词出现在句子中的概率取决于之前出现的单词 它
N 元组帮助我们做的一件事是了解自然语言是如何形成的。 如果我们认为一种语言是由较小的单词对(二元图)的一部分而不是单个单词代表的,则可以开始将语言建模为概率模型,其中单词出现在句子中的概率取决于它之前出现的单词
**一元**模型中,我们假设基于单词在语料库或文档中的分布,所有单词都有出现的可能性。 我们来看一个包含一个句子的文档:
......
......@@ -67,7 +67,7 @@ print('Output: ' + str(output_text))
图 4.2 –将输入转换为小写
这表明输入已全部转换为相同的小写表示形式。 有一些示例中的大写字母实际上可以提供其他语义信息。 例如, `May`(五月)和`may`(意味着*可能*)在语义上有所不同, `May`(五月)将始终是 大写。 但是,像这样的实例非常少见,将所有内容都转换为小写字母要比考虑这些少见的实例更为有效。
这表明输入已全部转换为相同的小写表示形式。 有一些示例中的大写字母实际上可以提供其他语义信息。 例如, `May`(五月)和`may`(意味着*可能*)在语义上有所不同, `May`(五月)将始终是大写。 但是,像这样的实例非常少见,将所有内容都转换为小写字母要比考虑这些少见的实例更为有效。
值得注意的是,大写可能在某些任务中很有用,例如语音标记的一部分(其中大写字母可能指示单词在句子中的作用)和命名实体识别(其中大写字母可能表明单词在句子中) 专有名词而不是非专有名词的替代; 例如`Turkey`(国家)和`turkey`(鸟类)。
......@@ -323,7 +323,7 @@ print(wordnet_lemmatizer.lemmatize('run', pos='v'))
图 4.13 –在功能中实现 POS
这意味着为了返回任何给定句子的正确词形,我们必须首先执行 POS 标记以获得句子中词的上下文,然后将其传递给词形还原器以获取每个词的词形 在句子中。 我们首先创建一个函数,该函数将为句子中的每个单词返回 POS 标签:
这意味着为了返回任何给定句子的正确词形,我们必须首先执行 POS 标记以获得句子中词的上下文,然后将其传递给词形还原器以获取句子中每个词的词形。 我们首先创建一个函数,该函数将为句子中的每个单词返回 POS 标签:
```py
sentence = 'The cats and dogs are running'
......@@ -388,7 +388,7 @@ lemmatize_with_pos(sentence)
现在我们已经看到了词干提取和词形还原,在的问题上,仍然存在问题,在什么情况下我们应该同时使用这两种技术。 我们看到,两种技术都试图将每个单词的根都减少。 在词干提取中,可能只是目标房间的简化形式,而在词形还原中,它会还原为真正的英语单词词根。
因为词义化需要在 WordNet 语料库中交叉引用目标词,并执行词性分析以确定词义的形式,所以如果必须使用大量词,这可能会花费大量的处理时间。 形容词 这与词干提取相反,词干提取使用详细但相对较快的算法来提取词干。 最终,与计算中的许多问题一样,这是在速度与细节之间进行权衡的问题。 在选择将这些方法中的哪一种纳入我们的深度学习流程时,要在速度和准确率之间进行权衡。 如果时间很重要,那么阻止可能是要走的路。 另一方面,如果您需要模型尽可能详细和准确,则限制词形还原可能会产生更好的模型。
因为词义化需要在 WordNet 语料库中交叉引用目标词,并执行词性分析以确定词义的形式,所以如果必须使用大量词,这可能会花费大量的处理时间。 这与词干提取相反,词干提取使用详细但相对较快的算法来提取词干。 最终,与计算中的许多问题一样,这是在速度与细节之间进行权衡的问题。 在选择将这些方法中的哪一种纳入我们的深度学习流程时,要在速度和准确率之间进行权衡。 如果时间很重要,那么阻止可能是要走的路。 另一方面,如果您需要模型尽可能详细和准确,则限制词形还原可能会产生更好的模型。
# 总结
......
......@@ -33,7 +33,7 @@ RNN 由循环层组成。 尽管它们在许多方面类似于标准前馈神经
该层用于`n`时间步长的输入。 我们的隐藏状态在状态`h0`中初始化,然后使用我们的第一个输入`x1`来计算下一个隐藏状态`h1`。 还学习了两组权重矩阵:矩阵`U`和矩阵`W`,矩阵`U`了解隐藏状态如何在时间步之间变化,矩阵`W`隐藏状态。
我们还将 *tanh* 激活函数应用于所得产品,将隐藏状态的值保持在 -1 和 1 之间。用于计算任何隐藏状态的公式`h[t]`变为 以下:
我们还将 *tanh* 激活函数应用于所得产品,将隐藏状态的值保持在 -1 和 1 之间。用于计算任何隐藏状态的公式`h[t]`变为以下:
![](img/Formula_05_001.png)
......@@ -117,7 +117,7 @@ LSTM 与 RNN 的结构非常相似。 虽然 LSTM 的各个步骤之间存在一
图 5.7 –遗忘门
遗忘门本质上是学习要忘记序列中的哪些元素。 先前的隐藏状态`h[t-1]`和最新的输入步骤`x1`被串联在一起,并通过了在遗忘门和 Sigmoid 函数上获得的权重矩阵 将值压缩为 0 到 1 之间的值。将得到的矩阵`f[t]`逐点乘以上一步`c[t-1]`单元状态。 这有效地将掩码应用于先前的小区状态,使得仅来自先前的小区状态的相关信息被提出。
遗忘门本质上是学习要忘记序列中的哪些元素。 先前的隐藏状态`h[t-1]`和最新的输入步骤`x1`被串联在一起,并通过了在遗忘门上习得的权重矩阵,以及 Sigmoid 函数,它将值压缩为 0 到 1 之间。将得到的矩阵`f[t]`逐点乘以上一步`c[t-1]`单元状态。 这有效地将掩码应用于先前的小区状态,使得仅来自先前的小区状态的相关信息被提出。
接下来,我们将查看**输入门**
......@@ -125,7 +125,7 @@ LSTM 与 RNN 的结构非常相似。 虽然 LSTM 的各个步骤之间存在一
图 5.8 –输入门
输入门再次采用串联的先前隐藏状态`h[t-1]`和当前序列输入`x[t]`,并将其通过具有学习参数的 Sigmoid 函数,从而输出 另一个矩阵`i[t]`由 0 到 1 之间的值组成。串联的隐藏状态和序列输入也通过 tanh 函数,该函数将输出压缩在 -1 和 1 之间。 通过`i[t]`矩阵。 这意味着生成`i[t]`所需的学习参数可以有效地了解应从当前时间步长将哪些元素保留在我们的细胞状态中。 然后将其添加到当前单元状态以获得最终单元状态,该状态将继续进行到下一个时间步骤。
输入门再次采用串联的先前隐藏状态`h[t-1]`和当前序列输入`x[t]`,并将其通过具有学习参数的 Sigmoid 函数,从而输出另一个矩阵`i[t]`,它由 0 到 1 之间的值组成。串联的隐藏状态和序列输入也通过 tanh 函数,该函数将输出压缩在 -1 和 1 之间。 通过`i[t]`矩阵。 这意味着生成`i[t]`所需的学习参数可以有效地了解应从当前时间步长将哪些元素保留在我们的细胞状态中。 然后将其添加到当前单元状态以获得最终单元状态,该状态将继续进行到下一个时间步骤。
最后,我们有是 LSTM 单元的最后一个元素-**输出门**
......@@ -135,7 +135,7 @@ LSTM 与 RNN 的结构非常相似。 虽然 LSTM 的各个步骤之间存在一
输出门计算 LSTM 单元的最终输出-单元状态和隐藏状态,并继续进行下一步。 单元状态`c[t]`与前两个步骤相同,是遗忘门和输入门的乘积。 通过获取串联的先前隐藏状态`h[t-1]`和当前时间步输入`x[t]`,可以计算出最终隐藏状态`h[t]`,并通过具有一些学习参数的 Sigmoid 函数来获得输出门输出`o[t]`。 最终单元状态`c[t]`通过 tanh 函数并乘以输出门输出`o[t]`,以计算最终隐藏状态`h[t]`。 这意味着在输出门上学习到的参数可以有效地控制将先前隐藏状态和当前输出中的哪些元素与最终单元状态进行组合,以作为新的隐藏状态延续到下一个时间步长。
在我们的前向遍历中,我们简单地遍历模型,初始化我们的隐藏状态和单元状态,并在每个时间步使用 LSTM 单元对其进行更新,直到剩下最终的隐藏状态为止,该状态将输出到神经元的下一层 网络。 通过在 LSTM 的所有层中进行反向传播,我们可以计算相对于网络损失的梯度,因此我们知道通过梯度下降来更新参数的方向。 我们得到几种矩阵或参数-一种用于输入门,一种用于输出门,以及一种用于遗忘门。
在我们的前向遍历中,我们简单地遍历模型,初始化我们的隐藏状态和单元状态,并在每个时间步使用 LSTM 单元对其进行更新,直到剩下最终的隐藏状态为止,该状态将输出到网络下一层的神经元。 通过在 LSTM 的所有层中进行反向传播,我们可以计算相对于网络损失的梯度,因此我们知道通过梯度下降来更新参数的方向。 我们得到几种矩阵或参数-一种用于输入门,一种用于输出门,以及一种用于遗忘门。
因为我们获得的参数要比简单的 RNN 多,并且我们的计算图更加复杂,所以与简单的 RNN 相比,通过网络反向传播和更新权重的过程可能会花费更长的时间。 但是,尽管训练时间更长,但是我们已经证明,与传统的 RNN 相比,LSTM 具有显着的优势,因为输出门,输入门和遗忘门都结合在一起,使模型能够确定应使用输入的哪些元素。 更新隐藏状态,并且以后应该忘记隐藏状态的哪些元素,这意味着该模型能够更好地形成长期依存关系并保留先前序列步骤中的信息。
......@@ -463,7 +463,7 @@ if (step % print_every) == 0:            
torch.save(net.state_dict(), 'model.pkl')
```
在为三个时期训练了我们的模型之后,我们注意到了两个主要方面。 我们将首先从好消息开始-我们的模型正在学习一些东西! 我们的训练损失不仅下降了,而且在每个时期之后,我们在验证集上的损失也下降了。 这意味着我们的模型仅在三个时期后就可以更好地预测看不见的数据的情感! 坏消息是,我们的模型过拟合。 我们的训练损失比验证损失要低得多,这表明虽然我们的模型已经学会了如何很好地预测训练数据集,但这并不能推广到看不见的数据集。 预期会发生这种情况,因为我们使用的训练数据非常少(仅 2,400 个训练语句)。 当我们训练整个嵌入层时,很可能许多单词在训练集中只出现一次,而在验证集中却没有出现,反之亦然,这使得该模型几乎不可能归纳出其中所有不同的单词 我们的语料库。 在实践中,我们希望在更大的数据集上训练我们的模型,以使我们的模型学习如何更好地归纳。 我们还在很短的时间内训练了该模型,并且没有执行超参数调整来确定模型的最佳迭代。 随意尝试更改模型中的某些参数(例如训练时间,隐藏状态大小,嵌入大小等),以提高模型的性能。
在为三个时期训练了我们的模型之后,我们注意到了两个主要方面。 我们将首先从好消息开始-我们的模型正在学习一些东西! 我们的训练损失不仅下降了,而且在每个时期之后,我们在验证集上的损失也下降了。 这意味着我们的模型仅在三个时期后就可以更好地预测看不见的数据的情感! 坏消息是,我们的模型过拟合。 我们的训练损失比验证损失要低得多,这表明虽然我们的模型已经学会了如何很好地预测训练数据集,但这并不能推广到看不见的数据集。 预期会发生这种情况,因为我们使用的训练数据非常少(仅 2,400 个训练语句)。 当我们训练整个嵌入层时,很可能许多单词在训练集中只出现一次,而在验证集中却没有出现,反之亦然,这使得该模型几乎不可能归纳出我们的语料库中所有不同的单词。 在实践中,我们希望在更大的数据集上训练我们的模型,以使我们的模型学习如何更好地归纳。 我们还在很短的时间内训练了该模型,并且没有执行超参数调整来确定模型的最佳迭代。 随意尝试更改模型中的某些参数(例如训练时间,隐藏状态大小,嵌入大小等),以提高模型的性能。
尽管我们的模型过拟合,但它仍然学到了一些东西。 现在,我们希望在最终的测试数据集上评估我们的模型。 我们使用之前定义的测试加载器对数据执行了最后一次传递。 在此过程中,我们遍历所有测试数据并使用最终模型进行预测:
......
......@@ -109,13 +109,13 @@ CNN 背后的基本概念是卷积。 **卷积**本质上是一个滑动窗口
## 定义多类分类数据集
在上一章中,我们查看了评论的选择,并根据评论是肯定的还是负面的,学习了二分类。 对于此任务,我们将查看来自 [TREC](https://trec.nist.gov/data/qa.html) 数据集的数据,这是用于评估性能的通用数据集 模型的文本分类任务。 数据集由一系列问题组成,每个问题都属于我们训练过的模型将要学习分类的六大语义类别之一。 这六个类别如下:
在上一章中,我们查看了评论的选择,并根据评论是肯定的还是负面的,学习了二分类。 对于此任务,我们将查看来自 [TREC](https://trec.nist.gov/data/qa.html) 数据集的数据,这是用于评估文本分类任务的模型表现的通用数据集。 数据集由一系列问题组成,每个问题都属于我们训练过的模型将要学习分类的六大语义类别之一。 这六个类别如下:
![Figure 6.8 – Semantic categories in the TREC dataset ](img/B12365_06_08.jpg)
图 6.8 – TREC 数据集中的语义类别
这意味着,与我们之前的分类类不同,我们的模型输出是`0``1`之间的单个预测,我们的多类预测模型现在返回概率 六个可能类别中的每个类别。 我们假设做出的预测是针对具有最高预测的类别的:
这意味着,与我们之前的分类类不同,我们的模型输出是`0``1`之间的单个预测,我们的多类预测模型现在返回六个可能类别中的每个类别的概率。 我们假设做出的预测是针对具有最高预测的类别的:
![Figure 6.9 – Prediction values ](img/B12365_06_09.jpg)
......@@ -123,7 +123,7 @@ CNN 背后的基本概念是卷积。 **卷积**本质上是一个滑动窗口
通过这种方式,我们的模型现在将能够在多个类上执行分类任务,并且我们不再局限于我们之前看过的 0 或 1 二分类。 具有更多类的模型可能会因预测而受到影响,因为有更多不同的类可以区分。
在二元分类模型中,假设我们有一个平衡的数据集,我们希望我们的模型仅执行随机猜测就可以达到 50% 的准确率,而具有五个不同类别的多类模型只能具有 基线精度为 20%。 这意味着仅仅因为多类模型的准确度远低于 100%,并不意味着模型本身固有地在做出预测方面就很糟糕。 当涉及从数百个不同类别进行预测的训练模型时,尤其如此。 在这些情况下,仅具有 50% 准确率的模型将被认为表现良好。
在二元分类模型中,假设我们有一个平衡的数据集,我们希望我们的模型仅执行随机猜测就可以达到 50% 的准确率,而具有五个不同类别的多类模型只能具有基线精度 20%。 这意味着仅仅因为多类模型的准确度远低于 100%,并不意味着模型本身固有地在做出预测方面就很糟糕。 当涉及从数百个不同类别进行预测的训练模型时,尤其如此。 在这些情况下,仅具有 50% 准确率的模型将被认为表现良好。
现在我们已经定义了多类分类问题,我们需要加载数据以训练模型。
......@@ -394,7 +394,7 @@ def multi_accuracy(preds, y):
在这里,对于我们的预测,我们的模型使用`torch.max`函数对所有预测返回具有最高预测值的索引。 对于这些预测中的每一个,如果此预测索引与标签的索引相同,则将其视为正确的预测。 然后,我们对所有这些正确的预测进行计数,然后将它们除以预测的总数,以得出多类准确率的度量。 我们可以在训练循环中使用此功能来测量每个时期的准确率。
接下来,我们定义训练函数。 最初,我们将时间段的损失和准确率设置为`0`,我们将其称为`model.train()`以允许我们在训练模型时更新模型中的参数 模型
接下来,我们定义训练函数。 最初,我们将时间段的损失和准确率设置为`0`,我们将其称为`model.train()`以允许我们在训练模型时更新模型中的参数:
```py
def train(model, iterator, optimizer, criterion):
......
......@@ -51,7 +51,7 @@ I will be traveling to Paris, the capital city of France, on the 2nd of March. M
我们可以在网络中通过实现的两种注意形式与非常相似,但存在细微的关键区别。 我们将从关注本地开始。
**局部注意力**中,我们的模型仅查看编码器的一些隐藏状态。 例如,如果我们正在执行句子翻译任务,并且我们正在计算翻译中的第二个单词,则模型可能希望仅查看与输入中第二个单词相关的编码器的隐藏状态 句子。 这意味着我们的模型需要查看编码器的第二个隐藏状态(`h2`),但也可能需要查看它之前的隐藏状态(`h1`)。
**局部注意力**中,我们的模型仅查看编码器的一些隐藏状态。 例如,如果我们正在执行句子翻译任务,并且我们正在计算翻译中的第二个单词,则模型可能希望仅查看与输入句子中第二个单词相关的编码器的隐藏状态。 这意味着我们的模型需要查看编码器的第二个隐藏状态(`h2`),但也可能需要查看它之前的隐藏状态(`h1`)。
在下图中,我们可以在实践中看到这一点:
......@@ -61,7 +61,7 @@ I will be traveling to Paris, the capital city of France, on the 2nd of March. M
我们首先从最终隐藏状态`h[n]`计算对齐位置`p[t]`。 这告诉我们需要进行观察才能发现哪些隐藏状态。 然后,我们计算局部权重并将其应用于隐藏状态,以确定上下文向量。 这些权重可能告诉我们,更多地关注最相关的隐藏状态(`h2`),而较少关注先前的隐藏状态(`h1`)。
然后,我们获取上下文向量,并将其转发给解码器以进行预测。 在我们基于非注意力的序列到序列模型中,我们只会向前传递最终的隐藏状态`h[n]`,但在这里我们看到的是,我们仅考虑了我们的相关隐藏状态 模型认为做出预测是必要的。
然后,我们获取上下文向量,并将其转发给解码器以进行预测。 在我们基于非注意力的序列到序列模型中,我们只会向前传递最终的隐藏状态`h[n]`,但在这里我们看到的是,我们仅考虑了我们的相关隐藏状态,模型认为它对于做出预测是必要的。
**全局注意力**模型的运作方式与非常相似。 但是,我们不仅要查看所有隐藏状态,还希望查看模型的所有隐藏状态,因此命名为全局。 我们可以在此处看到全局注意力层的图形化图示:
......@@ -171,7 +171,7 @@ for line in lines[:3]:
        self.addWord(word)
```
我们可以做的加快模型训练的一件事是减少词汇量。 这意味着任何嵌入层都将更小,并且模型中学习的参数总数会更少。 一种简单的方法是从我们的词汇表中删除所有低频词。 在我们的数据集中仅出现一次或两次的任何单词都不太可能具有巨大的预测能力,因此在最终模型中将它们从语料库中删除并替换为空白标记可以减少我们训练模型所需的时间并减少过拟合而无需 对我们模型的预测有很大的负面影响。
我们可以做的加快模型训练的一件事是减少词汇量。 这意味着任何嵌入层都将更小,并且模型中学习的参数总数会更少。 一种简单的方法是从我们的词汇表中删除所有低频词。 在我们的数据集中仅出现一次或两次的任何单词都不太可能具有巨大的预测能力,因此在最终模型中将它们从语料库中删除并替换为空白标记可以减少我们训练模型所需的时间并减少过拟合,而不会对我们模型的预测有很大的负面影响。
4. 为了从词汇中删除低频词,我们可以实现一个`trim`函数。该函数首先循环浏览单词计数词典,如果该单词的出现次数大于所需的最小计数,则将其追加到一个新的列表中。
......
......@@ -23,7 +23,7 @@
## BERT
**BERT** 代表**转换器**的双向编码器表示形式,由 Google 于 2018 年开发,被广泛认为是 NLP 领域的领先模型,在自然语言中已取得领先的性能 语言推理和问答任务。 幸运的是,它已作为开源模型发布,因此可以下载并用于您自己的 NLP 任务。
**BERT** 代表**转换器**的双向编码器表示形式,由 Google 于 2018 年开发,被广泛认为是 NLP 领域的领先模型,在自然语言的语言推理和问答任务中已取得领先的性能。 幸运的是,它已作为开源模型发布,因此可以下载并用于您自己的 NLP 任务。
BERT 是作为预训练的模型发布的,这意味着用户可以下载和实现 BERT,而无需每次都从头开始重新训练模型。 预先训练的模型在几个语料库上进行了训练,包括整个 Wikipedia(由 25 亿个单词组成)和另一个图书集(其中还包括 8 亿个单词)。 但是,BERT 与其他类似模型不同的主要因素是它提供了一种深度,双向,无监督的语言表示形式,该语言表示形式提供了更复杂,更详细的表示形式,从而提高了 NLP 任务的性能。 。
......@@ -138,7 +138,7 @@ BERT 是按照**转换器**的原理构建的,现在将对其进行详细说
自我关注可以说是编码器中最复杂的部分,因此我们将首先对其进行更详细的研究。 假设我们有一个由三个单词组成的输入句子; 例如`fine`。 对于此句子中的每个单词,我们将它们表示为从模型的嵌入层获得的单个单词向量。 然后,我们从此单个单词向量中提取三个向量:查询向量,键向量和值向量。 这三个向量是通过将词向量乘以训练模型时获得的三个不同权重矩阵而获得的。
如果我们在输入句子`Ethis``Eis``Efine`中为每个单词调用单词嵌入,则可以计算查询,键和值向量 像这样:
如果我们在输入句子`Ethis``Eis``Efine`中为每个单词调用单词嵌入,则可以计算查询,键和值向量像这样:
**查询向量**
......@@ -172,7 +172,7 @@ BERT 是按照**转换器**的原理构建的,现在将对其进行详细说
既然我们知道了如何计算每个向量,那么了解每个向量代表什么就很重要。 从本质上讲,每一个都是注意力机制内概念的抽象。 一旦我们看到它们是如何计算的,这将变得显而易见。
让我们继续我们的工作示例。 我们需要依次考虑输入句子中的每个单词。 为此,我们为句子中的每对查询/关键字向量计算得分。 这是通过获取输入句子中每个单词的每个查询/关键字向量对的点积来完成的。 例如,要计算句子中第一个单词`this`的分数,我们计算`this`的查询向量与位置 0 处的键向量之间的点积。我们在所有其他位置的键向量中重复此点积 输入句子中的位置,因此我们获得输入句子中第一个单词的`n`分,其中`n`是句子的长度:
让我们继续我们的工作示例。 我们需要依次考虑输入句子中的每个单词。 为此,我们为句子中的每对查询/关键字向量计算得分。 这是通过获取输入句子中每个单词的每个查询/关键字向量对的点积来完成的。 例如,要计算句子中第一个单词`this`的分数,我们计算`this`的查询向量与位置 0 处的键向量之间的点积。我们在输入句子中的所有其他位置对键向量重复它,因此我们获得输入句子中第一个单词的`n`分,其中`n`是句子的长度:
**分数(`"this"`)**
......@@ -214,7 +214,7 @@ E0 = Embedding with Time Signal
x0 + t0 = E0
```
我们的模型为每个位置学习不同的位置编码向量(`t0``t1`,依此类推),然后我们将应用于输入句子中的每个单词,然后再输入 甚至输入我们的编码器
我们的模型为每个位置学习不同的位置编码向量(`t0``t1`,依此类推),然后在它们进入编码器之前,我们将它应用于输入句子中的每个单词
![Figure 9.8 – Adding input to the encoder ](img/B12365_09_8.jpg)
......@@ -372,7 +372,7 @@ Chef - A chef is an entity
Dinner - Dinner is an object/thing
```
但是,名词短语略有不同,因为每个名词短语都应指一个单独的实体。 在前面的句子中,即使`Jeff``Cook`都是名词,短语`Jeff Cook`都指一个人,因此可以将其视为名词 短语。 但是,如何从语法上确定名词短语是指单个实体? 一种简单的方法是将短语置于动词之前,看看该句子是否具有句法意义。 如果确实如此,那么该短语就是名词短语:
但是,名词短语略有不同,因为每个名词短语都应指一个单独的实体。 在前面的句子中,即使`Jeff``Cook`都是名词,短语`Jeff Cook`都指一个人,因此可以将其视为名词短语。 但是,如何从语法上确定名词短语是指单个实体? 一种简单的方法是将短语置于动词之前,看看该句子是否具有句法意义。 如果确实如此,那么该短语就是名词短语:
```py
Jeff the chef cooks
......@@ -438,7 +438,7 @@ Jeff the chef drinks…
![](img/B12365_09_Table_01.jpg)
通过执行语义角色标记,我们可以为句子的每个部分分配特定的角色。 这在 NLP 中非常有用,因为它允许模型更好地“理解”一个句子,因此而不是仅作为角色分类的句子,应理解为语义角色的组合,可以更好地传达 实际上是在句子描述的情况下发生的
通过执行语义角色标记,我们可以为句子的每个部分分配特定的角色。 这在 NLP 中非常有用,因为它允许模型更好地“理解”一个句子,因此而不是仅作为角色分类的句子,应理解为语义角色的组合,可以更好地传达,在句子所描述的事件中发生了什么
当我们阅读句子`The boy kicked the ball`时,我们固有地知道有一个男孩,有一个球,并且那个男孩正在踢球。 但是,到目前为止,我们所研究的所有 NLP 模型都可以通过查看句子中的各个单词并为其创建一些表示来理解该句子。 到目前为止,我们所看到的系统不可能理解存在两个“事物”并且一个物体(男孩)对第二物体(球)执行某种动作(踢)的事实。 在模型中引入语义角色元素可以更好地帮助我们的系统通过定义句子的主题及其之间的相互作用来形成更现实的句子表示形式。
......
......@@ -73,7 +73,7 @@ import numpy
# 在 PyTorch 中创建张量
首先让我们了解张量是什么。 **标量**是单个独立值,一维值数组称为**向量**,二维值数组称为**矩阵**,并且任何 大于 2D 的值简称为**张量**。 张量是一个广义的术语,包含标量,向量和矩阵。
首先让我们了解张量是什么。 **标量**是单个独立值,一维值数组称为**向量**,二维值数组称为**矩阵**,并且任何大于 2D 的值简称为**张量**。 张量是一个广义的术语,包含标量,向量和矩阵。
标量是 0 阶张量,向量是 1 阶张量,矩阵是 2 阶张量。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册