Lucene 评分:获得余弦相似度作为分数
Lucene scoring: get cosine similarity as scores
我正在尝试解决最近邻搜索问题。
这是我的代码:
// Indexing
val analyzer = new StandardAnalyzer()
val directory = new RAMDirectory()
val config = new IndexWriterConfig(analyzer)
val iwriter = new IndexWriter(directory, config)
val queryField = "fieldname"
stringData.foreach { str =>
val doc = new Document()
doc.add(new TextField(queryField, str, Field.Store.YES))
iwriter.addDocument(doc)
}
iwriter.close()
// Searching
val ireader = DirectoryReader.open(directory)
val isearcher = new IndexSearcher(ireader)
val parser = new QueryParser(queryField, analyzer)
val query = parser.parse("Some text for testing")
val hits = isearcher.search(query, 10).scoreDocs
当我查看值命中时,我看到分数超过 1。
据我所知,lucene的评分公式是:
score(q,d) = coord-factor(q,d) · query-boost(q) · cosSim(q,d) · doc-len-norm(d) · doc-boost(d)
但我只想获得查询和文档之间范围 [0,1] 内的余弦相似度,而不是坐标因子、doc-len-norm 等。
实现它的可能方法是什么?
如果你看过这个官方 documentation,你会意识到 score
表达式中的其余术语很重要,可以使评分过程更加合乎逻辑和连贯。
但是,如果您想仅使用余弦相似度来实现评分过程,那么您可以编写自定义相似度 class。我在 class assignment 中使用了不同类型的相似度方法来进行文档检索。因此,简而言之,您可以编写自己的相似度方法并将其分配给 Lucene 的 index searcher
。我在这里给出一个例子,你可以修改它来完成你想要的。
编写您的自定义 class(您只需要在 class 中覆盖一个方法)。
import org.apache.lucene.search.similarities.BasicStats;
import org.apache.lucene.search.similarities.SimilarityBase;
public class MySimilarity extends SimilarityBase {
@Override
protected float score(BasicStats stats, float termFreq, float docLength) {
double tf = 1 + (Math.log(termFreq) / Math.log(2));
double idf = Math.log((stats.getNumberOfDocuments() + 1) / stats.getDocFreq()) / Math.log(2);
float dotProduct = (float) (tf * idf);
return dotProduct;
}
}
然后将您实现的方法分配给 index searcher
进行相关性计算,如下所示。
IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexPath)));
IndexSearcher indexSearcher = new IndexSearcher(reader);
indexSearcher.setSimilarity(new MySimilarity());
在这里,我使用 tf-idf 点积来计算查询和文档之间的相似度。公式是,
这里需要说明两点:
- stats.getNumberOfDocuments() returns 索引中的文档总数。
- stats.getDocFreq() returns 一个词出现在查询和文档中的文档频率。
Lucene 现在将调用您已实现的 score()
方法来计算每个匹配项的相关性得分;在查询和文档中都出现的术语。
我知道这不是对您问题的直接回答,但您可以随意使用我上面提到的方法。我在家庭作业中实施了 6 种不同的评分技巧。希望对你也有帮助。
我正在尝试解决最近邻搜索问题。 这是我的代码:
// Indexing
val analyzer = new StandardAnalyzer()
val directory = new RAMDirectory()
val config = new IndexWriterConfig(analyzer)
val iwriter = new IndexWriter(directory, config)
val queryField = "fieldname"
stringData.foreach { str =>
val doc = new Document()
doc.add(new TextField(queryField, str, Field.Store.YES))
iwriter.addDocument(doc)
}
iwriter.close()
// Searching
val ireader = DirectoryReader.open(directory)
val isearcher = new IndexSearcher(ireader)
val parser = new QueryParser(queryField, analyzer)
val query = parser.parse("Some text for testing")
val hits = isearcher.search(query, 10).scoreDocs
当我查看值命中时,我看到分数超过 1。
据我所知,lucene的评分公式是:
score(q,d) = coord-factor(q,d) · query-boost(q) · cosSim(q,d) · doc-len-norm(d) · doc-boost(d)
但我只想获得查询和文档之间范围 [0,1] 内的余弦相似度,而不是坐标因子、doc-len-norm 等。 实现它的可能方法是什么?
如果你看过这个官方 documentation,你会意识到 score
表达式中的其余术语很重要,可以使评分过程更加合乎逻辑和连贯。
但是,如果您想仅使用余弦相似度来实现评分过程,那么您可以编写自定义相似度 class。我在 class assignment 中使用了不同类型的相似度方法来进行文档检索。因此,简而言之,您可以编写自己的相似度方法并将其分配给 Lucene 的 index searcher
。我在这里给出一个例子,你可以修改它来完成你想要的。
编写您的自定义 class(您只需要在 class 中覆盖一个方法)。
import org.apache.lucene.search.similarities.BasicStats;
import org.apache.lucene.search.similarities.SimilarityBase;
public class MySimilarity extends SimilarityBase {
@Override
protected float score(BasicStats stats, float termFreq, float docLength) {
double tf = 1 + (Math.log(termFreq) / Math.log(2));
double idf = Math.log((stats.getNumberOfDocuments() + 1) / stats.getDocFreq()) / Math.log(2);
float dotProduct = (float) (tf * idf);
return dotProduct;
}
}
然后将您实现的方法分配给 index searcher
进行相关性计算,如下所示。
IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexPath)));
IndexSearcher indexSearcher = new IndexSearcher(reader);
indexSearcher.setSimilarity(new MySimilarity());
在这里,我使用 tf-idf 点积来计算查询和文档之间的相似度。公式是,
这里需要说明两点:
- stats.getNumberOfDocuments() returns 索引中的文档总数。
- stats.getDocFreq() returns 一个词出现在查询和文档中的文档频率。
Lucene 现在将调用您已实现的 score()
方法来计算每个匹配项的相关性得分;在查询和文档中都出现的术语。
我知道这不是对您问题的直接回答,但您可以随意使用我上面提到的方法。我在家庭作业中实施了 6 种不同的评分技巧。希望对你也有帮助。