## Lucene默認的打分算法
<div style="text-indent:2em;">
<p> 當談論到查詢的相關性,很重要的一件事就是對于給定的查詢語句,如何計算文檔得分。首先要弄清楚的是文檔得分是什么。文檔得分是一個用來描述查詢語句和文檔之間匹配程度的變量。在本節,我們將學習Lucene默認的打分機制:<b>TF/IDF(term frequency/inverse document frequecy)</b>算法,以及它是如何對相關文檔進行打分排序。理解默認的打分算法對設計復雜查詢語句來說至關重要,特別是在決定各個查詢子句權重的時候。</p>
<h3>匹配文檔的打分因子</h3>
<p>當一個文檔出現在了搜索結果中,這就意味著該文檔與用戶給定的查詢語句是相匹配的。Lucene會對匹配成功的文檔給定一個分數。至少從Lucene這個層面,從打分公式的結果來看,分數值越高,代表文檔相關性越高。 自然而然,我們可以得出:兩個不同的查詢語句對同一個文檔的打分將會有所不同,但是比較這兩個得分是沒有意義的。用戶需要記住的是:我們不僅要避免去比較不同查詢語句對同一個文檔的打分結果,還要避免比較不同查詢語句對文檔打分結果的最大值。這是因為文檔的得分是多個因素共同影響的結果,不僅有權重(boosts)和查詢語句的結構起作用,還有匹配關鍵詞的個數,關鍵詞所在的域,查詢歸一化因子中用到的匹配類型……。在極端情況下,只是因為我們用了自定義打分的查詢對象或者由于倒排索引中詞的動態變化,相似的查詢表達式對于同一個文檔都會產生截然不同的打分。</p>
<p>暫時還是先回來繼續探討打分機制。為了計算出一個文檔的得分,我們必須考慮如下的因素:
<ul>
<li><b>文檔權重(Document boost)</b>:在索引時給某個文檔設置的權重值。</li>
<li><b>域權重(Field boost)</b>:在查詢的時候給某個域設置的權重值。</li>
<li><b>調整因子(Coord)</b>:基于文檔中包含查詢關鍵詞個數計算出來的調整因子。一般而言,如果一個文檔中相比其它的文檔出現了更多的查詢關鍵詞,那么其值越大。</li>
<li><b>逆文檔頻率(Inerse document frequency)</b>:基于Term的一個因子,存在的意義是告訴打分公式一個詞的稀有程度。其值越低,詞越稀有(這里的值是指單純的頻率,即多少個文檔中出現了該詞;而非指Lucene中idf的計算公式)。打分公式利用這個因子提升包含稀有詞文檔的權重。</li>
<li><b>長度歸一化(Length norm)</b>:基于域的一個歸一化因子。其值由給定域中Term的個數決定(在索引文檔的時候已經計算出來了,并且存儲到了索引中)。域越的文本越長,因子的權重越低。這表明Lucene打分公式偏向于域包含Term少的文檔。</li>
<li><b>詞頻(Term frequency)</b>:基于Term的一個因子。用來描述給定Term在一個文檔中出現的次數,詞頻越大,文檔的得分越大。</li>
<li><b>查詢歸一化因子(Query norm)</b>:基于查詢語句的歸一化因子。其值為查詢語句中每一個查詢詞權重的平方和。查詢歸一化因子使得比較不同查詢語句的得分變得可行,當然比較不同查詢語句得分并不總是那么易于實現和可行的。</li>
</ul>
</p>
<h3>TF/IDF打分公式</h3>
<p>接下來看看打分公式的廬山真面目。如果只是為了調整查詢語句之間的關聯關系,用戶不必去理解它的原理。但是至少要知道它是如何工作的。</p>
<h3>Lucene概念上的打分公式</h3>
<p>TF/IDF公式的概念版是下面這個樣子的:</p>
<img src="../conceptual_score_formula.png" />
<p>上面的公式展示了布爾信息檢索模型和向量空間信息檢索模型的組合。我們暫時不去討論它,直接見識實際應用的公式,它是在Lucene實現并且正在使用的公式。
</p>
<br/><!--note structure -->
<div style="height:90px;width:650px;text-indent:0em;">
<div style="float:left;width:13px;height:100%; background:black;">
<img src="../lm.png" height="80px" width="13px" style="margin-top:5px;"/>
</div>
<div style="float:left;width:50px;height:100%;position:relative;">
<img src="../note.png" style="position:absolute; top:30%; "/>
</div>
<div style="float:left; width:550px;height:100%;">
<p style="font-size:13px;"><br/>關于信息檢索中的布爾模型和向量空間模型不在本書的知識范圍。如果想了解更多的相關知識,可以從 http://en.wikipedia.org/wiki/Standard_Boolean_model 和 http://en.wikipedia.org/wiki/Vector_Space_Model 里面了解。 </p>
</div>
<div style="float:left;width:13px;height:100%;background:black;">
<img src="../rm.png" height="80px" width="13px" style="margin-top:5px;"/>
</div>
</div> <!-- end of note structure -->
<br/>
<h3>Lucene實際應用的打分公式</h3>
<p>現在看看Lucene實際應用的打分公式長啥樣:</p>
<img src="../practical_score_formula.png"/>
<p>可以看到,文檔的分數實際上是由查詢語句q和文檔d作為變量的一個函數值。打分公式中有兩部分不直接依賴于查詢詞,它們是coord和queryNorm。 公式的值是這樣計算的,coord和queryNorm兩大部分直接乘以查詢語句中每個查詢詞計算值的總和。</p>
<p>另一方面,這個總和也是由每個查詢詞的詞頻(tf),逆文檔頻率(idf),查詢詞的權重,還有norm,也就是前面說的length norm相乘而得的結果。</p>
<p>聽上去有些復雜吧?不用擔心,這些東西不需要全部記住。用戶只需要知道在進行文檔打分的時候,哪些因素是起決定作用的就可以了。基本上,從前面的公式中可以提煉出以下的幾個規則:</p>
<ul>
<li>匹配到的關鍵詞越稀有,文檔的得分就越高。</li>
<li>文檔的域越小(包含比較少的Term),文檔的得分就越高。</li>
<li>設置的權重(索引和搜索時設置的都可以)越大,文檔得分越高。</li>
</ul>
<p>正如我們所看到的那樣,Lucene會給具有這些特征的文檔打最高分:文檔內容能夠匹配到較多的稀有的搜索關鍵詞,文檔的域包含較少的Term,并且域中的Term多是稀有的。
</p>
<br/><!--note structure -->
<div style="height:90px;width:650px;text-indent:0em;">
<div style="float:left;width:13px;height:100%; background:black;">
<img src="../lm.png" height="80px" width="13px" style="margin-top:5px;"/>
</div>
<div style="float:left;width:50px;height:100%;position:relative;">
<img src="../note.png" style="position:absolute; top:30%; "/>
</div>
<div style="float:left; width:550px;height:100%;">
<p style="font-size:13px;"><br/>如果想了解更多關于Apache Lucene TF/IDF打分公式,請關注Apache Lucene Javadocs中的TFIDFSimilarity類,訪問網址: http://lucene.apache.org/core/4_5_0/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html. </p>
</div>
<div style="float:left;width:13px;height:100%;background:black;">
<img src="../rm.png" height="80px" width="13px" style="margin-top:5px;"/>
</div>
</div> <!-- end of note structure -->
<h3>從ElasticSearch的角度看打分排序</h3>
<p>最為重要的是利用Lucene構建起來的ElasticSearch允許用戶修改默認的打分算法(了解更多相關的知識請參考<i>第3章 索引底層控制</i> 中 <i> 修改Lucene打分算法</i>一節的內容)。但是要記住,ElasticSearch不僅僅是Lucene簡單的封裝,因為在ElasticSearh中,文檔排序并非完全依賴于Apache Lucene的打分算法。ElasticSearch中實現了多種不同的查詢類型,這些查詢類型可以完全控制文檔打分的計算方式(比如 custom_boost_facotr query,constant_score query,custom_score query),ElasticSearch允許通過腳本定制文檔的打分方式。用戶可以利用ElasticSearch 0.90版本支持的重排序(rescore)機制,重新計算搜索到的文檔。也可以通過其它的查詢方式處理topN 結果集,不一而足。</p>
<br/><!--note structure -->
<div style="height:90px;width:650px;text-indent:0em;">
<div style="float:left;width:13px;height:100%; background:black;">
<img src="../lm.png" height="80px" width="13px" style="margin-top:5px;"/>
</div>
<div style="float:left;width:50px;height:100%;position:relative;">
<img src="../note.png" style="position:absolute; top:30%; "/>
</div>
<div style="float:left; width:550px;height:100%;">
<p style="font-size:13px;"><br/>如果想了解更多關于Apache Lucene 的query類型,請參考相關的 Javadocs 。比如: http://lucene.apache.org/core/4_5_0/queries/org/apache/lucene/queries/package-summary.html.</p>
</div>
<div style="float:left;width:13px;height:100%;background:black;">
<img src="../rm.png" height="80px" width="13px" style="margin-top:5px;"/>
</div>
</div> <!-- end of note structure -->
<div></div>
</div>
- 前言
- 第1章 認識Elasticsearch
- 認識Apache Lucene
- 熟悉Lucene
- 總體架構
- 分析你的文本
- Lucene查詢語言
- 認識 ElasticSearch
- 基本概念
- ElasticSearch背后的核心理念
- ElasticSearch的工作原理
- 本章小結
- 第2章 強大的用戶查詢語言DSL
- Lucene默認打分算法
- 查詢重寫機制
- 重排序
- 批處理
- 查詢結果的排序
- Update API
- 使用filters優化查詢
- filters和scope在ElasticSearch Faceting模塊的應用
- 本章小結
- 第3章 索引底層控制
- 第4章 探究分布式索引架構
- 選擇恰當的分片數量和分片副本數量
- 路由功能淺談
- 調整集群的分片分配
- 改變分片的默認分配方式
- 查詢的execution preference
- 學以致用
- 本章小結
- 第5章 管理Elasticsearch
- 選擇正確的directory實現類——存儲模塊
- Discovery模塊的配置
- 索引段數據統計
- 理解ElasticSearch的緩存
- 本章小結
- 第6章 應對突發事件
- 第7章 優化用戶體驗
- 第8章 ElasticSearch Java API
- 第9章 開發ElasticSearch插件