1. 程式人生 > >[Elasticsearch] 控制相關度 (一) - 相關度分值計算背後的理論

[Elasticsearch] 控制相關度 (一) - 相關度分值計算背後的理論

自己的 提升 del hub 內部 with 字節 frequency 更多

本章翻譯自Elasticsearch官方指南的Controlling Relevance一章。


控制相關度(Controlling Relevance)

對於僅處理結構化數據(比如日期,數值和字符枚舉值)的數據庫,它們只需要檢查一份文檔(在關系數據庫中是一行)是否匹配查詢即可。

盡管布爾類型的YES|NO匹配也是全文搜索的一個必要組成,它們本身是不夠的。我們還需要知道每份文檔和查詢之間的相關程度。全文搜索引擎不僅要找到匹配的文檔,還需要根據相關度對它們進行排序。

全文搜索相關度的公式,或者被稱為相似度算法,將多個因素綜合起來為沒份文檔產生一個相關度_score。在本章中,我們來討論一下其中的一些變化的部分以及如何控制它們。

當然相關度並不只和全文查詢相關;它也許會將結構化數據考慮在內。我們可能在尋找一個擁有某些賣點(空調,海景,免費的WiFi)的度假旅店。那麽當某個度假旅店擁有的賣點越多,那麽它也就越相關。或者我們希望除全文搜索本身的相關度外,同時將時間的遠近,價格,流行度或者距離這類因素也考慮在內。

以上這些設想都是可以實現的,得益於ES中強大的分值計算功能。

我們首先會從理論角度來看看Lucene是如何計算相關度的,然後從實際的例子出發來討論一下如何來控制該過程。


相關度分值計算背後的理論

Lucene(也就是ES)使用了布爾模型(Boolean Model)來尋找匹配的文檔,以及一個被稱為Prarical Scoring Function的公式來計算相關度。該公式借用了詞條頻度/倒排文檔頻度以及向量空間模型的概念,同時也增加了一些更現代的特性比如Coordination Factor,字段長度歸約,以及詞條/查詢子句提升。

NOTE

不要害怕!這些概念並不像它們的名字那般復雜。盡管在這一節中提到了算法,公式以及數學模型,它們的作用也只不過是方便人類理解。理解算法本身並不比理解它們對結果的影響更重要。

布爾模型(Boolean Model)

布爾模型簡單地應用查詢中的AND,OR以及NOT條件來尋找所有匹配的文檔。下面的查詢:

full AND text AND search AND (elasticsearch OR lucene)

會只包括含有所有full,text,search詞條,以及詞條elasticsearch或者lucene之一的文檔。

這個過程是簡單且迅速的。它用來排除那些不會匹配查詢的文檔。

詞條頻度/倒排文檔頻度(TF/IDF)

一旦我們擁有了匹配文檔的列表,我們就需要對它們進行相關度排序。並不是所有的文檔都會包含所有的詞條,而一部分詞條也比另一部分的詞條更加重要。整個文檔的相關度分值取決於(部分)出現在文檔中的每個查詢詞條的權重。

一個詞條的權重通過三個因素決定,這在什麽是相關度中已經介紹過了。對該公式的介紹是為了興趣,你不需要記住它們。

詞條頻度(Term Frequency)

詞條在當前文檔中出現的有多頻繁?越頻繁的話,那麽權重就越高。在一個字段中出現了5次的詞條應該比只出現了1次的文檔更加相關。詞條頻度通過下面的公式進行計算:

tf(t in d) = √frequency

詞條t在文檔d中的詞條頻度tf,是該詞條在文檔中出現次數的平方根。

如果你不在乎一個詞條在一個字段中的出現頻度,相反你在意的是詞條是否出現過,那麽你可以在字段映射中禁用詞條頻度:

將index_options設置為docs會禁用詞條頻度以及詞條位置信息。使用了該設置的字段不會記錄詞條出現的次數,也不能被用在短語或者鄰近度查詢中。精確值的not_analyzed字符串字段默認使用該設置。

倒排文檔頻度(Inverse Document Frequency)

詞條在所有的文檔中出現的頻繁嗎?出現的越頻繁,權重就越低。像and或者the這樣的常見詞條對相關度的貢獻幾乎沒有,因為它們在絕大多數的文檔中都會出現,而像elastic或者hippopotamus這樣的罕見詞條則能夠幫助找到我們最感興趣的文檔。倒排文檔頻度的計算方法如下:

idf(t) = 1 + log ( numDocs / (docFreq + 1))

對於詞條t的倒排文檔頻度(idf),通過將索引中的文檔數量除以含有該詞條的文檔數量,再取其對數得到。

字段長度歸約(Field-length Norm)

字段的有多長?字段越短,那麽其權重就越高。如果一個詞條出現在較短的字段,如title字段中,那麽該字段的內容相比更長的body字段而言,更有可能是關於該詞條的。字段長度歸約的計算方法如下:

