繁体   English   中英

自定义lucene评分-字段提升和查询提升之间的点积

[英]Custom lucene scoring - Dot product between field boost and query boost

我想将Lucene与以下评分逻辑一起使用:在索引文档时,我想为每个字段设置一个得分/权重。 查询索引时,我想为每个查询词设置得分/权重。

我将永远不会索引或查询具有相同字段的许多实例–在每个查询(文档)中,将有0-1个具有相同字段名称的实例。 我的字段/查询词未进行分析-它们已经由一个标记组成。

我希望分数只是查询字段与文档字段之间具有相同值的点积。

例如:
格式为(栏位名称)(栏位值)(栏位分数)
查询:
1 AA 0.1
7 BB 0.2
8 CC 0.3

文件1:
1 AA 0.2
2 DD 0.8
7 CC 0.999
10 FFF 0.1

文件2:
7 BB 0.3
8 CC 0.5

分数应为:
得分(q,d1)= FIELD_1_SCORE_Q * FILED_1_SCORE_D1 = 0.1 * 0.2 = 0.02
得分(q,d2)= FIELD_7_SCORE_Q * FILED_7_SCORE_D2 + FIELD_8_SCORE_Q * FILED_8_SCORE_D2 =(0.2 * 0.3)+(0.3 * 0.5)

实施它的最佳方法是什么? 在准确性和性能方面(我不需要TF和IDF计算)。

我目前通过对字段和查询字词设置增强来实现它。 然后,我覆盖DefaultSimilarity类,并在建立索引/查询之前将其设置为默认值:

public class MySimilarity extends DefaultSimilarity {

    @Override
    public float computeNorm(String field, FieldInvertState state) {
        return state.getBoost();
    }

    @Override
    public float queryNorm(float sumOfSquaredWeights) {
        return 1;
    }

    @Override
    public float tf(float freq) {
        return 1;
    }

    @Override
    public float idf(int docFreq, int numDocs) {
        return 1;
    }

    @Override
    public float coord(int overlap, int maxOverlap) {
        return 1;
    }

}


并且基于http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/scoring.html,这应该可行。
问题:

  1. 性能:我正在计算所有TF / IDF内容和NORMS……
  2. 我从TopScoreDocCollector获得的分数与我从解释中获得的分数不同。

这是我的代码的一部分:

indexSearcher = new IndexSearcher(IndexReader.open(directory, true));
TopScoreDocCollector collector = TopScoreDocCollector.create(iTopN, true);
indexSearcher.search(query, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
for (int i = 0; i < hits.length; ++i) {
  int docId = hits[i].doc;
  Document d = indexSearcher.doc(docId);
  double score = hits[i].score;
  String id = d.get(FIELD_ID);
  Explanation explanation = indexSearcher.explain(query, docId);
}

谢谢!

您可以解决几件事:

  • 您没有在粘贴的代码段中设置自定义相似性,请参见IndexSearcher#setSimilarity

  • 当freq等于0时,实现相似性的“ tf”方法应返回0。

此外,您应谨慎使用索引时间提升。 由于它们是在单个字节上编码的,因此可能会有一些精度损失,请参阅《 Lucene》,为什么我的增强文档和未增强文档的得分相同?

索引时间提升的一种替代方法是在不同的数字字段中索引提升值,然后使用CustomScoreQueryfloat FieldCacheSource在分数中利用这些提升。

找出答案-效果很好!

受Lucene邮件列表中的另一个线程(有关CustomScoreQuery的问题)的启发,我正在使用此解决方案,该解决方案运行得很好(有一个缺点):
我发现我的某些问题是由于我的假设是错误的:
我确实有许多具有相同字段ID的字段/查询术语。

这破坏了我的方法,因为查询提升已聚合并且我的计算是错误的。

我所做的是在索引编制过程中,将字段值添加到了字段ID(由“ _”连接),并在字段值中使用了所需的分数。

在搜索时,我使用具有复杂字段ID的简单FieldScoreQuery(按原样,无需修改)。

在这里,我仍然可以使用setBoost来设置分数,因为现在我的字段是唯一的。

从逻辑上讲,这是完美的选择-使用Lucene的点积。

缺点-许多许多不同类型的字段。

重要:
由于我没有使用索引文档字段的规范,因此权重是该字段的值,因此我现在使用以下方法索引这些字段:

Field field = new Field(field_name, Float.toString(weight), Store.YES, Index.NOT_ANALYZED_NO_NORMS);<br>

而且内存使用率已恢复正常...
非常酷!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM