找到两个文档之间的相似性

时间:2012-01-13 03:46:40

标签: lucene similarity

是否有内置算法来查找lucene中两个文档之间的相似性? 当我浏览默认的相似性类时,它会在比较查询和文档后给出得分。

我已经索引了我的文件a,使用了雪球分析器,下一步就是找到两个文件之间的相似性。

有人可以提出解决方案吗?

1 个答案:

答案 0 :(得分:0)

似乎没有内置算法。我相信有三种方法可以解决这个问题:

a)在其中一个文档上运行MoreLikeThis查询。迭代结果,检查doc id并获得分数。也许不漂亮,你可能需要为你想要的那些文件返回很多文件。

b)余弦相似度:Mikos在其评论中提供的链接的答案解释了如何计算两个文档的余弦相似度。

c)计算你自己的Lucene相似度得分。 Lucene得分为余弦相似度(http://lucene.apache.org/core/4_2_0/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html)增加了几个因素。

您可以使用

DefaultSimilarity ds = new DefaultSimilarity();
SimScorer scorer = ds.simScorer(stats , arc);
scorer.score(otherDocId, freq);

您可以通过

获取参数
AtomicReaderContext arc = IndexReader.leaves().get(0);
SimWeight stats = ds.computeWeight(1, collectionStats, termStats);
stats.normalize(1, 1);

反过来,您可以使用TermVector为两个文档中的第一个获取术语统计信息,并使用IndexReader获取收集统计信息。要获取freq参数,请使用

DocsEnum docsEnum = MultiFields.getTermDocsEnum(reader, null, field, term);

,遍历文档,直到找到第一个文档的文档ID,然后执行

freq = docsEnum.freq();

请注意,您需要拨打" scorer.score"对于第一个文档中的每个术语(或您要考虑的每个术语),并总结结果。

最后,乘以" queryNorm"和" coord"参数,你可以使用

//sumWeights was computed while iterating over the first termvector
//in the main loop by summing up "stats.getValueForNormalization();"
float queryNorm = ds.queryNorm(sumWeights);
//thisTV and otherTV are termvectors for the two documents.
//overlap can be easily calculated
float coord = ds.coord(overlap, (int) Math.min(thisTV.size(), otherTV.size()));
return coord * queryNorm * score;

所以这是一种应该有效的方法。它不优雅,并且由于难以获得术语频率(每个术语迭代DocsEnum),它也不是很有效。我仍然希望这有助于某人:)