【自然语言处理】Gensim核心概念

Gensim核心概念

1.Document:文档

在 Gensim 中,文档是文本序列类型的对象(在 Python 3 中通常称为 str)。文档可以是 140 个字符的简短推文、单个段落(即期刊文章摘要)、新闻文章或书籍。

2.Corpus:语料库

语料库是文档对象的集合。语料库在 Gensim 中主要有两个作用:

  • 作为训练模型的输入。在训练期间,模型使用这个训练语料库来寻找共同的主题,初始化它们的内部模型参数。
  • 组织文件。训练后,主题模型可用于从新文档(训练语料库中未出现的文档)中提取主题。这样的语料库可以为相似性查询建立索引,通过语义相似性查询,聚类等。
text_corpus = [
    "Human machine interface for lab abc computer applications",
    "A survey of user opinion of computer system response time",
    "The EPS user interface management system",
    "System and human system engineering testing of EPS",
    "Relation of user perceived response time to error measurement",
    "The generation of random binary unordered trees",
    "The intersection graph of paths in trees",
    "Graph minors IV Widths of trees and well quasi ordering",
    "Graph minors A survey",
]
# Create a set of frequent words
stoplist = set('for a of the and to in'.split(' '))
# Lowercase each document, split it by white space and filter out stopwords
texts = [[word for word in document.lower().split() if word not in stoplist]
         for document in text_corpus]

# Count word frequencies
from collections import defaultdict
frequency = defaultdict(int)
for text in texts:
    for token in text:
        frequency[token] += 1

# Only keep words that appear more than once
processed_corpus = [[token for token in text if frequency[token] > 1] for text in texts]
pprint.pprint(processed_corpus)
[['human', 'interface', 'computer'],
 ['survey', 'user', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'system'],
 ['system', 'human', 'system', 'eps'],
 ['user', 'response', 'time'],
 ['trees'],
 ['graph', 'trees'],
 ['graph', 'minors', 'trees'],
 ['graph', 'minors', 'survey']]

在继续之前,我们希望将语料库中的每个单词与一个唯一的整数 ID 相关联。我们可以使用 gensim.corpora.Dictionary 类来做到这一点。这本词典定义了我们的处理过程所知道的所有单词的词汇表。

from gensim import corpora

dictionary = corpora.Dictionary(processed_corpus)
print(dictionary)
Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...)

因为我们的语料库很小,所以在这个 gensim.corpora.Dictionary 中只有 12 个不同的标记。对于较大的语料库,包含数十万个标记的词典是很常见的。

3.Vector:向量

为了推断我们语料库中的潜在结构,我们需要一种方法来表示我们可以数学操作的文档。一种方法是将每个文档表示为特征向量。另一种将文档表示为向量的方法是词袋模型。在词袋模型下,每个文档都由一个向量表示,该向量包含字典中每个单词的频率计数。

我们处理后的语料库中有 12 个独特的词,这意味着每个文档在词袋模型下将由一个 12 维向量表示。我们可以使用字典将标记化文档转换为这些 12 维向量。我们可以看到这些 ID 对应的是什么:

print(dictionary.token2id)
{'computer': 0,
 'eps': 8,
 'graph': 10,
 'human': 1,
 'interface': 2,
 'minors': 11,
 'response': 3,
 'survey': 4,
 'system': 5,
 'time': 6,
 'trees': 9,
 'user': 7}

我们可以使用字典的 doc2bow 方法为文档创建词袋表示,它返回字数的稀疏表示。将整个原始语料库转换为向量列表:

bow_corpus = [dictionary.doc2bow(text) for text in processed_corpus]
print(bow_corpus)

[[(0, 1), (1, 1), (2, 1)],
 [(0, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)],
 [(2, 1), (5, 1), (7, 1), (8, 1)],
 [(1, 1), (5, 2), (8, 1)],
 [(3, 1), (6, 1), (7, 1)],
 [(9, 1)],
 [(9, 1), (10, 1)],
 [(9, 1), (10, 1), (11, 1)],
 [(4, 1), (10, 1), (11, 1)]]

每个元组中的第一个条目对应于字典中令牌的 ID,第二个对应于该令牌的计数。此向量仅包含文档中实际出现的单词的条目。

4.Model:模型

现在我们已经矢量化了我们的语料库,我们可以开始使用模型对其进行转换。我们使用模型作为一个抽象术语,指的是从一种文档表示到另一种文档表示的转换。在 gensim 中,文档表示为向量,因此可以将模型视为两个向量空间之间的转换。当模型读取训练语料库时,它会在训练期间学习这种转换的细节。

模型的一个简单示例是 TF-IDF。TF-IDF 模型将向量从词袋表示形式转换为向量空间,其中频率计数根据语料库中每个词的相对稀有度进行加权。

from gensim import models

# train the model
tfidf = models.TfidfModel(bow_corpus)

# transform the "system minors" string
words = "system minors".lower().split()
print(tfidf[dictionary.doc2bow(words)])
[(5, 0.5898341626740045), (11, 0.8075244024440723)]

TF-IDF 模型再次返回一个元组列表,其中第一个条目是令牌 ID,第二个条目是 TF-IDF 权重。请注意,与 “system” 对应的 ID(在原始语料库中出现了 4 次)的权重低于与 “minors” 对应的 ID(仅出现两次)。

