Lucene評分機制

原文地址:TFIDFSimilarity (Lucene 4.9.0 API)

TFIDFSimilarity類中定義了Lucene評分的要素。重寫這些要素計算實現可以方便的修改Lucene的打分機制。

擴展閱讀:Introduction To Information Retrieval, Chapter 6

下面將從信息檢索模型到具體(有效地)實現來描述Lucene如何實現評分。我們首先簡要介紹下向量空間模型評分(VSM Score),之後導出Lucene理論評分公式,並據此最終推導出Lucene實際評分方法(與Lucene實現中使用的類、方法相關聯)

Lucene混合了信息檢索的布爾模型(BM)信息檢索的向量空間模型——通過布爾模型確定文檔並通過VSM進行匹配程度評分。

在向量空間模型中,文檔和查詢被表示爲多維空間中的加權向量集。其每個不同的索引詞(Term)對應一個維度,在此維度上的權重是詞頻/逆向文件頻率(tf-idf)值。

向量空間模型並不要求權重使用tf-idf值,不過tf-idf值被認爲可以高效地評價搜索結果,所以Lucene使用tf-idf。之後將更加詳細的表述詞頻tf和逆向文件頻率idf,但現在(作爲結論)我們先設定:對於給定的詞(Term)t和文檔(或查詢)x,用tf(t,x)表示tx中出現的次數,類似的用idf(t)表示包含詞t的所有文檔數的反比。

文檔d對於查詢q的向量空間模型評分VSM score等於加權查詢向量V(q)V(d)之間的餘弦相似性(Cosine Similarity)


 
cosine-similarity(q,d)   =  
V(q) · V(d)
–––––––––
|V(q)| |V(d)|
VSM Score

 
其中V(q)·V(d)是加權向量的點乘積(dot product)|V(q)||V(d)|是各自的歐幾里得度量(Euclidean norms)(或者被叫作歐幾里得距離、模)。

Note:上述等式可被視作標準化加權向量(V(q)除以它自己的歐幾里得度量,將其標準化爲一個單位向量)的點乘積。

Lucene從搜索質量與可用性方面重新定義了VSM score

  • 將文檔向量V(d)標準化爲單位向量是有問題的,因爲它移除了全部的文檔長度信息。對部分文檔而言,這樣做大概沒有問題,例如一個由重複10遍的相同片段組成的文檔,尤其是這片片段由不同詞組成時。但對另一個不包含重複片段的文檔而言這樣做就可能錯了。爲了避免這個問題,Lucene使用了一個不同的文檔長度標準化因子,其使標準化後的向量等於或大於其單位向量:doc-len-norm(d)。(譯註:這個因子用來取代“1/|V(d)|”)
  • 在創建索引時,用戶可以指定一個確定的文檔要比其他文檔更加重要,通過指定一個文檔加權因子。在這種情況下,各文檔的評分結果也要與這個被稱這爲doc-boost(d)的加權因子值相乘。
  • Lucene是基於域的,因此每個查詢term也要應用到單獨的域上,文檔長度的標準化會基於查詢對應域的長度,而且作爲相對文檔的加權因子的補充文檔域也會存在加權因子。
  • 同一個域在文檔索引時可以多次被重複添加,所以這個域的加權因子是文檔中此域各次添入部分時的加權因子的乘積。
  • 在搜索時用戶可以指定各查詢、子查詢和各查詢term的加權因子,所以查詢term對於文檔評分的貢獻應該乘以查詢term的加權因子:query-boost(q).
  • 一個文檔可能被一個複合的查詢term匹配,即使該文檔不包含查詢中所有的term(對於一些查詢這是正確的),而用戶可以進一步的通過一個協調因子爲匹配更多查詢term的文檔加分,匹配了越多加分越高。協調因子記作coord-factor(q,d)

在上述單個索引域的簡化假定下,我們可以得到Lucene理論評分公式


 
score(q,d)   =   coord-factor(q,d) ·   query-boost(q) ·  
V(q) · V(d)
–––––––––
|V(q)|
  ·   doc-len-norm(d)   ·  doc-boost(d)
Lucene理論評分公式

 

這個理論公式是基於以下前提下的簡化:(1)查詢term和文檔是基於域的(2)加權因子通常是加在查詢term上的而不是查詢上的(譯註:一個查詢可以有衆多的查詢term)

現在我們描述下Lucene如何實現上述理論公式,並導出Lucene實際評分方法

