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