与 Lucene 的余弦相似度仅适用于匹配的文档

Cosine Similarity with Lucene only for documents that match

Lucene 是一个逆向索引系统,据我了解,它的强大之处在于它只会将查询与至少匹配标记的文档进行比较。

与将查询与每个文档进行比较的朴素方法(即使是那些未提及查询中存在的任何标记的文档)相比,这是一个很大的好处。

例如,如果我有索引文档:

D1: "Hello world said the guy"
D2: "Hello, what a beautiful world"
D3: "random text"

如我所见,搜索查询:“Hello world”,只会查看索引文档 D1 和 D2并跳过 D3,这样可以节省时间。

这是正确的吗?

现在,我正在尝试计算文档之间的余弦相似度。输入查询将是一个文档,输出应该是余弦分数。这是一个介于 0 和 1 之间的数字。

我已经读过一些计算余弦相似度的方法,但它们都是通过比较每个文档的术语向量来实现的。例如 this 博客提到了以下内容:

If you really need cosine similarity between documents, you have to enable term vectors for the source fields, and use them to calculate the angle. The problem is that this does not scale well, you would need to calculate angles with virtually all other documents.

和这个SO answers似乎说的一样:

  1. iterate over all doc ids, 0 to maxDoc();

有没有办法只计算与查询匹配的文档的余弦相似度,并将这个 return 作为文档的分数?

作为旁注, 我确实读到 TFIDFSimilarity 接近,我相信 VSM 部分正是我所需要的,但是这部分似乎已经在 Lucene 实用评分功能中消失了。我不确定如何 "transform" 这种相似性 class 最终只得到纯余弦相似性作为结果。

回顾一下我的问题:

  1. 我对逆向索引如何节省时间的看法正确吗?

  2. 有没有办法只计算文档的余弦相似度 实际上匹配其中一个标记,而不是所有文档?

  3. 我可以 use/transform TFIDFSimilarity class 结束吗 纯余弦相似度?
  1. 这在很大程度上取决于您如何制定查询。如果您制定一个 BooleanQuery,您可以指定查询的哪些术语必须在返回的文档中。这是使用 BoolenClause.Occur.MUST 完成的。

  2. 您可以通过扩展 TFIDFSimilarity 编写自己的相似度,但您可能会注意到 Lucene 实用评分是基于余弦相似度的。在该公式中,queryNorm(q) 和 norm(t, d) 构成余弦相似度的分母,求和是查询向量和文档向量的点积。

提示:您可以形成一个示例查询并使用explain()查看评分的详细信息。