爲了高效率的評分運算,一些評分組成被預先運算集成:

  • 查詢(實際是查詢term)的query-boost在搜索開始時就被告知。
  • 查詢的歐幾里得度量|V(q)|在搜索開始時被算好,因爲它對各文檔打分來說是獨立的(譯註:即對各文檔來說是一致的)。從搜索優化的角度來看,這確實是個很明顯的問題:既然所有的評分文檔將會乘以相同的|V(q)|,這樣文檔的排序(按評分排序)不會被這樣的標準化操作影響,爲什麼要麻煩的做查詢標準化呢?其實有兩個足夠好的理由保留這項標準化操作:
    • 重新調用餘弦相似性(Cosine Similarity)評估可以用來找出兩個文檔間的相似度。用戶可以使用Lucene來進行如聚類這樣的操作,也可以使用一個文檔作爲查詢來計算與其他文檔間的相似程度。出於這種用途,文檔d3對查詢(文檔)d1的評分與其對查詢(文檔)d2的評分之前的比較是很重要的。換言之,同一文檔針對不同查詢之前的評分應該是可比較的。可能其他的程序會需要使用這一特性。而這正是查詢向量V(q)標準化所提供的:在兩個或更多查詢之間的(某種程度上的)可比較性
    • 在評分時應用查詢(向量)標準化可以幫助保持評分結果在單位向量附近,因此可以阻止因浮點數精度限制導致的打分數據損失。
  • 文檔長度標準化因子doc-len-norm(d)和文檔權重因子doc-boost(d)在索引創建時確定。它們已經被事先(譯註:在索引創建時)運算並且它們的乘積已經在索引數據中單獨存儲:norm(d)。(在之後導出的等式中,norm(t in d)意爲norm(field(t) in doc d)其中field(t)是查詢term t對應的域。)

Lucene實際評分方法從之前敘述中得出:

score(q,d)   =   coord(q,d)  ·  queryNorm(q)  ·  ( tf(t in d)  ·  idf(t)2  ·  t.getBoost() ·  norm(t,d) )
  t in q  
Lucene實際評分方法

其中:

  1. tf(t in d)與term的頻率有關,定義爲當前評分的文檔d中term t出現的次數。文檔中出現給定term的次數越多得到的分值越高。注意tf(t in q)被假定爲1,因此它不會出現在等式中,不過,如果一個查詢包含兩次相同的查詢term,那麼將會有兩個具有相同term的term子查詢,因此計算結果仍然會保持正確(雖然不怎麼高效)。DefaultSimilarity中定義的默認的tf(t in d)計算方式爲:
     
    tf(t in d)   =   frequency½

     
  2. idf(t)意爲反向文件頻率。這個值是文檔頻率(docFreq)(出現term t的文檔數)的反比。這意味着罕見的term會爲查詢的總評分貢獻更多的分數。tidf(t)值在查詢和文檔中都會出現因此它在等式中被執行乘方。DefaultSimilarity中定義的默認的idf(t)計算方式爲:
     
    idf(t)  =   1 + log (
    numDocs
    –––––––––
    docFreq+1
    )

     
  3. coord(q,d)是一個基於“在指定文檔中查詢term匹配數”的評分因子。(譯註:term集:field1:query_value1,field2:query_value2,...中匹配數)。典型地,一個匹配更多查詢term的文檔要比一個匹配少的文檔得到更高的分數。這是一個在進行搜索時生效的被Similarity類中的方法coord(q,d)進行運算得出的搜索態因子。
     
  4. queryNorm(q)是一個用於使評分結果在查詢間可以進行比較的標準化因子。這個因子不會影響文檔的排序(因爲所有的排序文檔(的分值)都會乘以相同的因子),而只是嘗試使評分結果在不同查詢間可比較。這是一個在Similarity類中在搜索時生效進行運算得出的搜索態因子。DefaultSimilarity中默認的運算會給出一個歐幾里得度量(Euclidean norms)
     
    queryNorm(q)   =   queryNorm(sumOfSquaredWeights)   =  
    1
    ––––––––––––––
    sumOfSquaredWeights½

     
    (查詢term的)平方加權和通過查詢Weight對象計算。例如,一個BooleanQuery通過如下方式運算出這個值:
     
    sumOfSquaredWeights   =  q.getBoost()2  ·  ( idf(t)  ·  t.getBoost())2
      t in q  

     
  5. t.getBoost()在查詢文本中指定(參見query syntax)或者通過程序調用setBoost()進行設定的查詢q中term t的搜索態加權因子。注意,確實沒有一個直接的API可以訪問一組混合term查詢中的一個term的加權因子,不過混合的term被表示成一個混合了多個TermQuery對象的查詢,於是查詢中的一個term的加權因子可以通過調用子查詢的getBoost()方法來訪問。
     
  6. norm(t,d)封裝了一小部分加權和長度因子(在索引創建階段):
    • Field boost - 在將域加入文檔前通過調用field.setBoost()設定。
    • lengthNorm - 在文檔加入索引時按照文檔中此域包含的token數計算,所以域(包含的token數)越短得分越高。LengthNorm在索引創建時被Similarity類計算。
    computeNorm(org.apache.lucene.index.FieldInvertState)方法負責把結合這些因子運算成一個單獨的浮點數。

    當一個文檔被加入索引時,以上所有因子會被相乘。如果文檔中存在同名的域(譯註:多值域),那麼它們的加權會乘在一起(譯註:即進行乘方運算):

     
    norm(t,d)   =   lengthNorm  ·  f.boost()
      field f in d named as t  
    注意到了執行搜索操作的時候再修改評分的norm(譯註:規則,而不是值)就太晚了, 例如使用一個不同的Similarity類來執行搜索時。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章