Lucene4.3進階開發之禮敬如來(十三)

評分功能,在全文檢索中也算是一個很是重要的模塊,由於評分的好壞,直接決定着用戶搜索匹配的相關性,試想一下假如用戶輸入了一個搜索詞,搜索引擎返回了一大堆不相關的信息,或者沒有層次性,重點性的結果,那麼看起來將是一件多麼糟糕的事情。 java

lucene默認的評分機制,用的VSM(Vector  Space Model)空間向量模型,基於TF-IDF的評選方式,TF-IDF(term frequency–inverse document frequency)是一種用於資訊檢索與資訊探勘的經常使用加權技術。用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨着它在文件中出現的次數成正比增長,但同時會隨着它在語料庫中出現的頻率成反比降低。TF-IDF加權的各類形式常被搜索引擎應用,做爲文件與用戶查詢之間相關程度的度量或評級。除了TF-IDF之外,因特網上的搜索引擎還會使用基於連接分析的評級方法,以肯定文件在搜尋結果中出現的順序。 搜索引擎

TF-IDF模型,做爲一種加權策略,在信息檢索,搜索引擎,數據挖掘方面被普遍應用,這種模型在lucene中也獲得了很好的實現。 spa

咱們先來看下,通常經常使用的方法加權,在索引時給某個 code

Field加權 orm

 Field field= new Field("title", "過程", type);
 field.setBoost(10.0f);

這種方式在lucene4.x以前能夠給文檔和域分別進行加權,可是在4.x以後,只能給域加權,廢棄了文檔加權的方式,若是想給文檔加權,就須要對每一個域分別加權,來提高這個文檔的權重。 排序

對比索引時的加權,咱們在檢索時也能夠設置加權boost,代碼示例以下: 繼承

Query q=parser.parse(term);
q.setBoost(8f);//檢索時加權

或者也能夠用,queryparse的解析表達式表示: 索引

Query q=parser.parse("lucene^10 solr^5");

除了,上面的幾種方式外,咱們還能夠自定義評分在源碼級別改變一些打分策略: 文檔

1,coord(int overlap, int maxOverlap),協調因子,這個因素起什麼做用呢, get

舉個例子如今我索引裏面有2條數據: 

(1)中國一個多民族國家 

(2)中國是世界人口大國 

當咱們檢索「中國」的時候,會發現這兩個文檔的評分同樣,由於他們的長度也相等, 

而當咱們檢索「中國   民族」的時候會發現第一個文檔會排在前面並且得分要高,爲何呢? 

overlap的個數,表明咱們在文檔中命中的個數 

maxOverlap的個數,表明着檢索條件裏面的個數==>「中國   民族」2個 

由此咱們假設其餘的條件同樣的狀況下能夠推算出1的得分=2/2=1 

而第二個的評分是=1/2=0.5 

因此文檔1的評分會更好,由於它命中了更多的term。 

在源碼裏方法以下: 

 public float coord(int overlap, int maxOverlap) {
    return overlap / (float)maxOverlap;
  }

2,影響評分的第二個因素queryNorm,這個因素,影響評分,但不影響排序的結果,舉個例子,若是咱們想要把lucene的全部的記錄得分的結果,給總體變大,或變小一些,那麼咱們就能夠調整個參數,來控制總體的得分比率。 

在lucene的源碼裏表示以下方法: 

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

3,影響評分的第三個因素,TF,這個因素表明着一個term在某一篇文檔中,若是它出現的頻次越大,那麼對應的評分就越高,咱們假設,其餘的評分因子都同樣,有以下2篇文檔: 

(1)中國人的一天是怎麼度過的呀? 

(2)咱們是中國人,他們也是中國人 

咱們檢索「中國人」,會發現文檔2的得分會比文檔1的高,由於中國人的這個term,在文檔2中出現了2次,在文檔1中,只出現了一次。由此計算評分得: 

假設基數都同樣是10,那麼文檔1的得分=10*1=10 

而文檔二的得分則是=10*2=20,假設其餘因子都同樣,那麼此時 

文檔2的整體評分就會高於文檔1,在顯示結果時,會優先排在命中結果集的上方。 

lucene源碼裏的方法以下: 

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

4,影響評分的第四個因素IDF,這個參數表明的含義是,在全部的文檔中,若是某個term頻繁出現,那麼這個term就被認爲是廣泛詞,因此它的得分就要被減免。 

舉例以下3個文檔: 

(1)狗是一種聰明的動物。 

(2)貓和狗你更喜歡那個。 

(3)狗的種類也有許多種。 

如今咱們檢索「狗  貓」,結果呢,咱們會發現文檔2排在結果集的首位,爲何呢? 

這其實就是IDF的思想,由於狗這個term在全部的文檔中出現的次數大於貓,因此在IDF進行評分時,會下降其的評分。 

在lucene源碼裏,idf的方法以下: 

注意加1的二個做用第一個是爲了不除數的爲0的狀況,第二個是爲了這個文檔在整個文檔中不存在的時候,避免其的評分爲0的狀況存在。 

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

5,影響評分的第五個因素lengthNorm,這個因素是基於文檔內容的長度計算的。舉例以下: 

有2個文檔: 

(1)中國 

(2)中國人 

這個時候咱們在檢索「中國」的時候,文檔1就會排在文檔2的前面,爲何會這樣呢,明明中國一詞在他們中間都出現了一次,形成這樣狀況出現,偏偏是因爲lucene在計算評分,會將文檔的長度計算在裏面,由於根據常識,較短文本里,出現命中的詞,說明這個詞更加劇要。 

lucene源碼裏的代碼以下: 

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)));
  }

6,lucene裏影響評分的第六個因素,載荷Payload,這個功能是一個高級的功能,能夠存儲時,存儲額外的信息,從而在檢索時,達到從某種類型的數據動態加權。 

舉個例子,咱們可能但願某個XML裏面被若是含有<keyword></keywrod>標記的詞從而擁有更高的加權,這時候咱們就能夠利用載荷實現了,在索引的時候,咱們判斷term裏的標籤標記,若是出現了這個特定標籤的標記的term,咱們就額外存儲它的加權載荷信息,從而再檢索時,來達到一個良好的檢索結果。這時候使用載荷,是一個再好不過的選擇了。 

lucene的源碼裏對載荷的方法描述以下: 

  public float scorePayload(int doc, int start, int end, BytesRef payload) {
    return 1;
  }

除了散仙,上文介紹的6種因素外,加上散仙在文章開始部位介紹的boost放權,目前已經介紹了7種影響打分的因素,固然到這裏,並不意味着,這些就是所有的影響評分的方法了,事實上除了這些,還有一些其餘的自定義評分的方式,這個散仙會在後續的文章裏介紹,大部分的時候,咱們瞭解,利用這些信息,就能解決狠多業務上的需求了,因此咱們能夠在咱們須要的任什麼時候候,均可以繼承DefaultSimilarity類,來重寫和咱們業務相關的最好的打分策略。 

相關文章
相關標籤/搜索