一個搜索引擎使用的時候一定須要排序這個模塊,通常狀況下在不選擇按照某一字段排序的狀況下,都是按照打分的高低進行一個默認排序的,因此若是正式使用的話,必須對默認排序的打分策略有一個詳細的瞭解才能夠,不然被問起來爲何這個在前面,那個在後面很差辦,所以對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專欄