基于深度学习的自然语言处理
上QQ阅读APP看书,第一时间看更新

1.5 词嵌入

正如本章前面部分所述,自然语言处理为机器学习模型和深度学习模型准备了文本数据。当提供数值数据作为输入时,模型执行效率最高,因此自然语言处理的关键作用是将预处理的文本数据转换为数值数据,数值数据是文本数据的数字表示。

这就是词嵌入的含义:它们是文本实值向量形式的数值表示。具有相似含义的词映射到相似的向量,因此具有相似的表示。这有助于机器学习不同单词的含义和背景。由于词嵌入是映射到单个单词的向量,因此只有在语料库上执行了标记化后才能生成词嵌入。词嵌入的示例如图1-17所示。

图1-17 词嵌入示例

词嵌入包含多种用于创建学习的数值表示的技术,是表示文档词汇的最流行方式。词嵌入的好处在于,它们能够捕捉上下文、语义和句法的相似性,以及单词与其他单词的关系,从而有效地训练机器理解自然语言。这是词嵌入的主要目的——形成与具有相似含义的单词相对应的相似向量簇。

使用词嵌入是为了让机器像我们一样理解同义词。以一个在线餐馆评论为例。它们由描述食物、氛围和整体体验的形容词组成。它们要么是正面的,要么是负面的,理解哪些评论属于这两类中的哪一类是重要的。这些评论的自动分类可以让餐馆管理人员快速了解他们需要改进哪些方面,人们喜欢他们餐馆的哪些方面,等等。

有各种各样的形容词可以归类为正面的,负面的形容词也是如此。因此,机器不仅需要能够区分否定和肯定,还需要学习和理解多个单词可以与同一个类别相关,因为它们最终意味着相同的东西。这就是词嵌入的意义所在。

以餐饮服务申请中收到的餐馆评论为例。以下两句话来自两个不同的餐馆评论:

❏Sentence A–The food here was great.

❏Sentence B–The food here was good.

(句子A——这里的食物很棒。

句子B——这里的食物很好。)

机器需要能够理解这两个评论都是正面的,意思是相似的,尽管两个句子中的形容词不同。这是通过创建词嵌入来实现的,因为“good”和“great”两个词映射到两个独立但相似的实值向量,因此可以聚集在一起。

词嵌入的生成

我们已经理解了什么是词嵌入及其重要性,现在需要了解它们是如何产生的。将单词转换成其实值向量的过程称为矢量化,是通过词嵌入技术完成的。有许多可用的词嵌入技术,但是在本章中,我们将讨论两个主要的技术——Word2Vec和GloVe。一旦词嵌入(矢量)被创建,它们组合形成一个矢量空间,这是一个由遵循矢量加法和标量乘法规则的矢量组成的代数模型。如果你不记得你的线性代数,这可能是一个快速复习的好时机。

1.Word2Vec

如前所述,Word2Vec是用于从单词生成向量的词嵌入技术之一。这一点你可能从名字本身就能理解。

Word2Vec是一个浅层神经网络,只有两层,因此不具备深度学习模型的资格。输入是一个文本语料库,它用来生成矢量作为输出。这些向量被称为输入语料库中单词的特征向量。它将语料库转换成可以被深层神经网络理解的数值数据。

Word2Vec的目的是理解两个或更多单词一起出现的概率,从而将具有相似含义的单词组合在一起,在向量空间中形成一个聚类。像任何其他机器学习或深度学习模型一样,通过从过去的数据和过去出现的单词中学习,Word2Vec变得越来越有效。因此,如果有足够的数据和上下文,它可以根据过去的事件和上下文准确地猜测一个单词的意思,就像我们理解语言的方式一样。

例如,一旦我们听说并阅读了“男孩”和“男人”以及“女孩”和“女人”这几个词,并理解了它们的含义,我们就能够在它们之间建立联系。同样,Word2Vec也可以形成这种连接,并为这些单词生成向量,这些单词在同一个簇中紧密地放在一起,以确保机器知道这些单词意味着类似的事情。

一旦给了Word2Vec一个语料库,它就会产生一个词汇,其中每个单词都有一个自己的向量,这就是所谓的神经词嵌入,简单地说,这个神经词嵌入是一个用数字写的单词。

Word2Vec的功能

Word2Vec针对与输入语料库中的单词相邻的单词训练单词,有两种方法:

连续单词袋(CBOW)

该方法基于上下文预测当前单词。因此,它将单词的周围单词作为输入来产生单词作为输出,并且它基于这个单词确实是句子的一部分的概率来选择这个单词。

