music算法_Elasticsearch系列---相关性评分算法及正排索引
概要
上一篇中多次提到了按相關性評分,本篇我們就來簡單了解一下相關性評分的算法,以及正排索引排序的優勢。
評分算法
Elasticsearch進行全文搜索時,Boolean Model是匹配的基礎,先用boolean model將匹配的文檔挑選出來,然后再運用評分函數計算相關度,參與的函數如我們提到的TF/IDF、Length Norm等,再加上一些控制權重的參數設置,得到最后的評分。
Boolean Model
作為全文搜索的基礎,Boolean Model的結果決定文檔是否要進行下一步的評分操作,使用AND、OR、NOT這種邏輯操作符來判斷查找的文檔,整個過程不評分,非常快速地將匹配的文檔篩選出來。
由于Elastisearch各個版本相關度評分算法有異同,我們以6.3.1版本的BM25算法為準。
TFNORM/IDF
由Boolean Model之后得到的文檔,我們開始計算文檔的評分,每個文檔的評分取決于每個關鍵詞在文檔中的權重,權重我們會從以下幾個方面考慮:
TFNORM即詞頻長度(Term Frequency Norm),單個term在文檔中出現的頻率,并結合字段長度,出現次數越高,字段長度越低,分越高,計算公式:
tfNorm(t in d) = (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength))
詞t在文檔d的詞頻(tf):freq表示出現頻率,k1、b為ES參數,fieldLength為該字段長度,avgFieldLength為平均字段長度,公式了解一下即可。
IDF即逆向文檔頻率(inversed document frequency),單個term在所有文檔里出現的頻率是多少?出現次數越高,分越低,計算公式:
idf(t) = log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5))
詞 t 的逆向文檔頻率(idf):索引中文檔數量與該詞的文檔數比率,然后求其對數
例如:"and"、"the","的"、"了"、"呢"這種詞在文檔里到處都是,出現的頻率特別高,反倒是不常出現的詞"Elastic","成都"可以幫助我們快速縮小范圍找到感興趣的文檔。
結果合并一個term經過上面兩個算法計算后,會得到兩個不同的值,這兩個得分相乘得到一個綜合性的分數,這個分數就是最終的_score
我們用explain來看一下這個綜合分數的詳細信息:
搜索請求:
GET /music/children/_search {"explain": true,"query": {"term": {"name": "teeth"}} }響應結果:
{"took": 0,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 1,"max_score": 0.73617005,"hits": [{"_explanation": {"value": 0.7361701,"description": "weight(name:teeth in 1) [PerFieldSimilarity], result of:","details": [{"value": 0.7361701,"description": "score(doc=1,freq=1.0 = termFreq=1.0n), product of:","details": [{"value": 0.6931472,"description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:","details": [{"value": 1,"description": "docFreq","details": []},{"value": 2,"description": "docCount","details": []}]},{"value": 1.0620689,"description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:","details": [{"value": 1,"description": "termFreq=1.0","details": []},{"value": 1.2,"description": "parameter k1","details": []},{"value": 0.75,"description": "parameter b","details": []},{"value": 3.5,"description": "avgFieldLength","details": []},{"value": 3,"description": "fieldLength","details": []}]}]}]}}]} }_explanation節點,里面包含了description、value、details字段,從這里我們可以知道計算的類型,計算結果和任何我們需求的計算細節。從示例中我們可以看到IDF和TF的計算公式和計算結果。
我們可以看到最終得分是0.73617005,其中tfNorm得分1.0620689,idf得分0.6931472,經過相乘1.0620689 * 0.6931472 = 0.73617005
多個term查詢
上面的案例是只有一個term查詢的,如果有多個term查詢,如:
GET /music/children/_search {"explain": true,"query": {"match": {"name": "your teeth"}} }我們可以看到,總的score就是將每個term查詢的score求和。
Lucene公式這里我們先看query score的計算公式:
我們從左往右看,公式依次的含義如下:
- score(D,Q):這個公式最終的結果,Q表示query,D表示doc,表示一個query對一個doc的最終的總得分。
- IDF(qi):idf算法對一個term的值。
- f(xxx)/xxx:這一大串公式,即tf norm的計算公式。
- ∑ 求和符號:idf和tf norm結果相乘,最后求和。
這個求相關性分數的公式了解一下即可,可以結合上面的案例去理解這個公式。
這個公式可以參見wiki: [Okapi BM25]https://en.wikipedia.org/wiki/Okapi_BM25
文檔是如何被匹配到的如果對搜索的結果有異議,我們可以指定文檔ID進行查看,該文檔為什么能被匹配上,也是使用explain參數,示例如下:
GET /music/children/4/_explain {"query": {"match": {"content": "wake up morning"}} }4為文檔ID,此請求的含義表示針對如下的搜索條件,文檔ID為4的記錄是為何能匹配上的,響應的結果也是非常長,節選一部分:
{"_index": "music","_type": "children","_id": "4","matched": true,"explanation": {"value": 0.9549814,"description": "sum of:","details": [{"value": 0.62577873,"description": "weight(content:wake in 0) [PerFieldSimilarity], result of:","details": [{"value": 0.62577873,"description": "score(doc=0,freq=1.0 = termFreq=1.0n), product of:","details": [{"value": 0.6931472,"description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:","details": [{"value": 1,"description": "docFreq","details": []},{"value": 2,"description": "docCount","details": []}]},注意關鍵屬性matched,如果是true,則explanation會有非常詳細的信息,每個分詞后的關鍵詞,相關性得分是多少,都會詳細列舉出來,很多匹配過程的細節,都能在上面找到證據。如果是false,響應報文則是這樣:
{"_index": "music","_type": "children","_id": "1","matched": false,"explanation": {"value": 0,"description": "No matching clauses","details": []} }這是一個非常實用的工具,研發過程中出現讓人困惑的搜索結果,都可以用它進行分析。
正排索引
ES在索引文檔時,會建立倒排索引,倒排索引的檢索性能非常高,但對排序來說,卻不是理想的結構。
因此ES索引文檔時,還會建立正排索引,即Doc Values,這是一種列式存儲結構,默認情況下每個字段都會存儲到Doc Values里。
所以整個搜索排序過程中,正排搜索和倒排搜索是這樣配合的:
- 倒排索引負責關鍵詞的檢索,快速得到匹配的結果集。
- 正排索引完成排序、過濾、聚合的功能,得到期望的文檔順序。
Elasticsearch中的Doc Values常被應用到以下場景:
- 對某個字段排序
- 對某個字段聚合
- 對某個字段過濾
- 某些與字段相關的計算、腳本執行等
Doc Values是被保存到磁盤上的,如果os cache內存足夠,整個working set將自動緩存到內存中,性能非常高,如果內存不充裕,Doc Values會將其寫入到磁盤上。整體來說,性能還是可以的,合理的os cache設置,可以極大地提高查詢的性能。
小結
本篇主要介紹了相關性評分算法的基礎知識,能夠使用工具查看評分的詳細過程,可以輔助解釋一些困惑的現象,最后簡單介紹了一下正排索引的應用場景。
專注Java高并發、分布式架構,更多技術干貨分享與心得,請關注公眾號:Java架構社區
總結
以上是生活随笔為你收集整理的music算法_Elasticsearch系列---相关性评分算法及正排索引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: conda init 关闭和重启shel
- 下一篇: python的property用法_Py