gensim 专注于非监督学习,一般来说就是训练词向量。
core concepts
- Document: 文档,一个字符串。
- Corpus: 语料库,文档的集合。
- Vector: 向量,文档的数学表示方式。
- Model: 将向量从一种表示转换为另一种表示的算法。
Document
document
是文本序列类型,在python中就是 str
。document
可以是一个句子,一篇文章,甚至是一本书的内容。
document = "Human machine interface for lab abc computer applications
Corpus
corpus
是 document
对象的集合,在 gensim 中有两个作用:
- 作为训练
model
的输入。在训练期间,模型会使用该训练语料库来查找常见的主题和话题,从而初始化其内部模型参数。Gensim专注于无监督模型,因此不需要人工干预,例如昂贵的注释或手工标记文档。 - Documents to organize。训练后,可以使用主题模型从新文档(训练语料库中未显示的文档)中提取主题。这样的
corpora
可以被Similarity Queries
索引化,可以被semantic similarity
,clustered
等查询。
例如:
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",
]
收集完语料库后,通常需要执行许多预处理步骤。例如删除高频词和低频词,并对 corpus 进行 tokenization,将句子分解为 words。
# 创建停用词集合
stoplist = set('for a of the and to in'.split(' '))
# 小写化,分解为单词并过滤停用词
texts = [[word for word in document.lower().split() if word not in stoplist]
for document in text_corpus]
# 计算频次
from collections import defaultdict
frequency = defaultdict(int)
for text in texts:
for token in text:
frequency[token] += 1
# 去掉低频词
processed_corpus = [[token for token in text if frequency[token] > 1] for text in texts]
pprint.pprint(processed_corpus)
Out:
[['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 提供的类来处理:
from gensim import corpora
dictionary = corpora.Dictionary(processed_corpus)
print(dictionary)
Out:
Dictionary(12 unique tokens: ['computer', 'human', 'interface', 'response', 'survey']...)
Vector
为了推断语料库中的潜在结构,我们需要一种可以进行数学处理的 document 表示方式。
有很多表示方法。
其中一种是词袋表示。示例 corpus 有 12 个 unique 单词,意味着一个 document 可以表示为一个 12 维向量。可以打印出这个字典里所有单词到 ID 的映射关系:
>>> pprint.pprint(dictionary.token2id)
Out:
{
'computer': 0,
'eps': 8,
'graph': 10,
'human': 1,
'interface': 2,
'minors': 11,
'response': 3,
'survey': 4,
'system': 5,
'time': 6,
'trees': 9,
'user': 7}
想要向量化一个 document, 可以使用 doc2bow
方法:
new_doc = "Human computer interaction"
new_vec = dictionary.doc2bow(new_doc.lower().split())
print(new_vec)
Out:
[(0, 1), (1, 1)]
第一个是 token id, 第二个数字表示这个 token id 出现的频次。字典中没有的不会出现。函数 doc2bow()
只是计算每个不同单词的出现次数,将该单词转换为其整数单词id,然后将结果作为稀疏向量返回。
将原始 corpus 转换为 vectors:
bow_corpus = [dictionary.doc2bow(text) for text in processed_corpus]
pprint.pprint(bow_corpus)
Out:
[[(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)]]
Model
进行了向量化处理后就可以用 Model 进行转换了。document 以 vector 表示,因此可以将 model 视为两个 vector space 之间的转换。当 model 读取 training corpus 时,将在训练过程中学习到此转换的详细信息。
以 tfidf model 为例,在 corpus 中训练并转换 ‘system minors’ :
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)])
Out:
[(5, 0.5898341626740045), (11, 0.8075244024440723)]
第一个是 token id,第二个是 tf-idf 权重。在 corpus 中,“system” 出现了 4 次, “minors” 出现了 2 次,所以 “system” 权重低。
创建模型后,可以使用它进行各种有趣的操作。例如,要通过 TfIdf 转换整个语料并对其进行索引,以准备 similarity queries:
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)))
Out:
[(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)]
第一个数字表示 document 的序号,第二个数字表示 query_document
与之的相似度。
Corpora and Vector Spaces
演示如何将文本转换为向量空间表示形式。 还介绍了语料库流和各种格式的磁盘持久性。
From Strings to Vectors
首先对 corpus 进行同上的预处理:
from pprint import pprint # pretty-printer
from collections import defaultdict
documents = [
"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",
]
stoplist = set('for a of the and to in'.split())
texts = [
[word for word in document.lower().split() if word not in stoplist]
for document in documents
]
frequency = defaultdict(int)
for text in texts:
for token in text:
frequency[token] += 1
texts = [[token for token in text if frequency[token] > 1] for text in texts]
pprint(texts)
Out:
[['human', 'interface', 'computer'],
['survey', 'user', 'computer', 'system', 'response', 'time'],
['eps', 'user', 'interface', 'system'],
['system', 'human', 'system', 'eps'<