Lucene Scoring 评分机制

原文出处:http://blog.chenlb.com/2009/08/lucene-scoring-architecture.html

Lucene 评分体系/机制(lucene scoring)是 Lucene 出名的一核心部分。它对用户来说隐藏了很多复杂的细节,致使用户可以简单地使用 lucene。但个人觉得:如果要根据自己的应用调节评分(或结构排序),十分有必须深入了解 lucene 的评分机制。

Lucene scoring 组合使用了 信息检索的向量空间模型布尔模型

首先来看下 lucene 的评分公式(在 Similarity 类里的说明)

score(q,d)   =   coord(q,d) ·  queryNorm(q) · ( tf(t in d) ·  idf(t)2 ·  t.getBoost() ·  norm(t,d) )
  t in q  

其中:

  1. tf(t in d) 关联到项频率,项频率是指 项 t 在 文档 d 中出现的次数 frequency。默认的实现是:

    tf(t in d) = frequency½
  2. idf(t) 关联到反转文档频率,文档频率指出现 项 t 的文档数 docFreq。docFreq 越少 idf 就越高(物以稀为贵),但在同一个查询下些值是相同的。默认实现:
    idf(t) = 1 + log (
    numDocs
    –––––––––
    docFreq+1
    )
  3. coord(q,d) 评分因子,是基于文档中出现查询项的个数。越多的查询项在一个文档中,说明些文档的匹配程序越高。默认是出现查询项的百分比。
  4. queryNorm(q)查询的标准查询,使不同查询之间可以比较。此因子不影响文档的排序,因为所有有文档都会使用此因子。默认值:
    queryNorm(q)   =   queryNorm(sumOfSquaredWeights) =
    1
    ––––––––––––––
    sumOfSquaredWeights½

    每个查询项权重的平分方和(sumOfSquaredWeights)由 Weight 类完成。例如 BooleanQuery 地计算:

    sumOfSquaredWeights =   q.getBoost() 2 · ( idf(t) ·  t.getBoost() ) 2
      t in q  
  5. t.getBoost()查询时期的 项 t 加权(如:java^1.2),或者由程序使用 setBoost()。
  6. norm(t,d)压缩几个索引期间的加权和长度因子:
    • Document boost - 文档加权,在索引之前使用 doc.setBoost()
    • Field boost - 字段加权,也在索引之前调用 field.setBoost()
    • lengthNorm(field) - 由字段内的 Token 的个数来计算此值,字段越短,评分越高,在做索引的时候由 Similarity.lengthNorm 计算。

    以上所有因子相乘得出 norm 值,如果文档中有相同的字段,它们的加权也会相乘:

    norm(t,d)   =   doc.getBoost() ·  lengthNorm(field) · f.getBoost()
      field f in d named as t  

    索引的时候,把 norm 值压缩(encode)成一个 byte 保存在索引中。搜索的时候再把索引中 norm 值解压(decode)成一个 float 值,这个 encode/decode 由 Similarity 提供。官方说:这个过程由于精度问题,以至不是可逆的,如:decode(encode(0.89)) = 0.75。

计算这个评分涉及到几个核心的类/接口:Similarity、Query、Weight、Scorer、Searcher,由它们或其子类来完成评分的计算。先来看下它们的类图:

lucene search score uml, 点击放大

搜索中,评分的过程:

  1. 创建一个查询对象 Query,传给 Searcher,具体来讲可能是 IndexSearcher。
  2. Searcher 根据 Query 创建一个对应的 Weight(是 Query 的内部特征表示),接着 Weight 会创建对应的 Scorer。
  3. Searcher 会创建 Hitcollector 并传到 Scorer,scorer 找到匹配的文档并计算评分,最后写到 Hitcollector 中。

Query、Weight、Scorer 三都关系十分密切,尤其是 Query 和 Weight。Weight 是计算查询权重和创建 Scorer 的。Query 为了可以重用把内部的特征抽象为 Weight,由子类去完成一些相关评分的计算。