例如,如图1-18所示,如果算法被提供了单词“the food was”并且需要预测它后面的形容词,它最有可能输出单词“good”而不是输出单词“delightful”,因为将会有更多的例子使用单词“good”,并且因此它已经知道“good”比“delightful”具有更高的概率。CBOW比skip-gram更快,并且使用更频繁的单词具有更高的准确性。

图1-18 连续词袋算法

Skip-gram

这种方法通过将单词作为输入,理解单词的意思,并将其分配给上下文来预测单词周围的单词。例如,如图1-19所示,如果算法被赋予“delightful”这个词,它就必须理解它的意思,并从过去的上下文中学习来预测周围的词是“the food was”的概率是最高的。Skip-gram在小语料库中效果最好。

图1-19 skip-gram算法

虽然这两种方法似乎以相反的方式工作,但它们本质上是基于本地(附近)单词的上下文来预测单词。它们使用上下文窗口来预测下一个单词。这个窗口是可配置的参数。

选择使用哪种算法取决于手头的语料库。CBOW基于概率工作,因此选择在特定上下文中出现概率最高的单词。这意味着它通常只预测常见和频繁的单词,因为这些单词具有最高的概率,而罕见和不频繁的单词永远不会由CBOW产生。另一方面,Skip-gram预测上下文,因此当给定一个单词时,它将把它作为一个新的观察,而不是把它与一个具有相似含义的现有单词进行比较。正因为如此,罕见的词语将不会被避免或忽略。然而,这也意味着skip-gram需要大量的训练数据才能有效工作。因此,应该根据手头的训练数据和语料库,来决定使用哪种算法。

从本质上说,这两种算法以及整个模型,都需要一个高强度的学习阶段,在这个阶段,它们要经过成千上万个单词的训练,才能更好地理解上下文和含义。基于此,它们能够给单词分配向量,从而帮助机器学习和预测自然语言。为了更好地理解Word2Vec,让我们使用Gensim的Word2Vec模型做一个练习。

Gensim是一个开源库,用于无监督主题建模和使用统计机器学习的自然语言处理。Gensim的Word2Vec算法以单个单词(标记)的形式输入句子序列。

此外,我们可以使用min_count参数。它会问你一个单词在语料库中应该有多少个实例,以使它对你来说很重要,然后在生成词嵌入时会考虑到这一点。在现实生活中,当处理数百万个单词时,一个只出现一两次的单词可能根本不重要,因此可以忽略。然而,现在,我们只在三个句子上训练模型,每个句子只有5-6个单词。因此,min_count设置为1,因为一个词对我们也很重要,即使它只出现一次。

练习8:使用Word2Vec生成词嵌入

在本练习中,我们将使用Gensim的Word2Vec算法在标记化后生成词嵌入。

注意:在以下练习中,你需要在系统上安装gensim。如果尚未安装,可以使用以下命令安装:

欲了解更多信息,请访问https://radimrehurek.com/gensim/models/word2vec.html

以下步骤将帮助你解决问题:

1)打开一个新的Jupyter notebook。

2)从gensim导入Word2Vec模型,并从nltk导入word_tokenize,如下所示:

3)将包含一些常用单词的三个字符串存储到三个独立的变量中,然后标记每个句子,并将所有标记存储在一个数组中,如下所示:

4)训练模型:

Word2Vec的min_count默认值为5。

5)总结模型,如下所示:

输出将如图1-20所示。

图1-20 模型概要的输出

Vocab=12表示输入模型的句子中有12个不同的单词。

6)让我们通过总结来找出词汇中有哪些单词,如下所示:

输出将如图1-21所示。

图1-21 语料库词汇的输出

让我们看看‘singer’这个词的向量(词嵌入)是什么:

预期输出如图1-22所示。

图1-22 “singer”一词的向量

我们的Word2Vec模型已经在这三个句子上训练过了,因此它的词汇只包括这个句子中的单词。如果我们从Word2Vec模型中找到与特定输入单词相似的单词,则找不到真正有意义的单词,因为词汇量太小了。考虑以下示例:

“positive”是指在输出中只描述正矢量值。

与“great”相似的前6个词如图1-23所示。

图1-23 与单词“great”相似的单词向量

同样,对于“singer”一词,可以如下所示:

与“singer”相似的前6个词如图1-24所示。

图1-24 与单词“singer”相似的单词向量

我们知道这些词实际上与输入的词在意义上根本不相似,这也显示在它们旁边的相关值中。然而,它们出现是因为这些是词汇中唯一存在的单词。

