Gensim - 向量和模型

在这里,我们将学习 Gensim 的核心概念,主要关注向量和模型。

什么是向量?

如果我们想推断语料库中的潜在结构怎么办?为此,我们需要以一种可以数学操作的方式来表示文档。一种流行的表示方法是将语料库的每个文档表示为特征向量。这就是为什么我们可以说向量是文档的数学便捷表示。

举个例子,让我们将上面使用的语料库中的一个特征表示为 Q-A 对 −

Q − 单词 Hello 在文档中出现了多少次?

A −零 (0)。

Q − 文档中有多少个段落?

A − 二 (2)

问题通常用其整数 id 表示,因此该文档的表示是一系列对,如 (1, 0.0)、(2, 2.0)。这种向量表示被称为 密集 向量。为什么是 密集,因为它包含对上述所有问题的明确答案。

如果我们事先知道所有问题,表示可以很简单,如 (0, 2)。这样的答案序列(当然,如果事先知道问题)就是我们文档的 向量

另一种流行的表示是 词袋 (BoW) 模型。在这种方法中,每个文档基本上都由一个向量表示,该向量包含字典中每个单词的频率计数。

举个例子,假设我们有一本字典,其中包含单词 ['Hello', 'How', 'are', 'you']。那么由字符串"How are you how"组成的文档将由向量 [0, 2, 1, 1] 表示。这里,向量的条目按"Hello"、"How"、"are"和"you"出现的顺序排列。

向量与文档

从上面对向量的解释中,文档和向量之间的区别几乎可以理解。但是,为了更清楚起见,文档是文本,而向量是该文本的数学上方便的表示。不幸的是,有时许多人会互换使用这些术语。

例如,假设我们有一个任意的文档 A,那么他们不会说"与文档 A 对应的向量",而是说"向量 A"或"文档 A"。这会导致很大的歧义。这里要注意的还有一件重要的事情是,两个不同的文档可能具有相同的向量表示。

将语料库转换为向量列表

在介绍将语料库转换为向量列表的实现示例之前,我们需要将语料库中的每个单词与一个唯一的整数 ID 相关联。为此,我们将扩展上一章中的示例。

示例

from gensim import corpora
dictionary = corpora.Dictionary(processed_corpus)
print(dictionary)

输出

Dictionary(25 unique tokens: ['computer', 'opinion', 'response', 'survey', 'system']...)

它表明在我们的语料库中,这个gensim.corpora.Dictionary中有 25 个不同的标记。

实施示例

我们可以使用字典将标记化的文档转换为这些 5 维向量,如下所示 −

pprint.pprint(dictionary.token2id)

输出

{
   'binary': 11,
   'computer': 0,
   'error': 7,
   'generation': 12,
   'graph': 16,
   'intersection': 17,
   'iv': 19,
   'measurement': 8,
   'minors': 20,
   'opinion': 1,
   'ordering': 21,
   'paths': 18,
   'perceived': 9,
   'quasi': 22,
   'random': 13,
   'relation': 10,
   'response': 2,
   'survey': 3,
   'system': 4,
   'time': 5,
   'trees': 14,
   'unordered': 15,
   'user': 6,
   'well': 23,
   'widths': 24
}

类似地,我们可以为文档创建词袋表示,如下所示 −

BoW_corpus = [dictionary.doc2bow(text) for text in processed_corpus]
pprint.pprint(BoW_corpus)

输出

[
   [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)],
   [(2, 1), (5, 1), (6, 1), (7, 1), (8, 1), (9, 1), (10, 1)],
   [(11, 1), (12, 1), (13, 1), (14, 1), (15, 1)],
   [(14, 1), (16, 1), (17, 1), (18, 1)],
   [(14, 1), (16, 1), (19, 1), (20, 1), (21, 1), (22, 1), (23, 1), (24, 1)]
]

什么是模型?

一旦我们将语料库矢量化,下一步做什么?现在,我们可以使用模型对其进行转换。模型可以称为用于将一种文档表示转换为另一种文档表示的算法。

正如我们所讨论的,在 Gensim 中,文档表示为向量,因此,我们可以将模型视为两个向量空间之间的转换。总是有一个训练阶段,模型会学习此类转换的细节。模型在训练阶段读取训练语料库。

初始化模型

让我们初始化 tf-idf 模型。该模型将向量从 BoW(词袋)表示转换为另一个向量空间,其中频率计数根据语料库中每个单词的相对稀有性进行加权。

实施示例

在下面的例子中,我们将初始化 tf-idf 模型。我们将在语料库上对其进行训练,然后转换字符串"trees graph"。

示例

from gensim import models
tfidf = models.TfidfModel(BoW_corpus)
words = "trees graph".lower().split()
print(tfidf[dictionary.doc2bow(words)])

输出

[(3, 0.4869354917707381), (4, 0.8734379353188121)]

现在,一旦我们创建了模型,我们就可以通过 tfidf 转换整个语料库并对其进行索引,并查询我们的查询文档的相似性(我们给出查询文档'trees system')针对语料库中的每个文档 −

示例

from gensim import similarities
index = similarities.SparseMatrixSimilarity(tfidf[BoW_corpus],num_features=5)
query_document = 'trees system'.split()
query_bow = dictionary.doc2bow(query_document)
simils = index[tfidf[query_bow]]
print(list(enumerate(simils)))

输出

[(0, 0.0), (1, 0.0), (2, 1.0), (3, 0.4869355), (4, 0.4869355)]

从上面的输出来看,文档 4 和文档 5 的相似度得分约为 49%。

此外,我们还可以按如下方式对该输出进行排序以提高可读性 −

示例

for doc_number, score in sorted(enumerate(sims), key=lambda x: x[1], reverse=True):
   print(doc_number, score)

输出

2 1.0
3 0.4869355
4 0.4869355
0 0.0
1 0.0