lucene 的评分机制

elasticsearch是基于lucene的,所以他的评分机制也是基于lucene的。评分就是我们搜索的短语和索引中每篇文档的相关度打分。

如果没有干预评分算法的时候,每次查询,lucene会基于一个评分算法来计算所有文档和搜索语句的相关评分。

使用lucene的评分机制基本能够把最符合用户需要的搜索放在最前面。

当然有的时候,我们可能想要自定义评分算法,这个就和lucene的评分算法没有什么关系了。当然,我们大多数应该还是会根据自己的需求,来调整lucene本身的算法。

lucene的评分公式

lucene的评分是叫做TF/IDF算法,基本意思就是词频算法。

根据分词词库,所有的文档在建立索引的时候进行分词划分。进行搜索的时候,也对搜索的短语进行分词划分。

TF代表分词项在文档中出现的次数(term frequency),IDF代表分词项在多少个文档中出现(inverse document frequency)。

lucene的算法简单来说就是将搜索的短语进行分词得出分词项,每个分词项和每个索引中的文档根据TF/IDF进行词频出现的评分计算。

然后每个分词项的得分相加,就是这个搜索对应的文档得分。

这个评分公式有6个部分组成

  • coord(q,d) 评分因子,基于文档中出现查询项的个数。越多的查询项在一个文档中,说明文档的匹配程度越高。
  • queryNorm(q)查询的标准查询
  • tf(t in d) 指项t在文档d中出现的次数frequency。具体值为次数的开根号。
  • idf(t) 反转文档频率, 出现项t的文档数docFreq
  • t.getBoost 查询时候查询项加权
  • norm(t,d) 长度相关的加权因子

coord(q, d)

这个评分因子的计算公式是:

public float coord(int overlap, int maxOverlap) {
return overlap / (float)maxOverlap;
}
  • overlap: 文档中命中检索的个数
  • maxOverlap: 检索条件的个数

比如检索"english book", 现在有一个文档是"this is an chinese book"。

那么,这个搜索对应这个文档的overlap为1(因为匹配了book),而maxOverlap为2(因为检索条件有两个book和english)。

最后得到的这个搜索对应这个文档的coord值为0.5。

queryNorm(q)

这个因素对所有文档都是一样的值,所以它不影响排序结果。比如如果我们希望所有文档的评分大一点,那么我们就需要设置这个值。

public float queryNorm(float sumOfSquaredWeights) {
return (float)(1.0 / Math.sqrt(sumOfSquaredWeights));
}

tf(t in d)

项t在文档d中出现的次数

public float tf(float freq) {
return (float)Math.sqrt(freq);
}

比如有个文档叫做"this is book about chinese book", 我的搜索项为"book",那么这个搜索项对应文档的freq就为2,那么tf值就为根号2,即1.4142135

idf

public float idf(long docFreq, long numDocs) {
return (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0);
}

这里的两个值解释下

  • docFreq 指的是项出现的文档数,就是有多少个文档符合这个搜索
  • numDocs 指的是索引中有多少个文档。

我在用es实际看这里的时候遇到一个问题,numDocs数和实际的文档数不一致,最后弄明白了,这里的numDocs指的是分片的文档数据,而不是所有分片的文档数。

所以使用es分析这个公式的时候,最好将分片数设置为1。

比如我现在有三个文档,分别为:

  • this book is about english
  • this book is about chinese
  • this book is about japan

我要搜索的词语是"chinese",那么对第二篇文档来说,docFreq值就是1,因为只有一个文档符合这个搜索,而numDocs就是3。最后算出idf的值是:

(float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0) = ln(3/(1+1)) + 1 = ln(1.5) + 1 = 0.40546510810816 + 1 = 1.40546510810816

t.getBoost

查询时期项t的加权,这个就是一个影响值,比如我希望匹配chinese的权重更高,就可以把它的boost设置为2

norm(t,d)

这个项是长度的加权因子,目的是为了将同样匹配的文档,比较短的放比较前面。

比如两个文档:

  • chinese
  • chinese book

我搜索chinese的时候,第一个文档会放比较前面。因为它更符合"完全匹配"。

norm(t,d) = doc.getBoost()· lengthNorm· ∏ f.getBoost()

public float lengthNorm(FieldInvertState state) {
final int numTerms;
if (discountOverlaps)
numTerms = state.getLength() - state.getNumOverlap();
else
numTerms = state.getLength();
return state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)));
}

这里的doc.getBoost表示文档的权重,f.getBoost表示字段的权重,如果这两个都设置为1,那么nor(t,d)就和lengthNorm一样的值。

比如我现在有一个文档:

  • chinese book

搜索的词语为chinese, 那么numTerms为2,lengthNorm的值为 1/sqrt(2) = 0.71428571428571。

但是非常遗憾,如果你使用explain去查看es的时候,发现lengthNorm显示的只有0.625。

这个官方给出的原因是精度问题,norm在存储的时候会进行压缩,查询的时候进行解压,而这个解压是不可逆的,即decode(encode(0.714)) = 0.625。

示例

es中可以使用_explain接口进行评分解释查看。

比如现在我的文档为:

  • chinese book

搜索词为:

{
"query": {
"match": {
"content": "chinese"
}
}
}

explain得到的结果为:

{
"_index": "scoretest",
"_type": "test",
"_id": "2",
"matched": true,
"explanation": {
"value": 0.8784157,
"description": "weight(content:chinese in 1) [PerFieldSimilarity], result of:",
"details": [
{
"value": 0.8784157,
"description": "fieldWeight in 1, product of:",
"details": [
{
"value": 1,
"description": "tf(freq=1.0), with freq of:",
"details": [
{
"value": 1,
"description": "termFreq=1.0"
}
]
},
{
"value": 1.4054651,
"description": "idf(docFreq=1, maxDocs=3)"
},
{
"value": 0.625,
"description": "fieldNorm(doc=1)"
}
]
}
]
}
}

看到这篇文档的总得分为 0.8784157

  • tf(t in d): 1
  • idf: ln(3/(1+1)) + 1 = 1.4054651
  • norm(t,d): decode(encode(1/sqrt(2))) = 0.625
  • 总分: 1.4054651 * 0.625 = 0.8784157

lucene 的评分机制的更多相关文章

  1. Lucene Scoring 评分机制

    原文出处:http://blog.chenlb.com/2009/08/lucene-scoring-architecture.html Lucene 评分体系/机制(lucene scoring)是 ...

  2. Lucene 的 Scoring 评分机制

    转自: http://www.oschina.net/question/5189_7707  Lucene 评分体系/机制(lucene scoring)是 Lucene 出名的一核心部分.它对用户来 ...

  3. Elasticseach的评分机制

    lucene 的评分机制 elasticsearch是基于lucene的,所以他的评分机制也是基于lucene的.评分就是我们搜索的短语和索引中每篇文档的相关度打分. 如果没有干预评分算法的时候,每次 ...

  4. Apache Lucene评分机制的内部工作原理

    Apache Lucene评分机制的内部工作原理' 第5章

  5. Lucene的评分(score)机制研究

    首先,需要学习Lucene的评分计算公式—— 分值计算方式为查询语句q中每个项t与文档d的匹配分值之和,当然还有权重的因素.其中每一项的意思如下表所示: 表3.5 评分公式中的因子 评分因子 描 述 ...

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

    Solr In Action 笔记(2) 之评分机制(相似性计算) 1 简述 我们对搜索引擎进行查询时候,很少会有人进行翻页操作.这就要求我们对索引的内容提取具有高度的匹配性,这就搜索引擎文档的相似性 ...

  7. ELASTICSEARCH 搜索的评分机制

    从我们在elasticsearch复合框输入搜索语句到结果显示,展现给我们的是一个按score得分从高到底排好序的结果集.下面就来学习下elasticsearch怎样计算得分. Lucene(或 El ...

  8. Wifi 评分机制分析

    从android N开始,引入了wifi评分机制,选择wifi的时候会通过评分来选择. android O源码 frameworks\opt\net\wifi\service\java\com\and ...

  9. Lucene TFIDFSimilarity评分公式详解

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/zteny/article/details/ ...

随机推荐

  1. 建立自己的Visual Studio工程模板

    如果你需要经常创建自己的特殊工程的话,那么预先建立自定义的工程模块,可能会让你的工作变得更轻松一些. 实现方法很简单,一共只需要六个步骤: 一. 新建工程 * 这里选用空白的Web工程. 二. 建立必 ...

  2. note of introduction of Algorithms(Lecture 3 - Part1)

    Lecture 3(part 1) Divide and conquer 1. the general paradim of algrithm as bellow: 1. divide the pro ...

  3. 图解集合3:CopyOnWriteArrayList

    初识CopyOnWriteArrayList 第一次见到CopyOnWriteArrayList,是在研究JDBC的时候,每一个数据库的Driver都是维护在一个CopyOnWriteArrayLis ...

  4. 【转载】学习资料存档:jQuery的deferred对象详解

    我在以前的文章里提到promise和deferred,这两个东西其实是对回调函数的一种写法,javascript的难点之一是回调函数,但是我们要写出优秀的javascript代码又不得不灵活运用回调函 ...

  5. 支持断点续传的文件上传插件——Huploadify-V2.0来了

    之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...

  6. C#Light 和 uLua的对比第二弹

    上次的对比大家还有印象否,C#Light和ulua对比各有胜负 今天我们加入一个去反射优化,这是uLua没办法实现的优化,我们也就只能不要脸的胜之不武了 以原生执行同一测试时间为X1,数字越小的越快 ...

  7. 每天一个linux命令(56):netstat命令

    netstat命令​用于显示与IP.TCP.UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况.netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UD ...

  8. 每天一个linux命令(60):scp命令

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...

  9. atitit 英文与中文与阿拉伯文的简化解决方案.docx

    atitit 英文与中文与阿拉伯文的简化解决方案.docx 1. 英文与中文与阿拉伯文的简化意义1 2. 简化的主要方法分类2 2.1. 同音替代法(比如o2o)2 2.2. 符号法(比如英文i18n ...

  10. java 线程协作 join()

    在实际开发中我们往往会遇到这样的情况一个线程的执行需要依赖另一个线程执行后的结果.即主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他 ...