任何 Searcher 依赖的状态都存储在 Weight 实现中,而不是在Query 中,这样可以重用 Query。

Weight 的生命周期(被使用):

  1. Weight 由顶层的 Query 创建。Query.createWeight(Searcher),创建的 Weight 给 Searcher 去使用。
  2. 当用 Similarity.queryNorm(float) 来计算查询标准化因子(query normalization)的时候,Weight.sumOfSquaredWeights() 会被调用。
  3. 查询标准化因子(query normalization)会传给 Weight.normalize(float)计算,这个时候权重(weighting)计算完成。
  4. 创建一个 Scorer。

自定义评分的计算

可以实现一个 Similarity 换掉默认的。它仅限于 Scorer、Weight 计算好的因子值再加工。要想对评分有更强的控制力,可以实现一套 Query、Weight、Scorer。

  • Query 是用户信息需要的抽象
  • Weight 是 Query 的内部特性表示的抽象
  • Scorer 抽象公用的计算评分功能,提供计算评分和解说(explanation)评分的能力。

Query 子类实现的方法:

  1. createWeight(Searcher searcher) -- Weight 是 Query 内部代表,所以每个 Query 都必实现一个 Weight,此方法就是生成一个Query对应的Weight对象。
  2. rewrite(IndexReader reader) -- 重写查询为原始的查询,原始的查询有:TermQuery,BooleanQuery……

Weight 接口方法:

  1. Weight#getQuery() -- 指出代表 Weight 的 Query。
  2. Weight#getValue() -- Query 的权重,例如:TermQuery.TermWeight 的 value = idf^2 * boost * queryNorm
  3. Weight#sumOfSquaredWeights() -- 各查询项的平方和,如,TermWeight 的 = (idf * boost)^2
  4. Weight#normalize(float) -- 决定查询标准化的因子,查询标准化值可以在不同 Query 比较 score
  5. Weight#scorer(IndexReader) -- 创建 Query 对应的评分器 Scorer,它的责任是给 Query 匹配到的文档评分。
  6. Weight#explain(IndexReader, int) -- 给指定的文档详细解说评分值是怎么得来了。

Scorer 子类实现的方法:

  1. Scorer#next() -- 预取匹配到的下一文档,有才返回 true。
  2. Scorer#doc() -- 返回当前匹配到的文档id,它必须 next() 调用后才有效。
  3. Scorer#score() -- 返回当前文档的评分,此值可以由应用程序以任何适当的方式给出,如 TermScorer 返回 tf * Weight.getValue() * fieldNorm
  4. Scorer#skipTo(int) -- 跳到大于或等于 int 的匹配文档上。很多情况下,在结果集中 skipTo 比较循环更加快速高效。
  5. Scorer#explain(int) -- 给出评分产生的细节。

要实现一套 Query、Weight、Scorer,最好还是看下 TermQuery、TermWeight、TermScorer。

当 Lucene 中没有想要的查询时(包括不同的评分细节),自定义Query 可能帮得上忙。

重要参考资料:

时间: 2024-12-29 23:10:45

Lucene Scoring 评分机制的相关文章

Lucene 的 Scoring 评分机制

转自: http://www.oschina.net/question/5189_7707  Lucene 评分体系/机制(lucene scoring)是 Lucene 出名的一核心部分.它对用户来说隐藏了很多复杂的细节,致使用户可以简单地使用 lucene.但个人觉得:如果要根据自己的应用调节评分(或结构排序),十分有必须深入了解 lucene 的评分机制. Lucene scoring 组合使用了 信 息检索的向量空间模型 和 布尔模型 . 首先来看下 lucene 的评分公式(在 Sim

Elasticseach的评分机制

lucene 的评分机制 elasticsearch是基于lucene的,所以他的评分机制也是基于lucene的.评分就是我们搜索的短语和索引中每篇文档的相关度打分. 如果没有干预评分算法的时候,每次查询,lucene会基于一个评分算法来计算所有文档和搜索语句的相关评分. 使用lucene的评分机制基本能够把最符合用户需要的搜索放在最前面. 当然有的时候,我们可能想要自定义评分算法,这个就和lucene的评分算法没有什么关系了.当然,我们大多数应该还是会根据自己的需求,来调整lucene本身的算

