Elasticsearch搜索相關性排序算法詳解

前言

說明:本文章使用的ES版本是:6.2.4html

在上一篇文章Elasticsearch搜索過程詳解中,介紹了ES的搜索過程。git

接下來咱們具體的看一下ES搜索時,是如何計算文檔相關性得分並用於排序的。github

TF-IDF

在介紹ES計算文檔得分以前,先來看一下TF-IDF算法。算法

TF-IDF(Term Frequency–Inverse Document Frequency)是一種用於信息檢索與文本挖掘的經常使用加權算法。它是一種統計方法,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨着它在文件中出現的次數成正比增長,但同時會隨着它在語料庫中出現的頻率成反比降低。apache

TF-IDF算法原理

TF-IDF其實是兩個算法TFIDF的乘積。api

詞頻(Term Frequency,TF)

詞頻的所在對象是一個具體的文檔,是指一個文檔中出現某個單詞(Term)的頻率(Frequency)。這裏用的是頻率而不是次數,是爲了防止文檔內容過長從而致使某些單詞出現過多。爲了正確評價一個單詞在一個文檔中的重要程度,須要將出現次數歸一化,其算法以下:搜索引擎

$$ tf_i=\frac{n_i}{\sum\nolimits_{k=1}^nn_k} $$人工智能

上面式子中n_i是該詞在文件中的出現次數,而分母code

$$ \sum _{k=1}^nn_k $$orm

則是在文件中全部字詞的出現次數之和。

逆向文件頻率(Inverse Document Frequency,IDF)

逆向文件頻率描述的對象是一個文檔集合中,包含某個單詞的文檔數量。它表示的是一個單詞在一個文檔集合中的廣泛重要程度。將其歸一化的算法入下:

$$ {idf_{i}} =\lg {\frac {|D|}{1+|\{j:t_{i}\in d_{j}\}|}} $$

其中

  • |D|:表示文檔集合中的文件總數
  • |{$j:t_i\in d_j$}| :包含詞語t_i的文件數目(即n_i≠0的文件數目)若是詞語不在數據中,就致使分母爲零,所以通常狀況下使用分母加了一個1

最後

$$ tfidf_i=tf_i\times idf_i $$

某一特定文件內的高詞語頻率,以及該詞語在整個文件集合中的低文件頻率,能夠產生出高權重的tf-idf。所以,tf-idf傾向於過濾掉常見的詞語,保留重要的詞語。

TF—IDF總結

  • TF表示的是一個單詞在一段文本中的重要程度,隨着單詞的增長而增長
  • IDF表示的是一個單詞在一個文檔集合中的重要程度,越稀有權重越高,因此它隨着單詞的增長而下降

TF-IDF算法舉例

用上面的公式,計算一個例子。

假如一篇文件的總詞語數是100個,而詞語「學校」出現了5次,那麼「學校」一詞在該文件中的詞頻(tf)就是

$$ tf_i=5/100=0.05 $$

「學校」一詞在1,000份文件出現過,而文件總數是1,000,000份的話,其逆向文件頻率就是

$$ idf_i = lg(1,000,000 / 1,000)=3 $$

最後的tf-idf的分數爲

$$ tfidf_i = tf_i\times idf_i = 0.05 \times 3= 0.15 $$

OKapi BM25算法原理

BM25(Best Match25)是在信息檢索系統中根據提出的query對document進行評分的算法。

TF-IDF算法是一個可用的算法,但並不太完美。它給出了一個基於統計學的相關分數算法,而BM25算法則是在此之上作出改進以後的算法。(爲何要改進呢?TF-IDF不完美的地方在哪裏?)

  1. 當兩篇描述「人工智能」的文檔A和B,其中A出現「人工智能」100次,B出現「人工智能」200次。兩篇文章的單詞數量都是10000,那麼按照TF-IDF算法,A的tf得分是:0.01,B的tf得分是0.02。得分上B比A多了一倍,可是兩篇文章都是再說人工智能,tf分數不該該相差這麼多。可見單純統計的tf算法在文本內容多的時候是不可靠的
  2. 多篇文檔內容的長度長短不一樣,對tf算法的結果也影響很大,因此須要將文本的長度也考慮到算法當中去

