一个搜索引擎使用的时候一定须要排序这个模块,通常状况下在不选择按照某一字段排序的状况下,都是按照打分的高低进行一个默认排序的,因此若是正式使用的话,必须对默认排序的打分策略有一个详细的了解才能够,不然被问起来为何这个在前面,那个在后面很差办,所以对Elasticsearch的打分策略详细的看了下,虽说还不是了解的很所有,可是大部分都看的差很少了,结合理论以及搜索的结果,作一个简单的介绍html
Elasticsearch的默认打分公式是lucene的打分公式,主要分为两部分的计算,一部分是计算query部分的得分,另外一部分是计算field部分的得分,下面给出ES官网给出的打分公式:java
[java] view plain copyapp
在此给每个部分作一个解释elasticsearch
对查询进行一个归一化,不影响排序,由于对于同一个查询这个值是相同的,可是对term于ES来讲,必须在分片是1的时候才不影响排序,不然的话,仍是会有一些细小的区别,有几个分片就会有几个不一样的queryNorm值ide
queryNorm(q)=1 / √sumOfSquaredWeights ui
上述公式是ES官网的公式,这是在默认query boost为1,而且在默认term boost为1 的状况下的打分,其中搜索引擎
sumOfSquaredWeights =idf(t1)*idf(t1)+idf(t2)*idf(t2)+...+idf(tn)*idf(tn)spa
其中n为在query里面切成term的个数,可是上面所有是在默认为1的状况下的计算,实际上的计算公式以下所示:.net
coord(q,d)是一个协调因子它的值以下:3d
[java] view plain copy
其中overlap是检索命中query中term的个数,maxoverlap是query中总共的term个数,例如查询词为“无线通讯”,使用默认分词器,若是文档为“通知他们开会”,只会有一个“通”命中,这个时候它的值就是1/4=0.25
即term t在文档中出现的个数,它的计算公式官网给出的是:
[java] view plain copy
即出现的个数进行开方,这个没什么能够讲述的,实际打分也是如此
这个的意思是出现的逆词频数,即召回的文档在总文档中出现过多少次,这个的计算在ES中与lucene中有些区别,只有在分片数为1的状况下,与lucene的计算是一致的,若是不惟一,那么每个分片都有一个不一样的idf的值,它的计算方式以下所示:
[java] view plain copy
其中,log是以e为底的,不是以10或者以2为底,这点须要注意,numDocs是指全部的文档个数,若是有分片的话,就是指的是在当前分片下总的文档个数,docFreq是指召回文档的个数,若是有分片对应的也是在当前分片下召回的个数,这点是计算的时候与lucene不一样之处,若是想验证是否正确,只需将分片shard的个数设置为1便可。
对于每个term的权值,没仔细研究这个项,我的理解的是,若是对一个field设置boost,那么若是在这个boost召回的话,每个term的boost都是该field的boost
对于field的标准化因子,在官方给的解释是field越短,若是召回的话权重越大,例如搜索无线通讯,一个是很长的内容,但都是包含这几个字,可是并非咱们想要的,另一个内容很短,可是完整包含了无线通讯,咱们不能由于后面的只出现了一次就认为权重是低的,相反,权重应当是更高的,其计算公式以下所示:
其中d.getboost代表若是该文档权重越大那么久越重要
f.getboost代表该field的权值越大,越重要
lengthnorm表示该field越长,越不重要,越短,越重要,在官方文档给出的公式中,默认boost所有为1,在此给出官方文档的打分公式:
[java] view plain copy
该值在计算的时候老是没法对上,查询网上的资料说是在打分的时候将结果先进行压缩,而后解压缩,因此结果跟原始值对不上,我的理解有点像量化的过程,由于在实际explain的时候发现该值有必定的规律性
在实际的时候,例如搜索“无线通讯”,以下图所示,由于一些私人缘由,将一些字段打码,查询的时候设置explain为true,以下图所示:
由于使用的是默认的分词器,因此最后的结果是将“无线通讯”分红了四个字,而且认为是四个term来进行计算,最后将计算的结果进行相加获得最后的得分0.7605926,这个分数是“无”的得分+“线”的得分+“通”的得分+“信”的得分,四个term的得分以下图所示:
最后的得分是0.7605926=0.118954286+0.1808154+0.14515185+0.31567,与上述符合,由于四个词都出现了因此在这里面的coord=1,总分数的计算知道后,咱们单看每一部分的得分的计算,以“无”为例进行介绍:
其中每个term内部分为两部分的分数,一部分是queryweight,一部分是fieldweight,其中总分数=queryweight*fieldweight
例如此处queryweight=0.51195854,fieldWeight=0.2323514,因此总的分数就是0.118954286
对于queryweight部分的计算分为两个部分idf和querynorm,其中idf的值是2.8618271,这个值是如何计算的呢
idf=1+ln(1995/(309+1))=2.8618271,说明在分片四里面共有1995个文档,召回了包含“无”的309个文档,所以为这个值
querynorm部分的计算:根据上面“无”“线”“通”“信”四个的分数计算,能够看到,idf的值分别为
无:2.8618271
线:3.1053379
通:2.235371
信:2.901306
因此按照计算公式
[java] view plain copy
因此queryweight部分的值是0.1788922*2.8618271=0.51195854
再次总结下此处的公式:queryweight=idf*queryNorm(d)
idf的计算上边已经算过,在此不详细叙述
tf的值是在此处出现3次,因此为√3=1.7320508
fieldnorm的值不知道如何计算,按照公式计算不出来explain的值,网上资料说是编解码致使的,哪位朋友知道如何计算麻烦回复下,多谢
总结下fieldweight部分的计算公式:fieldweight=idf*tf*fieldnorm=1.7320508*2.8618271*0.046875=0.2323514
因此整体的计算就是
[java] view plain copy
http://www.cnblogs.com/forfuture1978/archive/2010/03/07/1680007.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/scoring-theory.html#field-norm
版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/molong1208 https://blog.csdn.net/molong1208/article/details/50623948
文章标签: Elasticsearch score explain TFIDF 打分
我的分类: elasticsearch
所属专栏: Elasticsearch专栏