Lucene的评分(score)机制研究

首先,需要学习Lucene的评分计算公式—— 分值计算方式为查询语句q中每个项t与文档d的匹配分值之和,当然还有权重的因素.其中每一项的意思如下表所示: 表3.5 评分公式中的因子 评分因子 描 述 tf(t in d) 项频率因子——文档(d)中出现项(t)的频率 idf(t) 项在倒排文档中出现的频率:它被用来衡量项的“唯一”性.出现频率较高的term具有较低的idf,出现较少的term具有较高的idf boost(t.field in d) 域和文档的加权,在索引期间设置.你可以用该方法

Solr In Action 笔记(2) 之 评分机制(相似性计算)

Solr In Action 笔记(2) 之评分机制(相似性计算) 1 简述 <这就是搜索引擎>里面对相似性计算进行了简单的介绍. 内容的相似性计算由搜索引擎的检索模型建模,它是搜索引擎的理论基础,为量化相关性提供了一种数学模型,否则没法计算.当然检索模型理论研究存在理想化的隐含假设,即假设用户需求已经通过查询非常清晰明确地表达出来了,所以检索模型的任务不牵扯到对用户需求建模,但实际上这个和实际相差较远,即使相同的查询词,不同用户的需求目的可能差异很大,而检索模型对此无能为力.几种常见的检索模

lucene indexwriter锁机制

最近有个项目要用solr,solr是基于lucene的,今天在测试indexwriter时遇到了lock的问题: 测试代码: import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.index.In

lucene 评分机制研究

评分公式 1.coord(q,d),查询覆盖率 /** Implemented as <code>overlap / maxOverlap</code>. */ @Override public float coord(int overlap, int maxOverlap) { return overlap / (float)maxOverlap; } 例如: 查询:query=title:search and content:lucenen 确定最大覆盖maxOverlap =

lucene 自定义评分 影响排序

前记 这段时间需要修改一个别人写的一个搜索有关的项目,恰好底层使用的是lucene搜索框架. 为什么要去修改呢,当然是搜索结果不太令人满意啦,于是去研读了项目中关于搜索的代码...... 正文 经过了几天代码的研读,最终总结出来了几条问题: 创建索引的过程,相当简单,感觉仅仅是把lucene当成关键词匹配的工具去了(需要修改索引策略) 搜索的过程也是比较简单,没有结合项目的需求,定制化搜索(搜索策略需要修改) 额,感觉上面两条好像是在说废话,感觉lucene的和核心就是索引和搜索 为了能尽快解决

lucene自定义评分

要实现自定义评分,想把我们认为应该排在前面成为top,lucenen给我们留了一个扩展类就是CustomScoreQuery 首先.我们创建评分的时候要先定义一个我们自己要改变的评分域 FieldScoreQuery fieldScoreQuery=new FieldScoreQuery("score", Type.INT);//设置评分域为socre 然后indexSearch.search中要传入一个CustomScoreQuery,要覆盖getCustomScoreProvide

原创:史上对BM25模型最全面最深刻的解读以及lucene排序深入讲解(佟学强)

垂直搜索结果的优化包括对搜索结果的控制和排序优化两方面,其中排序又是重中之重.本文将全面深入探讨垂直搜索的排序模型的演化过程,最后推导出BM25模型的排序.然后将演示如何修改lucene的排序源代码,下一篇将深入解读目前比较火热的机器学习排序在垂直搜索中的应用.文章的结构如下: 一.VSM模型简单介绍: 二.lucene默认的评分公式介绍: 三.概率语言模型中的二元独立模型BIM介绍: 四.BM25介绍: 五.lucene中的edismax解析器介绍以及评分公式源代码介绍: 六.修改排序源代码: