相似性查询

别忘了设置

  1. >>> import logging
  2. >>> logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

如果你想看到记录事件。

相似性界面

在之前关于Corpora和向量空间以及主题和转换的教程中,我们介绍了在向量空间模型中创建语料库以及如何在不同向量空间之间进行转换的含义。这种特征的一个常见原因是我们想要确定 文档对**之间相似性,或者特定文档与一组其他文档(例如用户查询与索引文档)之间相似性**。

为了说明在gensim中如何做到这一点,让我们考虑与之前的例子相同的语料库(它最初来自Deerwester等人的“潜在语义分析索引” 1990年开篇 文章):

  1. >>> from gensim import corpora, models, similarities
  2. >>> dictionary = corpora.Dictionary.load('/tmp/deerwester.dict')
  3. >>> corpus = corpora.MmCorpus('/tmp/deerwester.mm') # comes from the first tutorial, "From strings to vectors"
  4. >>> print(corpus)
  5. MmCorpus(9 documents, 12 features, 28 non-zero entries)

按照Deerwester的例子,我们首先使用这个小的语料库来定义一个二维LSI空间:

  1. >>> lsi = models.LsiModel(corpus, id2word=dictionary, num_topics=2)

现在假设用户输入查询“人机交互”。我们希望按照与此查询相关的递减顺序对我们的九个语料库文档进行排序。与现代搜索引擎不同,这里我们只关注可能相似性的一个方面 - 关于其文本(单词)的明显语义相关性。没有超链接,没有随机游走静态排名,只是布尔关键字匹配的语义扩展:

  1. >>> doc = "Human computer interaction"
  2. >>> vec_bow = dictionary.doc2bow(doc.lower().split())
  3. >>> vec_lsi = lsi[vec_bow] # convert the query to LSI space
  4. >>> print(vec_lsi)
  5. [(0, -0.461821), (1, 0.070028)]

此外,我们将考虑余弦相似性 来确定两个向量的相似性。余弦相似度是向量空间建模中的标准度量,但是无论向量表示概率分布, 不同的相似性度量可能更合适。

初始化查询结构

为了准备相似性查询,我们需要输入我们想要与后续查询进行比较的所有文档。在我们的例子中,它们与用于训练LSI的九个文件相同,转换为二维LSA空间。但这只是偶然的,我们也可能完全索引不同的语料库。

  1. >>> index = similarities.MatrixSimilarity(lsi[corpus]) # transform corpus to LSI space and index it

警告

  • similarities.MatrixSimilarity只有当整个向量集适合内存时,该类才适用。例如,当与此类一起使用时,一百万个文档的语料库在256维LSI空间中将需要2GB的RAM。
  • 如果没有2GB的可用RAM,则需要使用similarities.Similarity该类。此类通过在磁盘上的多个文件(称为分片)之间拆分索引,在固定内存中运行。它使用similarities.MatrixSimilaritysimilarities.SparseMatrixSimilarity内部,所以它仍然很快,虽然稍微复杂一点。

索引持久性通过标准save()load()函数处理:

  1. >>> index.save('/tmp/deerwester.index')
  2. >>> index = similarities.MatrixSimilarity.load('/tmp/deerwester.index')

对于所有相似性索引类(similarities.Similaritysimilarities.MatrixSimilaritysimilarities.SparseMatrixSimilarity)都是如此。同样在下文中,索引可以是任何这些的对象。如果有疑问,请使用similarities.Similarity,因为它是最具扩展性的版本,并且它还支持稍后向索引添加更多文档。

执行查询

要获得我们的查询文档与九个索引文档的相似性:

  1. >>> sims = index[vec_lsi] # perform a similarity query against the corpus
  2. >>> print(list(enumerate(sims))) # print (document_number, document_similarity) 2-tuples
  3. [(0, 0.99809301), (1, 0.93748635), (2, 0.99844527), (3, 0.9865886), (4, 0.90755945),
  4. (5, -0.12416792), (6, -0.1063926), (7, -0.098794639), (8, 0.05004178)]

余弦测量返回范围中的相似度(越大,越相似),因此第一个文档的得分为0.99809301等。

使用一些标准的Python魔术,我们将这些相似性按降序排序,并获得查询 人机交互 的最终答案:

  1. >>> sims = sorted(enumerate(sims), key=lambda item: -item[1])
  2. >>> print(sims) # print sorted (document number, similarity score) 2-tuples
  3. [(2, 0.99844527), # The EPS user interface management system
  4. (0, 0.99809301), # Human machine interface for lab abc computer applications
  5. (3, 0.9865886), # System and human system engineering testing of EPS
  6. (1, 0.93748635), # A survey of user opinion of computer system response time
  7. (4, 0.90755945), # Relation of user perceived response time to error measurement
  8. (8, 0.050041795), # Graph minors A survey
  9. (7, -0.098794639), # Graph minors IV Widths of trees and well quasi ordering
  10. (6, -0.1063926), # The intersection graph of paths in trees
  11. (5, -0.12416792)] # The generation of random binary unordered trees

(我将原始文档以“字符串形式”添加到输出注释中,以提高清晰度。)

这里要注意的是文件没有。标准布尔全文搜索永远不会返回2(EPS用户界面管理系统)和4(用户感知响应时间与错误测量的关系),因为他们不与 人机交互 分享任何常用词。然而,在应用LSI之后,我们可以观察到它们都获得了相当高的相似性得分(第2个实际上是最相似的!),这更符合我们对它们与查询共享 computer-human 相关主题的直觉。事实上,这种语义概括是我们首先应用转换并进行主题建模的原因。

下一个在哪里

恭喜你,你已经完成了教程-现在你知道作品:-)深入到更多的细节如何gensim,您可以通过浏览API文档,请参阅维基百科的实验或者是退房分布式计算中gensim。

gensim是一个相当成熟的软件包,已被许多个人和公司成功使用,用于快速原型制作和生产。这并不意味着它是完美的:

在所有NLP(甚至机器学习)子域中,gensim没有野心成为一个包罗万象的框架。它的使命是帮助NLP从业者轻松地在大型数据集上尝试流行的主题建模算法,并促进研究人员对新算法的原型设计。