针对许多文档计算文本相似度

Posted

技术标签:

【中文标题】针对许多文档计算文本相似度【英文标题】:Computing text similarity against many documents 【发布时间】:2020-03-10 12:17:51 【问题描述】:

我正在尝试计算搜索词 A 与其他搜索词集合的文本相似度,例如“如何制作鸡”。为了计算相似度,我使用余弦距离和 TF-IDF 将 A 转换为向量。我想一次比较 A所有 个文档的相似度。

目前,我的方法是迭代地计算 A 与其他所有文档的余弦相似度。我有 100 个要比较的文件。如果是cos_sim(A, X) > 0.8 的结果,那么我会说“酷,这很相似”。

但是,我觉得这可能不是整体相似性的真实表示。有没有办法在运行时为我的 100 个文档预先计算一个向量,并且每次我看到一个新的搜索查询 A 时,我都可以与这个预定义的向量/文档进行比较?

我相信我可以通过简单地将所有文档合并为一个来实现这一点……不过感觉很粗糙。有哪些利弊,以及可能的解决方案?效率加分!

【问题讨论】:

【参考方案1】:

这个问题本质上是传统的搜索问题:您是否尝试过将文档放入Lucene (Java) 或Whoosh (python) 之类的位置?我认为他们有一个余弦相似模型(但即使他们没有,默认值可能会更好)。

所有搜索引擎使用的一般技巧是,文档通常是稀疏的。这意味着要计算相似度(例如,余弦相似度),只关心文档的长度(提前知道)以及它们都包含的术语 ;您可以组织一个像书后索引这样的数据结构,称为inverted index,它可以快速告诉您哪些文档将获得至少非零分。

只有 100 个文档,搜索引擎可能是矫枉过正;您想预先计算 TF-IDF 向量并将它们保存在一个 numpy 矩阵中。然后,您可以使用 numpy 操作一次计算所有文档的点积——它将输出numerators you need 的 1x100 向量。分母可以类似地预先计算。然后numpy.max(numpy.dot(query, docs)/denom) 可能就足够快了。

您应该分析您的代码,但我敢打赌您的矢量提取是缓慢的部分;但是对于所有查询,您应该只需要这样做一次。

如果您有数千或数百万个文档要比较,您可以查看 SciKit learn 的 K-最近邻结构(例如,Ball Tree 或 KDTree,或类似 Facebook's FAISS library 的东西。

【讨论】:

以上是关于针对许多文档计算文本相似度的主要内容,如果未能解决你的问题,请参考以下文章

基于Gensim的文本相似度计算

文本相似度计算(一):距离方法

文本相似度-bm25算法原理及实现

向量空间模型(VSM)计算文本相似度

自然语言语义相似度计算方法

文本、语音相似度算法