天天看點

lucene 的評分機制lucene 的評分機制lucene的評分公式示例

elasticsearch是基于lucene的,是以他的評分機制也是基于lucene的。評分就是我們搜尋的短語和索引中每篇文檔的相關度打分。

如果沒有幹預評分算法的時候,每次查詢,lucene會基于一個評分算法來計算所有文檔和搜尋語句的相關評分。

使用lucene的評分機制基本能夠把最符合使用者需要的搜尋放在最前面。

當然有的時候,我們可能想要自定義評分算法,這個就和lucene的評分算法沒有什麼關系了。當然,我們大多數應該還是會根據自己的需求,來調整lucene本身的算法。

lucene的評分是叫做TF/IDF算法,基本意思就是詞頻算法。

根據分詞詞庫,所有的文檔在建立索引的時候進行分詞劃分。進行搜尋的時候,也對搜尋的短語進行分詞劃分。

TF代表分詞項在文檔中出現的次數(term frequency),IDF代表分詞項在多少個文檔中出現(inverse document frequency)。

lucene的算法簡單來說就是将搜尋的短語進行分詞得出分詞項,每個分詞項和每個索引中的文檔根據TF/IDF進行詞頻出現的評分計算。

然後每個分詞項的得分相加,就是這個搜尋對應的文檔得分。

lucene 的評分機制lucene 的評分機制lucene的評分公式示例

這個評分公式有6個部分組成

coord(q,d) 評分因子,基于文檔中出現查詢項的個數。越多的查詢項在一個文檔中,說明文檔的比對程度越高。

queryNorm(q)查詢的标準查詢

tf(t in d) 指項t在文檔d中出現的次數frequency。具體值為次數的開根号。

idf(t) 反轉文檔頻率, 出現項t的文檔數docFreq

t.getBoost 查詢時候查詢項權重

norm(t,d) 長度相關的權重因子

這個評分因子的計算公式是:

overlap: 文檔中命中檢索的個數

maxOverlap: 檢索條件的個數

比如檢索"english book", 現在有一個文檔是"this is an chinese book"。

那麼,這個搜尋對應這個文檔的overlap為1(因為比對了book),而maxOverlap為2(因為檢索條件有兩個book和english)。

最後得到的這個搜尋對應這個文檔的coord值為0.5。

這個因素對所有文檔都是一樣的值,是以它不影響排序結果。比如如果我們希望所有文檔的評分大一點,那麼我們就需要設定這個值。

項t在文檔d中出現的次數

比如有個文檔叫做"this is book about chinese book", 我的搜尋項為"book",那麼這個搜尋項對應文檔的freq就為2,那麼tf值就為根号2,即1.4142135

這裡的兩個值解釋下

docFreq 指的是項出現的文檔數,就是有多少個文檔符合這個搜尋

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的權重,這個就是一個影響值,比如我希望比對chinese的權重更高,就可以把它的boost設定為2

這個項是長度的權重因子,目的是為了将同樣比對的文檔,比較短的放比較前面。

比如兩個文檔:

chinese

chinese book

我搜尋chinese的時候,第一個文檔會放比較前面。因為它更符合"完全比對"。

這裡的doc.getBoost表示文檔的權重,f.getBoost表示字段的權重,如果這兩個都設定為1,那麼nor(t,d)就和lengthNorm一樣的值。

比如我現在有一個文檔:

搜尋的詞語為chinese, 那麼numTerms為2,lengthNorm的值為 1/sqrt(2) = 0.71428571428571。

但是非常遺憾,如果你使用explain去檢視es的時候,發現lengthNorm顯示的隻有0.625。

這個官方給出的原因是精度問題,norm在存儲的時候會進行壓縮,查詢的時候進行解壓,而這個解壓是不可逆的,即decode(encode(0.714)) = 0.625。

比如現在我的檔案為:

搜尋詞為:

explain得到的結果為:

看到這篇文檔的總得分為 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

本文轉自軒脈刃部落格園部落格,原文連結:http://www.cnblogs.com/yjf512/p/4860134.html,如需轉載請自行聯系原作者

繼續閱讀