目錄
相關(guān)性
布爾模型
詞頻/逆向文檔頻率(TF/IDF)
詞頻
逆向文檔頻率
字段長度歸一值
結(jié)合使用
向量空間模型
Lucene 的實用評分函數(shù)
近義詞匹配
近義詞查詢原理
同義詞過濾器
糾錯匹配
相關(guān)性
Lucene(或 Elasticsearch)使用?布爾模型(Boolean model)?查找匹配文檔,并用一個名為?實用評分函數(shù)(practical scoring function)?的公式來計算相關(guān)度。這個公式借鑒了?詞頻/逆向文檔頻率(term frequency/inverse document frequency)?和?向量空間模型(vector space model),同時也加入了一些現(xiàn)代的新特性,如協(xié)調(diào)因子(coordination factor),字段長度歸一化(field length normalization),以及詞或查詢語句權(quán)重提升。
布爾模型
布爾模型(Boolean Model)?只是在查詢中使用?AND
?、?OR
?和?NOT
?(與、或和非)這樣的條件來查找匹配的文檔,以下查詢:
full AND text AND search AND (elasticsearch OR lucene)
會將所有包括詞?full
?、?text
?和?search
?,以及?elasticsearch
?或?lucene
?的文檔作為結(jié)果集。
這個過程簡單且快速,它將所有可能不匹配的文檔排除在外。
詞頻/逆向文檔頻率(TF/IDF)
當(dāng)匹配到一組文檔后,需要根據(jù)相關(guān)度排序這些文檔,不是所有的文檔都包含所有詞,有些詞比其他的詞更重要。一個文檔的相關(guān)度評分部分取決于每個查詢詞在文檔中的?權(quán)重?。
詞的權(quán)重由三個因素決定,在?什么是相關(guān)?中已經(jīng)有所介紹,有興趣可以了解下面的公式,但并不要求記住。
詞頻
詞在文檔中出現(xiàn)的頻度是多少?頻度越高,權(quán)重?越高?。 5 次提到同一詞的字段比只提到 1 次的更相關(guān)。詞頻的計算方式如下:
tf(t in d) = √frequency
詞? |
如果不在意詞在某個字段中出現(xiàn)的頻次,而只在意是否出現(xiàn)過,則可以在字段映射中禁用詞頻統(tǒng)計:
PUT /my_index { "mappings": { "doc": { "properties": { "text": { "type": "string", "index_options": "docs" } } } } }
將參數(shù)? |
逆向文檔頻率
詞在集合所有文檔里出現(xiàn)的頻率是多少?頻次越高,權(quán)重?越低?。常用詞如?and
?或?the
?對相關(guān)度貢獻很少,因為它們在多數(shù)文檔中都會出現(xiàn),一些不常見詞如?elastic
?或?hippopotamus
?可以幫助我們快速縮小范圍找到感興趣的文檔。逆向文檔頻率的計算公式如下:
idf(t) = 1 + log ( numDocs / (docFreq + 1))
詞? |
字段長度歸一值
字段的長度是多少?字段越短,字段的權(quán)重?越高?。如果詞出現(xiàn)在類似標(biāo)題?title
?這樣的字段,要比它出現(xiàn)在內(nèi)容?body
?這樣的字段中的相關(guān)度更高。字段長度的歸一值公式如下:
norm(d) = 1 / √numTerms
字段長度歸一值(? |
字段長度的歸一值對全文搜索非常重要,許多其他字段不需要有歸一值。無論文檔是否包括這個字段,索引中每個文檔的每個?string
?字段都大約占用 1 個 byte 的空間。對于?not_analyzed
?字符串字段的歸一值默認(rèn)是禁用的,而對于?analyzed
?字段也可以通過修改字段映射禁用歸一值:
PUT /my_index { "mappings": { "doc": { "properties": { "text": { "type": "string", "norms": { "enabled": false } } } } } }
這個字段不會將字段長度歸一值考慮在內(nèi),長字段和短字段會以相同長度計算評分。 |
對于有些應(yīng)用場景如日志,歸一值不是很有用,要關(guān)心的只是字段是否包含特殊的錯誤碼或者特定的瀏覽器唯一標(biāo)識符。字段的長度對結(jié)果沒有影響,禁用歸一值可以節(jié)省大量內(nèi)存空間。
結(jié)合使用
以下三個因素——詞頻(term frequency)、逆向文檔頻率(inverse document frequency)和字段長度歸一值(field-length norm)——是在索引時計算并存儲的。最后將它們結(jié)合在一起計算單個詞在特定文檔中的?權(quán)重?。
前面公式中提到的?文檔?實際上是指文檔里的某個字段,每個字段都有它自己的倒排索引,因此字段的 TF/IDF 值就是文檔的 TF/IDF 值。
當(dāng)用?explain
?查看一個簡單的?term
?查詢時(參見?explain?),可以發(fā)現(xiàn)與計算相關(guān)度評分的因子就是前面章節(jié)介紹的這些:
PUT /my_index/doc/1 { "text" : "quick brown fox" } GET /my_index/doc/_search?explain { "query": { "term": { "text": "fox" } } }
以上請求(簡化)的?explanation
?解釋如下:
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
詞? |
|
詞? |
|
|
|
該字段的字段長度歸一值。 |
當(dāng)然,查詢通常不止一個詞,所以需要一種合并多詞權(quán)重的方式——向量空間模型(vector space model)。
向量空間模型
向量空間模型(vector space model)?提供一種比較多詞查詢的方式,單個評分代表文檔與查詢的匹配程度,為了做到這點,這個模型將文檔和查詢都以?向量(vectors)?的形式表示:
向量實際上就是包含多個數(shù)的一維數(shù)組,例如:
[1,2,5,22,3,8]
在向量空間模型里,向量空間模型里的每個數(shù)字都代表一個詞的?權(quán)重?,與?詞頻/逆向文檔頻率(term frequency/inverse document frequency)?計算方式類似。
盡管 TF/IDF 是向量空間模型計算詞權(quán)重的默認(rèn)方式,但不是唯一方式。Elasticsearch 還有其他模型如 Okapi-BM25 。TF/IDF 是默認(rèn)的因為它是個經(jīng)檢驗過的簡單又高效的算法,可以提供高質(zhì)量的搜索結(jié)果。
設(shè)想如果查詢 “happy hippopotamus” ,常見詞?happy
?的權(quán)重較低,不常見詞?hippopotamus
?權(quán)重較高,假設(shè)?happy
?的權(quán)重是 2 ,?hippopotamus
?的權(quán)重是 5 ,可以將這個二維向量——?[2,5]
?——在坐標(biāo)系下作條直線,線的起點是 (0,0) 終點是 (2,5) ,如圖?Figure 27, “表示 “happy hippopotamus” 的二維查詢向量”?
在實際中,只有二維向量(兩個詞的查詢)可以在平面上表示,幸運的是,?線性代數(shù)?——作為數(shù)學(xué)中處理向量的一個分支——為我們提供了計算兩個多維向量間角度工具,這意味著可以使用如上同樣的方式來解釋多個詞的查詢。
關(guān)于比較兩個向量的更多信息可以參考?余弦近似度(cosine similarity);
Lucene 的實用評分函數(shù)
對于多詞查詢, Lucene 使用?布爾模型(Boolean model)?、?TF/IDF?以及?向量空間模型(vector space model)?,然后將它們組合到單個高效的包里以收集匹配文檔并進行評分計算。
近義詞匹配
ES近義詞匹配搜索需要用戶提供一張滿足相應(yīng)格式的近義詞表,并在創(chuàng)建索引時設(shè)計將該表放入settings
中。
近義詞表的可以直接以字符串的形式寫入settings
中也可以放入文本文件中,由es讀取。
近義詞表需要滿足以下格式要求:
-
A => B,C
格式- 這種格式在搜索時會將搜索詞A替換成B、C,且B,C互不為同義詞;
-
A,B,C,D
格式
這種格式得分情況討論:
-
當(dāng)
expand == true
時,這種格式等價于A,B,C,D => A,B,C,D
即ABCD互為同義詞 -
當(dāng)
expand == false
時,這種格式等價于A,B,C,D => A,即ABCD四個詞在搜索時會被替換成A
PUT /fond_goods
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 1,
"analysis": {
"analyzer": {
"my_whitespace":{
"tokenizer":"whitespace",
"filter": ["synonymous_filter"]
}
},
"filter": {
"synonymous_filter":{
"type": "synonym",
"expand": true
"synonyms": [
"A, B, C, D"
]
}
}
}
},
"mappings": {
"properties": {
"code":{
"type": "keyword"
},
"context":{
"type": "text",
"analyzer": "my_whitespace"
},
"color":{
"type": "text",
"analyzer": "my_whitespace"
}
}
}
}
-
expand
默認(rèn)值為true
。 -
lenient
默認(rèn)值為false
若lenient
值為true
, es會忽略轉(zhuǎn)換近義詞文件時的報錯。值得注意的是,只有當(dāng)遇到近義詞無法轉(zhuǎn)換時出現(xiàn)的異常才會被忽略掉; -
synonyms
近義詞表,即開始所說要按格式填寫的近義詞表。 -
synonyms
也可替換成synonyms_path
,此時需要填寫一個外部文件的路徑。該文件可以是某個外部的網(wǎng)頁,也可以是存放在本地的文件。 -
format
當(dāng)該參數(shù)值為wordnet
時,可以使用wordnet英文詞匯數(shù)據(jù)庫中的近義詞。
近義詞查詢原理
ES的分詞器主要由字符過濾器(Character Filter)、分詞器(Tokenizer)、分詞過濾器(Token Filter)組成。
- 字符過濾器(Character Filter)
- 以字符流的形式接受文本,并可以通過添加、刪除或更改字符來轉(zhuǎn)化文本。
- 一個Analyzer可以由0個或多個字符過濾器
- 分詞器(Tokenizer)
- 對經(jīng)過字符過濾器過濾后的文本按照一定規(guī)則分詞。一個Analyzer只允許有一個分詞器
- 分詞過濾器(Token Filter)
- 針對分詞后的token再次進行過濾,可以增刪和修改token,一個分詞器中可以有多個token過濾器
同義詞過濾器
同義詞查詢的關(guān)鍵其實就是自定義Token過濾器。該過濾器在收到分詞器發(fā)過來的數(shù)據(jù)(我暫時將其稱之為分詞數(shù)據(jù))時,會先讀取用戶存放的近義詞文件,比對分詞數(shù)據(jù)。當(dāng)出現(xiàn)同義詞時,Token過濾器就按照近義詞文件配置的規(guī)則選定帶搜索詞組,進行同義詞搜索。
我們可以拿之前的索引做個試驗:我們的索引使用的是自定義的分析器my_whitespace
,其中分詞器是whitespace
空格分詞器, 而token Filter 使用的是自定義的近義詞過濾器。由上述可知,我們自定義的分析器與官方自帶的whitespace
分析器唯一的差別就在token Filter上。
糾錯匹配
es中使用phrase Suggester來進行拼寫糾錯。phrase suggester在term suggester之上添加了額外的邏輯以選擇整體更正的phrase,而不是基于單個分詞加權(quán)的ngram語言模型。在實際中phrase suggester能夠根據(jù)單詞的詞頻等信息作出更好的選擇。
ES中常用的4種Suggester類型:Term、Phrase、Completion、Context。
Term suggester正如其名,只基于analyze過的單個term去提供建議,并不會考慮多個term之間的關(guān)系。API調(diào)用方只需為每個token挑選options里的詞,組合在一起返回給用戶前端即可。 那么有無更直接辦法,API直接給出和用戶輸入文本相似的內(nèi)容? 答案是有,這就要求助Phrase Suggester了。
Phrase suggester在Term suggester的基礎(chǔ)上,會考量多個term之間的關(guān)系,比如是否同時出現(xiàn)在索引的原文里,相鄰程度,以及詞頻等等。
Completion Suggester,它主要針對的應(yīng)用場景就是"Auto Completion"。 此場景下用戶每輸入一個字符的時候,就需要即時發(fā)送一次查詢請求到后端查找匹配項,在用戶輸入速度較高的情況下對后端響應(yīng)速度要求比較苛刻。因此實現(xiàn)上它和前面兩個Suggester采用了不同的數(shù)據(jù)結(jié)構(gòu),索引并非通過倒排來完成,而是將analyze過的數(shù)據(jù)編碼成FST和索引一起存放。對于一個open狀態(tài)的索引,F(xiàn)ST會被ES整個裝載到內(nèi)存里的,進行前綴查找速度極快。但是FST只能用于前綴查找,這也是Completion Suggester的局限所在。
Context Suggester,會根據(jù)上下文進行補全,這種方式補全效果較好,但性能較差,用的人不多。這也是es中拼寫糾錯的高級用法。
Lucene中通過Suggest模塊下的SpellChecker功能來實現(xiàn)拼寫糾錯
源碼中,定義了兩個public的靜態(tài)成員變量, DEFAULT_ACCURACY表示默認(rèn)的最小分?jǐn)?shù),SpellCheck會對字典里的每個詞與用戶輸入的搜索關(guān)鍵字進行一個相似度打分,默認(rèn)該值是0.5,相似度分值范圍是0到1之間,數(shù)字越大表示越相似,小于0.5會認(rèn)為不是同一個結(jié)果。F_WORD是對于字典文件里每一行創(chuàng)建索引時使用的默認(rèn)域名稱,默認(rèn)值為:word。
幾個重要的API:文章來源:http://www.zghlxwxcb.cn/news/detail-537147.html
getAccuracy: accuracy是精確度的意思,這里表示最小評分,評分越大表示與用戶輸入的關(guān)鍵字越相似
suggestSimilar:這個方法就是用來決定哪些word會被判定為比較相似的然后以數(shù)組的形式返回,這是SpellChecker的核心;
setComparator:設(shè)置比較器,既然涉及到相似度問題,那肯定有相似度大小問題,有大小必然存在比較,有比較必然需要比較器,通過比較器決定返回的建議詞的順序,因為一般需要把最相關(guān)的顯示在最前面,然后依次排序顯示;
setSpellIndex:設(shè)置拼寫檢查索引目錄的
setStringDistance:設(shè)置編輯距離
?文章來源地址http://www.zghlxwxcb.cn/news/detail-537147.html
到了這里,關(guān)于【Elasticsearch】相關(guān)性,近義詞匹配,糾錯匹配的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!