norm(d) = 1 / √numTerms

盡管字段長度歸約對於全文搜索而言是重要的,也有許多其它字段不需要。無論文檔是否含有該字段,對於索引中每份文檔的每個字符串字段,歸約大概需消耗1個字節的空間。對於精確值的not_analyzed字符串字段,歸約功能默認是被禁用的,但是你也可以對analyzed類型的字段通過字段映射禁用歸約:

在以上的例子中,該字段不會將字段長度歸約考慮在內。這就意味著字段的長度不再被相關度計算考慮在內。

對於日誌記錄這種用例,歸約是沒有多大用處的。你在意的只是某個特定錯誤代碼或者某個瀏覽器標識碼是否出現在了某個字段中。字段的長度不會對結果造成影響。禁用歸約功能也可以省下相當的內存空間。

結合起來

以上的三個因素 - 詞條頻度,倒排文檔頻度以及字段長度規範 - 都是在索引期間被計算和保存的。它們被用來計算單個詞條對於某一份文檔的權重。

TIP

我們前面討論的文檔,實際上是在討論文檔中的字段。每個字段都有它自己的倒排索引,因此對於TF/IDF而言,字段的值和文檔的值是等效的。

當我們將explain設置為true(參考理解分值(Understanding the Score)),然後再運行簡單的term查詢時,你會發現參與到分值計算過程中的因素就是我們前面討論的那些:

前面的請求得到的解釋(有省略)如下所示:

weight(text:fox in 0) [PerFieldSimilarity]: 0.15342641 result of: fieldWeight in 0 0.15342641 product of: tf(freq=1.0), with freq of 1: 1.0 idf(docFreq=1, maxDocs=1): 0.30685282 fieldNorm(doc=0): 0.5

第一行:對於Lucene內部文檔ID為0的文檔,詞條fox在其text字段中的最終分值。 第五行 - 第七行:詞條頻度,倒排文檔頻度以及字段長度歸約得到的結果。

當然,查詢通常都會由不止一個詞條組成,因此我們需要一種將多個詞條的權重聯系起來的方法。為此我們可以求助向量空間模型(Vector Space Model)。

向量空間模型

向量空間模型提供了一種多詞條查詢的比較方法。它的輸出是一個代表了文檔和查詢之間匹配程度的分值。為了計算該分值,文檔和查詢都被表示成向量。

一個向量實際上就是一個包含了數值的一維數組,比如:

[1,2,5,22,3,8]

在向量空間模型中,向量中的每個數值都是由TF/IDF計算得到的一個詞條的權重。

TIP

盡管TF/IDF是在向量空間模型中默認被用來計算詞條權重的方法,它並不是唯一可用的方法。在ES中,其它諸如Okapi-BM25的計算模型也是可用的。TF/IDF由於其簡潔性,高效性,產生的搜索結果的高質量而經受了時間的考驗,從而被當做是默認方法。

假設我們查詢了"happy hippopotamus"。一個像happy這樣的常見單詞的權重是較低的,然而像hippopotamus這樣的罕見單詞則擁有較高的權重。假設happy的權重為2而hippopotamus的權重為5。我們可以使用坐標來表達這個簡單的二維向量 - [2, 5] - 一條從坐標(0, 0)到坐標(2, 5)的直線,如下所示:

技術分享

現在,假設我們有三份文檔:

  1. I am happy in summer.
  2. After Christmas I’m a hippopotamus.
  3. The happy hippopotamus helped Harry.

我們可以為每份文檔創建一個類似的向量,它由每個查詢詞條的權重組成 - 也就是出現在文檔中的詞條happy和hippopotamus,然後將它繪制在坐標中,如下圖:

  • 文檔1:(happy,____________) — [2,0]
  • 文檔2:( ___ ,hippopotamus) — [0,5]
  • 文檔3:(happy,hippopotamus) — [2,5]

技術分享

向量的一個很棒的性質是它們能夠被比較。通過測量查詢向量和文檔向量間的角度,我們可以給每份文檔計算一個相關度分值。文檔1和查詢之間的角度較大,因此它的相關度較低。文檔2和查詢更靠近,所以它的相關度更高,而文檔3和查詢之間則是一個完美的匹配。

TIP

實際上,只有二維向量(使用兩個詞條的查詢)才能夠被簡單地表示在坐標中。幸運的是,線性代數 - 數學的一個分支,能夠處理向量 - 提供了用來比較多維向量間角度的工具,這意味著我們能夠使用上述原理對包含很多詞條的查詢進行處理。

你可以獲得關於使用余弦相似性來比較兩個向量的更多信息:http://en.wikipedia.org/wiki/Cosine_similarity

我們已經討論了分值計算的理論基礎,現在讓我們看看Lucene是如何進行分值計算的。

[Elasticsearch] 控制相關度 (一) - 相關度分值計算背後的理論