Here’s the table of contents:
向量數(shù)據(jù)庫:使用Elasticsearch實現(xiàn)向量數(shù)據(jù)存儲與搜索
一、簡介
??Elasticsearch在7.x的版本中支持 向量檢索 。在向量函數(shù)的計算過程中,會對所有匹配的文檔進行線性掃描。因此,查詢預計時間會隨著匹配文檔的數(shù)量線性增長。出于這個原因,建議使用查詢參數(shù)來限制匹配文檔的數(shù)量(類似二次查找的邏輯,先使用
match query
檢索到相關文檔,然后使用向量函數(shù)計算文檔相關度)。
??訪問
dense_vector
的推薦方法是通過cosinessimilarity, dotProduct, 1norm或l2norm函數(shù)。但是需要注意,每個DSL腳本只能調用這些函數(shù)一次。例如,不要在循環(huán)中使用這些函數(shù)來計算文檔向量和多個其他向量之間的相似性。如果需要該功能,可以通過直接訪問向量值來重新實現(xiàn)這些函數(shù)。
二、實驗前準備
2.1 創(chuàng)建索引設置向量字段
??創(chuàng)建一個支持向量檢索的
mapping
,字段類型為dense_vector
。
// 7.x 支持的 dims 最大為 1024。
PUT index3
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3
},
"my_text" : {
"type" : "keyword"
}
}
}
}
2.2 寫入數(shù)據(jù)
PUT index3/_doc/1
{
"my_text" : "text1",
"my_vector" : [0.5, 10, 6]
}
PUT index3/_doc/2
{
"my_text" : "text2",
"my_vector" : [-0.5, 10, 10]
}
三、向量計算函數(shù)
3.1 余弦相似度:cosineSimilarity
??cosinessimilarity函數(shù)計算給定查詢向量和文檔向量之間的余弦相似性度量。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": "cosineSimilarity(params.queryVector, doc['my_vector'])+1.0",
"params": {
"queryVector": [-0.5, 10, 6]
}
}
}
}
}
- 要限制
script_score
計算的文檔數(shù)量,需要提供一個過濾器 (query)。 -
script
腳本在cosineSimilarity
上增加了1.0,以防止得分為負。 - 為了更好的利用DSL優(yōu)化器,可以使用參數(shù)的方式提供一個查詢向量。
- 檢查缺失值:如果文檔中沒有用于執(zhí)行向量函數(shù)的向量字段的值,會拋出錯誤。可以使用
doc['my_vector'].size() == 0
來檢查文檔是否有my_vector
字段的值。腳本樣例:
"source":
"
doc['my_vector'].size() == 0 ? 0 :
cosineSimilarity(params.queryVector, 'my_vector')
"
??如果文檔的
dense_vector
字段與查詢的向量維度不同,就會拋出異常。
3.2 計算點積:dotProduct
??dotProduct函數(shù)計算給定查詢向量和文檔向量之間的點積度量。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": """
double value = dotProduct(params.queryVector,doc['my_vector']);
return sigmoid(1, Math.E, -value);
""",
"params": {
"queryVector": [
-0.5,
10,
6
]
}
}
}
}
}
- 使用標準的
sigmoid
函數(shù)可以防止分數(shù)為負。
3.3 曼哈頓距離:l1norm
??
l1norm
函數(shù)計算給定查詢向量和文檔向量之間的L1距離(曼哈頓距離)。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source":"1 / (1 + l1norm(params.queryVector, doc['my_vector']))",
"params": {
"queryVector": [-0.5, 10, 6]
}
}
}
}
}
- 與表示相似性的余弦相似度不同,
1norm
和l2norm
表示距離或差異。這意味著,向量越相似,由1norm
和l2norm
函數(shù)產生的分數(shù)就越低。因此,當我們需要相似的向量來獲得更高的分數(shù)時,我們將1norm
和l2norm
的輸出反過來。另外,為了避免在文檔向量與查詢完全匹配時被除0,在分母中加了1。
3.4 歐幾里得距離:l2norm
??l2norm函數(shù)計算給定查詢向量和文檔向量之間的L2距離(歐幾里德距離)。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": "1 / (1 + l2norm(params.queryVector, doc['my_vector']))",
"params": {
"queryVector": [
-0.5,
10,
6
]
}
}
}
}
}
3.5 自定義計算函數(shù)
??使用函數(shù)訪問向量的值,自定義實現(xiàn)向量余弦相似度計算。ES 中向量檢索 doc[].vectorValue 函數(shù)是在 Elasticsearch 7.8.0 版本開始支持的,在ES 7.5.1 或 7.8.0 以下版本會運行失敗。
??可以通過以下函數(shù)直接訪問向量值:
-
doc[<field>].vectorValue
– 以浮點數(shù)數(shù)組的形式返回向量的值。文章來源:http://www.zghlxwxcb.cn/news/detail-468010.html -
doc[<field>].magnitude
– 將向量的大小作為浮點數(shù)返回(對于7.5版本之前創(chuàng)建的向量,其向量的大小不會被存儲)。所以這個函數(shù)每次被調用時都會進行重新計算。文章來源地址http://www.zghlxwxcb.cn/news/detail-468010.html
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": """
float[] v = doc['my_vector'].vectorValue;
float vm = doc['my_vector'].magnitude;
float dotProduct = 0;
for (int i = 0; i < v.length; i++) {
dotProduct += v[i] * params.queryVector[i];
}
return dotProduct / (vm * (float) params.queryVectorMag);
""",
"params": {
"queryVector": [
-0.5,
10,
6
],
"queryVectorMag": 5.25357
}
}
}
}
}
到了這里,關于向量數(shù)據(jù)庫:使用Elasticsearch實現(xiàn)向量數(shù)據(jù)存儲與搜索的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!