或者将转换应用于整个语料库:

corpus_tfidf = tfidf[bow_corpus]
for doc in corpus_tfidf:
    print(doc)
[(0, 0.5773502691896257), (1, 0.5773502691896257), (2, 0.5773502691896257)]
[(0, 0.44424552527467476), (3, 0.44424552527467476), (4, 0.44424552527467476), (5, 0.3244870206138555), (6, 0.44424552527467476), (7, 0.3244870206138555)]
[(2, 0.5710059809418182), (5, 0.4170757362022777), (7, 0.4170757362022777), (8, 0.5710059809418182)]
[(1, 0.49182558987264147), (5, 0.7184811607083769), (8, 0.49182558987264147)]
[(3, 0.6282580468670046), (6, 0.6282580468670046), (7, 0.45889394536615247)]
[(9, 1.0)]
[(9, 0.7071067811865475), (10, 0.7071067811865475)]
[(9, 0.5080429008916749), (10, 0.5080429008916749), (11, 0.695546419520037)]
[(4, 0.6282580468670046), (10, 0.45889394536615247), (11, 0.6282580468670046)]

转换也可以序列化,一个在另一个之上,在一种链中:

lsi_model = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=2)  # initialize an LSI transformation
corpus_lsi = lsi_model[corpus_tfidf]  # create a double wrapper over the original corpus: bow->tfidf->fold-in-lsi

这里,我们通过潜在语义索引将我们的 TF-IDF 语料库转换为潜在的二维空间(2-D,因为我们设置了 num_topics=2)。现在你可能想知道:这两个潜在维度代表什么?让我们用 models.LsiModel.print_topics() 检查一下:

lsi_model.print_topics(2)
2022-07-18 19:59:39,298 : INFO : topic #0(1.594): 0.703*"trees" + 0.538*"graph" + 0.402*"minors" + 0.187*"survey" + 0.061*"system" + 0.060*"time" + 0.060*"response" + 0.058*"user" + 0.049*"computer" + 0.035*"interface"
2022-07-18 19:59:39,298 : INFO : topic #1(1.476): -0.460*"system" + -0.373*"user" + -0.332*"eps" + -0.328*"interface" + -0.320*"time" + -0.320*"response" + -0.293*"computer" + -0.280*"human" + -0.171*"survey" + 0.161*"trees"

[(0, '0.703*"trees" + 0.538*"graph" + 0.402*"minors" + 0.187*"survey" + 0.061*"system" + 0.060*"time" + 0.060*"response" + 0.058*"user" + 0.049*"computer" + 0.035*"interface"'), 
 (1, '-0.460*"system" + -0.373*"user" + -0.332*"eps" + -0.328*"interface" + -0.320*"time" + -0.320*"response" + -0.293*"computer" + -0.280*"human" + -0.171*"survey" + 0.161*"trees"')]

看起来,根据 LSI,“trees”、“graph” 和 “minors” 都是相关词(并且对第一个主题的方向贡献最大),而第二个主题实际上与所有其他词相关。正如预期的那样,前五个文档与第二个主题更密切相关,而其余四个文档与第一个主题相关:

# both bow->tfidf and tfidf->lsi transformations are actually executed here, on the fly
for doc, as_text in zip(corpus_lsi, documents):
    print(doc, as_text)
[(0, 0.06600783396090446), (1, -0.5200703306361851)] Human machine interface for lab abc computer applications
[(0, 0.19667592859142627), (1, -0.7609563167700037)] A survey of user opinion of computer system response time
[(0, 0.08992639972446514), (1, -0.724186062675251)] The EPS user interface management system
[(0, 0.07585847652178207), (1, -0.632055158600343)] System and human system engineering testing of EPS
[(0, 0.10150299184980262), (1, -0.5737308483002944)] Relation of user perceived response time to error measurement
[(0, 0.703210893937831), (1, 0.16115180214025884)] The generation of random binary unordered trees
[(0, 0.8774787673119828), (1, 0.16758906864659542)] The intersection graph of paths in trees
[(0, 0.9098624686818574), (1, 0.14086553628719167)] Graph minors IV Widths of trees and well quasi ordering
[(0, 0.6165825350569278), (1, -0.05392907566389242)] Graph minors A survey

您可以将经过训练的模型保存到磁盘,然后再将它们加载回来,以继续训练新的训练文档或转换新文档。gensim 提供了许多不同的模型/转换。

创建模型后,您可以用它做各种事情。例如通过 TF-IDF 对整个语料进行改造并建立索引,为相似度查询做准备:

from gensim import similarities

index = similarities.SparseMatrixSimilarity(tfidf[bow_corpus], num_features=12)

并查询我们的查询文档 query_document 与语料库中每个文档的相似性:

query_document = 'system engineering'.split()
query_bow = dictionary.doc2bow(query_document)
sims = index[tfidf[query_bow]]
print(list(enumerate(sims)))
[(0, 0.0), (1, 0.32448703), (2, 0.41707572), (3, 0.7184812), (4, 0.0), (5, 0.0), (6, 0.0), (7, 0.0), (8, 0.0)]

你可能感兴趣的:(自然语言处理,人工智能,自然语言处理,人工智能,Gensim,主题建模)