Gensim Word2Vec模型的另一个重要参数是尺寸参数。它的默认值是100,表示用于训练模型的神经网络层的大小。这相当于训练算法的自由度。更大的尺寸需要更多的数据,但也会达到更高的精度。

注意 如需了解更多关于Gensim的Word2Vec模型的信息,请访问https://rare-technologies.com/word2vec-tutorial/

2.GloVe

GloVe是“全局向量(global vector)”的缩写,是斯坦福开发的一种词嵌入技术。这是一个无监督的学习算法,建立在Word2Vec的基础上。虽然Word2Vec在生成词嵌入方面相当成功,但它的问题是它有一个小窗口,通过这个窗口它可以聚焦于本地单词和局部上下文来预测单词。这意味着它无法从全局,即整个语料库中出现的词的频率中学习。GloVe,顾名思义,可以查看语料库中的所有单词。

Word2Vec是一种预测模型,学习向量来提高预测能力,而GloVe是一种基于计数的模型。这意味着GloVe通过对共现计数矩阵(co-occurrence counts matrix)进行降维来学习向量。GloVe能够建立的联系是这样的:

king–man+woman=queen

(国王-男人+女人=王后)

这意味着它能够理解“king”和“queen”之间的关系类似于“man”和“woman”之间的关系。

这些是复杂的术语,让我们一个接一个地理解它们。所有这些概念都来自统计学和线性代数,所以如果你已经知道怎么回事,可以跳出这个活动!

在处理语料库时,存在基于词频构造矩阵的算法。基本上,这些矩阵包含以行的形式出现在文档中的单词,而列则是段落或单独的文档。矩阵的元素代表单词在文档中出现的频率。自然,有了一个大语料库,这个矩阵将是巨大的。处理如此大的矩阵将花费大量的时间和内存,因此我们执行降维。这是减小矩阵尺寸的过程,因此可以对其执行进一步的操作。

在GloVe的例子中,矩阵被称为共现计数矩阵,它包含一个单词在语料库的特定上下文中出现了多少次的信息。行是单词,列是上下文。这个矩阵然后被分解以减少维数,且新矩阵对于每个单词以一个向量表示。

GloVe也有附带向量的预处理词,如果语义匹配语料库和手头的任务,就可以使用这些词。下面的活动将引导你完成在Python中实现GloVe的过程,代码不是直接提供的,所以你需要做一些思考,也许还要进行一些谷歌搜索。试试看。

练习9:使用GloVe生成词嵌入

在本练习中,我们使用GloVe-Python生成词嵌入。

注意 要在平台上安装GloVe-Python,请访问https://pypi.org/project/glove/#files

http://mattmahoney.net/dc/text8.zip.下载Text8Corpus。

提取文件并将其保存在Jupyter notebook中。

1)导入itertools:

2)我们需要一个语料库来生成词嵌入,幸运的是,gensim.models.word2vec库有一个名为Text8Corpus的语料库。将它与GloVe-Python库中的两个模块一起导入:

3)使用itertools将语料库转换成列表形式的句子:

4)启动Corpus()模型,并将其应用于句子:

window参数控制有多少相邻单词被考虑。

5)我们已经准备好了语料库,需要训练嵌入。启动GloVe()模型:

6)基于语料库生成共现计数矩阵,并将gloVe模型与该矩阵相匹配:

模型已训练好了!

7)添加语料库的词典:

8)根据生成的词嵌入,使用以下命令查看哪些单词与你选择的单词相似:

预期输出如图1-25所示。

图1-25 “man”的词嵌入输出

你可以试着用几个不同的词来看看哪些词与它们相邻,哪些词与它们最相似:

预期输出如图1-26所示。

图1-26 “queen”的词嵌入输出

注意 要了解更多关于GloVe的知识,可访问https://nlp.stanford.edu/projects/glove/

活动1:使用Word2Vec从语料库中生成词嵌入

你被赋予了在一个特定的语料库上训练一个Word2Vec模型的任务(在这个例子中是Text8Corpus),以此来确定哪些单词彼此相似。以下步骤将帮助你解决问题。

注意 你可以在http://mattmahoney.net/dc/text8.zip.找到文本语料库文件。

1)从前面给出的链接上传文本语料库。

2)从gensim模型导入word2vec。

3)将语料库存储在变量中。

4)在语料库上匹配word2vec模型。

5)找到与“man”最相似的词。

6)“father”对应“girl”,“x”对应“boy”。找出“x”的前三个单词。

注意 该活动的解决方案参见附录。

预期输出如图1-27所示。

图1-27 相似词嵌入的输出

“x”的前三个词可能如图1-28所示。

图1-28 “x”前三个单词的输出