基於上面兩點,BM25算法作出了改進,最終該算法公式以下:

$$ {\displaystyle {\text{score}}(D,Q)=\sum _{i=1}^{n}{\text{IDF}}(q_{i})\cdot {\frac {f(q_{i},D)\cdot (k_{1}+1)}{f(q_{i},D)+k_{1}\cdot \left(1-b+b\cdot {\frac {|D|}{\text{avgdl}}}\right)}}} $$

其中:

  • Q:文檔集合
  • D:具體的文檔
  • ${\text{IDF}}(q_{i})$:就是TF-IDF中的IDF,表示單詞q_{i}在文檔集合Q的IDF值
  • $f(q_{i},D)$:就是TF-IDF中的TF,表示單詞q_{i}在文檔D中的TF值
  • $k_{1}$:詞語頻率飽和度(term frequency saturation)它用於調節飽和度變化的速率。它的值通常介於 1.2 到 2.0 之間。數值越低則飽和的過程越快速。(意味着兩個上面A、B兩個文檔有相同的分數,由於他們都包含大量的「人工智能」這個詞語)。在ES應用中爲1.2
  • $b$:字段長度歸約,將文檔的長度歸約化到所有文檔的平均長度,它的值在 0 和 1 之間,1 意味着所有歸約化,0 則不進行歸約化。在ES的應用中爲0.75
  • $\|D\|$:文本長度
  • $avgdl$:文本平均長度

Lucene相關性算法

注:ES版本6.2.4所用的Lucene jar包版本是:7.2.1

在瞭解了TF-IDF算法以後,再來了解Lucene中的相關性算法就很好理解了。

Lucene中,相關性算法以下:

$$ score(t, q, d)={\sum\nolimits_{t}^n (idf(t) * boost(t) * tfNorm(t, d))} $$

其中:

  • q:文檔集合
  • d:具體的文檔
  • t:單詞
  • score(t, q, d):表示包含查詢詞t的文檔d在文檔集合q中的相關性得分
  • idf(t):逆向文件頻率,ES中,逆向文件頻率的算法是:

$$ {idf_{t}} =\ln {(1 + \frac {docCount-docFreq+0.5}{docFreq+0.5})} $$

docCount:表示文檔總數,docFreq:表示包含單詞t的文檔數量。
  • boost(t):查詢時,指定的單詞的權重,不指定時爲1
  • tfNorm(t, d):單詞頻率權重,它用BM25替代了簡單的TF算法,ES中,其算法以下:

$$ {\displaystyle {\text{tfNorm}}(t,d)={\frac {f(t, d)\cdot (k_{1}+1)}{f(t, d)+k_{1}\cdot \left(1-b+b\cdot {\frac {|D|}{\text{avgdl}}}\right)}}} $$

  • tfNorm(t, d):單詞t在文檔d中的頻率權重
  • f(t, d):單詞t在文檔d中的出現次數
  • $k_{1}$:詞語頻率飽和度,用於控制詞頻對結果的影響,數值越低則單詞數量影響越小。它的值通常介於 1.2 到 2.0 之間。。在ES應用中爲1.2
  • $b$:字段長度歸約,用於控制文本長度對結果的影響,數值越大文本長度影響越小。它的值在 0 和 1 之間,在ES的應用中爲0.75
  • $\|D\|$:文檔d中查詢該字段的文本長度
  • $avgdl$:文檔集合中,全部查詢該字段的平均長度

ES在搜索過程當中,拿到文檔ID以後,就會根據搜索詞,計算每篇文檔的相關性得分,用其進行排序。

系列文章

  1. 搜索引擎ElasticSearch源碼編譯和Debug環境搭建
  2. 搜索引擎ElasticSearch的啓動過程
  3. Elasticsearch建立索引流程
  4. Elasticsearch搜索過程詳解
  5. Elasticsearch搜索相關性排序算法詳解
  6. Elasticsearch中的倒排索引
參考資料:
相關文章
相關標籤/搜索