gensim计算文档相似度
gensim 是以Python语言为基础的一个免费软件包,支持向量空间模型(VSM)和话题模型(topic modeling)的相关任务。本文将介绍如何利用gensim 工具来计算两篇中文文本之间的相似程度。
我们需要生成一组中文样本文档。以下代码创建了一个名为documents的列表,在此过程中我们使用的是简单的文本处理方法。作为演示实例,在每个文档中仅包含少量词汇。对于原始文本进行分词处理的方法可以在官方推荐中找到详细说明:推荐阅读)
from gensim import corpora
from pprint import pprint
documents = ["你好 好的 不错 笨蛋",
"笨蛋 傻瓜 傻子 哈哈",
"好的 不错 你好 哈哈",
"有趣 可以 好的 不错 还行",
"傻瓜 傻子 二货 还行",
"可以 好的 不错 哈哈",
"有趣 有趣 哈哈 哈哈"]
texts = [[word for word in document.split()] for document in documents]
pprint(texts)
[['你好', '好的', '不错', '笨蛋'],
['笨蛋', '傻瓜', '傻子', '哈哈'],
['好的', '不错', '你好', '哈哈'],
['有趣', '可以', '好的', '不错', '还行'],
['傻瓜', '傻子', '二货', '还行'],
['可以', '好的', '不错', '哈哈'],
['有趣', '有趣', '哈哈', '哈哈']]
然后我们进行了原始文档的预处理工作。具体而言,在这一步骤中我们统计了每个词项在文本中的频率,并排除了仅在文本中出现一次的词项因为这些词通常不具备显著的意义价值进而不会对后续的信息提取产生帮助作用。此外,在预处理过程中我们还去除了数字、字母以及标点符号等元素这些基本字符对于数据清洗具有重要作用
from collections import defaultdict
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)
[['你好', '好的', '不错', '笨蛋'],
['笨蛋', '傻瓜', '傻子', '哈哈'],
['好的', '不错', '你好', '哈哈'],
['有趣', '可以', '好的', '不错', '还行'],
['傻瓜', '傻子', '还行'],
['可以', '好的', '不错', '哈哈'],
['有趣', '有趣', '哈哈', '哈哈']]
接着我们系统性地构建了一个囊括所有词汇的词汇表,并以此为基础为后续步骤提供必要的数据支持。在实际应用中,这个词汇表往往会变得极为庞大,在这种情况下直接进行重复处理将会导致效率低下甚至性能瓶颈问题。因此建议我们在每次构建完成后立即执行存储操作以实现数据持久化存储
dictionary = corpora.Dictionary(texts)
dictionary.save('sample.dict')
print(dictionary)
Dictionary(10 unique tokens: ['不错', '你好', '好的', '笨蛋', '傻子']...)
基于上一步骤生成的词汇表, 我们即可将每一个词汇映射为一个索引号. 这个索引号代表该词汇在全部文档中的排序位置. 进而使得每一个文档转化为由这些索引号构成的一个列表.
corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize('sample.mm', corpus)
pprint(corpus)
[[(0, 1), (1, 1), (2, 1), (3, 1)],
[(3, 1), (4, 1), (5, 1), (6, 1)],
[(0, 1), (1, 1), (2, 1), (6, 1)],
[(0, 1), (2, 1), (7, 1), (8, 1), (9, 1)],
[(4, 1), (5, 1), (9, 1)],
[(0, 1), (2, 1), (6, 1), (7, 1)],
[(6, 2), (8, 2)]]
然后我们可以利用 gensim 提供的 tf-idf 模块为每个单词计算相应的权重值。具体而言, 关于 tf-id-f 的计算方法, 可以参考 维基百科 相关介绍.
from gensim import models, similarities
tf_idf = models.TfidfModel(corpus)
vec = [(0, 1), (5, 1), (7, 1)]
print(tf_idf[vec])
[(0, 0.3011997233053068), (5, 0.6742695034927825), (7, 0.6742695034927825)]
当前阶段,在线编辑器中的内容更新流程已设置完成,并且已经完成了测试运行阶段的全部内容验证工作
index = similarities.SparseMatrixSimilarity(tf_idf[corpus], num_features=10)
sims = index[tf_idf[vec]]
print(sims)
[0.08686648 0.37695488 0.10641449 0.43870124 0.38928968 0.63969857
0. ]
另外我们可以输出整个相似度矩阵以观察前面准备好的七篇文档之间的两两相似度情况
print(index[tf_idf[corpus]])
[[1. 0.3609379 0.71441036 0.13975498 0. 0.20378576
]
[0.3609379 1.0000001 0.08823138 0. 0.64554304 0.08823138
10185669]
[0.71441036 0.08823138 1.0000001 0.17120475 0. 0.37446705
1440983 ]
[0.13975498 0. 0.17120475 1. 0.31315398 0.60019135
4952337 ]
[0. 0.64554304 0. 0.31315398 0.99999994 0.
]
[0.20378576 0.08823138 0.37446705 0.60019135 0. 1.
1440983 ]
[0. 0.10185669 0.1440983 0.4952337 0. 0.1440983
99999994]]
本文中的代码基于Jupyter Notebook开发。有需要的访客可以直接访问github,该资源将提供详细说明并可下载。
