Elasticsearch 向量搜尋
本文將會介紹 Elasticsearch 向量搜尋的兩種方式。
向量搜尋
提到向量搜尋,我想你一定想知道:
- 向量搜尋是什麼?
- 向量搜尋的應用場景有哪些?
- 向量搜尋與全文搜尋有何不同?
ES 的全文搜尋簡而言之就是將文字進行分詞,然後基於詞通過 BM25 演算法計算相關性得分,從而找到與搜尋語句相似的文字,其本質上是一種 term-based(基於詞)的搜尋。
全文搜尋的實際使用已經非常廣泛,核心技術也非常成熟。但是,除了文字內容之外,現實生活中還有非常多其它的資料形式,例如:圖片、音訊、視訊等等,我們能不能也對這些資料進行搜尋呢?
答案是 Yes !
隨著機器學習和人工智慧等技術的發展,萬物皆可 Embedding
。換句話說就是,我們可以對文字、圖片、音訊、視訊等等一切資料通過 Embedding 相關技術將其轉換成特徵向量,而一旦向量有了,向量搜尋的需求隨之也越發強烈,向量搜尋的應用場景也變得一望無際、充滿想象力。
ES 向量搜尋說明
ES 向量搜尋目前有兩種方式:
script_score
_knn_search
script_score 精確搜尋
ES 7.6 版本對新增的欄位型別 dense_vector
確認了穩定性保證,這個欄位型別就是用來表示向量資料的。
資料建模示例:
PUT my-index
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 128
},
"my_text" : {
"type" : "keyword"
}
}
}
}
如上圖所示,我們在索引中建立了一個 dims 維度為 128 的向量資料欄位。
script_score
搜尋示例:
{
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "cosineSimilarity(params.query_vector, 'my_vector') + 1.0",
"params": {"query_vector": query_vector}
}
}
}
上圖所示的含義是使用 ES 7.3 版本之後內建的 cosineSimilarity
餘弦相似度函式計算向量之間的相似度得分。
需要注意的是,script_score
這種搜尋方式是先執行 query
,然後對匹配的文件再進行向量相似度算分,其隱含的含義是:
- 資料建模時向量欄位可以與其它欄位型別一起使用,也就是支援混合查詢(先進行全文搜尋,再基於搜尋結果進行向量搜尋)。
script_score
是一種暴力計算,資料集越大,效能損耗就越大。
_knn_search 搜尋
由於 script_score
的效能問題,ES 在 8.0 版本引入了一種新的向量搜尋方法 _knn_search
(目前處於試驗性功能)。
所謂的 _knn_search
其實就是一種 approximate nearest neighbor search (ANN) 即 近似最近鄰搜尋
。這種搜尋方式在犧牲一定準確性的情況下優先追求搜尋效能。
為了使用 _knn_search
搜尋,在資料建模時有所不同。
示例:
PUT my-index-knn
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 128,
"index": true,
"similarity": "dot_product"
}
}
}
}
如上所示,我們必須額外指定:
index
為 true 。similarity
指定向量相似度演算法,可以是l2_norm
、dot_product
、cosine
其中之一。
額外指定 index
為 true 是因為,為了實現 _knn_search
,ES 必須在底層構建一個新的資料結構(目前使用的是 HNSW graph )。
_knn_search
搜尋示例:
GET my-index-knn/_knn_search
{
"knn": {
"field": "my_vector",
"query_vector": [0.3, 0.1, 1.2, ...],
"k": 10,
"num_candidates": 100
},
"_source": ["name", "date"]
}
使用 _knn_search
搜尋的優點就是搜尋速度非常快,缺點就是精確度不是百分百,同時無法與 Query DSL 一起使用,即無法進行混合搜尋。