Alibaba Cloud Elasticsearch V8.0 以降では、k 近傍 (kNN) 検索機能がサポートされており、クエリベクターと最も類似したベクターを検索できます。kNN 検索は、以下のユースケースを実現します。
画像検索およびビデオ指紋:視覚的に類似した画像や、ほぼ重複する動画セグメントを検索します。
顔認証および音声認識:生体認証ベクターを保存済みプロファイルと照合します。
商品推薦:ユーザーのプリファレンスベクターに最も近い特徴ベクターを持つ商品を取得します。
仕組み
データを Elasticsearch インデックス内の dense_vector フィールドとして格納します。kNN 検索を実行すると、Elasticsearch はクエリベクターと各ドキュメントベクター間の類似度を計算し、最も近い k 個のマッチを返します。
利用可能な検索方法は 2 種類です。
| 検索方法 | クエリインタフェース | メモリ内ストレージ | マッピング要件 |
|---|---|---|---|
| 近似 kNN 検索 | Search API の knn パラメーターを使用 | はい | index: true を dense_vector フィールドに設定 |
| 正確な kNN 検索 | script_score クエリとベクトル関数を使用 | はい | index: false を設定するか、空欄のままにします。 |
ほとんどの場合、近似 kNN 検索をご利用ください。 これは、わずかに精度が低下する代わりに、低遅延で結果を返します。正確な kNN 検索は正確な結果を保証しますが、一致したすべてのドキュメントをブルートフォーススキャンするため、大規模なデータセットには適していません。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
Alibaba Cloud Elasticsearch V8.x クラスター。本ガイドでは例として V8.5.1 を使用します。セットアップ手順については、「Alibaba Cloud Elasticsearch クラスターの作成」をご参照ください。
ビジネスデータをベクトル表現に変換し、
dense_vectorフィールドに格納済みであること。選択した類似度メトリックに基づき、クエリとより類似したドキュメントほど、クエリベクターとの距離が小さくなるようにベクターを設計してください。
注意事項
dense_vectorフィールドは集約およびソートをサポートしません。nested型フィールドは近似 kNN 検索をサポートしません。クラスター間検索のシナリオでは、
ccs_minimize_roundtripsパラメーターは kNN 検索と併用できません。kNN 検索では、デフォルトで
dfs_query_then_fetch検索タイプが使用されます。kNN 検索を実行する際には、search_typeパラメーターを明示的に設定できません。
近似 kNN 検索
パフォーマンスに関する考慮事項
近似 kNN 検索では、Hierarchical Navigable Small World (HNSW) グラフを用いて、セグメントごとに密ベクトルをインデックス化します。インデックス作成時の HNSW グラフ構築はリソースを多く消費します。安定したパフォーマンスを維持するには、以下の点に注意してください。
ベクトルデータのインデックス作成時に、クライアントのタイムアウト期間を延長し、バルク書き込みリクエストをご利用ください。
セグメント数を減らすか、すべてのセグメントを 1 つにマージすることで、検索速度を向上させます。
データノードのメモリが、すべてのベクトルデータと HNSW インデックス構造の合計サイズを超えるようにしてください。
近似 kNN 検索を実行中の大規模な書き込みまたは更新操作は避けてください。
インデックスの作成
index: true を設定し、similarity パラメーターを指定して、dense_vector フィールドを定義します。
PUT image-index
{
"mappings": {
"properties": {
"image-vector": {
"type": "dense_vector",
"dims": 3,
"index": true,
"similarity": "l2_norm"
},
"title": {
"type": "text"
},
"file-type": {
"type": "keyword"
}
}
}
}dense_vector フィールドのパラメーター
全パラメーターのリファレンスについては、「dense-vector」をご参照ください。
| パラメーター | 説明 |
|---|---|
type | dense_vector を指定します。 |
dims | ベクターあたりのディメンション数。最大値は、index: true の場合 1024、index: false の場合 2048 です。 |
index | 近似 kNN 検索用の HNSW インデックスを構築するには、true を指定します。デフォルト値は false です。 |
similarity | マッチのスコアリングに使用される類似度アルゴリズムです。index: true の場合に必須です。下記の表をご参照ください。 |
サポートされる類似度アルゴリズム
| 値 | アルゴリズム | スコア算出式 |
|---|---|---|
l2_norm | ユークリッド距離 | 1 / (1 + l2_norm(query, vector)^2) |
dot_product(float) | 内積 — 両方のベクターを単位長に正規化する必要があります | (1 + dot_product(query, vector)) / 2 |
dot_product(byte) | 内積 — 両方のベクターの長さが等しい必要があります | 0.5 + (dot_product(query, vector) / (32768 × dims)) |
cosine | 余弦類似度 | (1 + cosine(query, vector)) / 2 |
cosine アルゴリズムは、値が 0 のベクターをサポートしません。
近似 kNN 検索は Elasticsearch V8.0 以降でサポートされています。V8.0 より前のバージョンからアップグレードされたクラスターの場合、近似 kNN 検索を実行する前に、インデックスを再作成し、index: true を任意の dense_vector フィールドに設定してください。
データの書き込み
POST image-index/_bulk?refresh=true
{ "index": { "_id": "1" } }
{ "image-vector": [1, 5, -20], "title": "ヘラジカの家族", "file-type": "jpg" }
{ "index": { "_id": "2" } }
{ "image-vector": [42, 8, -15], "title": "アルプスの湖", "file-type": "png" }
{ "index": { "_id": "3" } }
{ "image-vector": [15, 11, 23], "title": "満月", "file-type": "jpg" }近似 kNN 検索の実行
Search API の knn パラメーターをご利用ください。kNN 検索 API は Elasticsearch V8.4 以降で非推奨となりました。
POST image-index/_search
{
"knn": {
"field": "image-vector",
"query_vector": [-5, 9, -12],
"k": 10,
"num_candidates": 100
},
"fields": [ "title", "file-type" ]
}kNN 検索のパラメーター
全パラメーターのリファレンスについては、「Search API」をご参照ください。
| パラメーター | 必須 | 説明 |
|---|---|---|
field | はい | 検索対象の dense_vector フィールド名。 |
query_vector | はい | クエリベクター。対象フィールドと同じディメンション数である必要があります。 |
k | はい | 返却する最近傍の数。必ず num_candidates より小さい値を指定してください。 |
num_candidates | はい | シャードあたりに評価される最近傍候補の数。最大値は 10,000 です。値を大きくすると精度は向上しますが、遅延も増加します。 |
filter | いいえ | 検索中に適用されるクエリ DSL フィルターです。フィルターに一致する上位 k 個のドキュメントを返します。省略した場合は、すべてのドキュメントが対象となります。 |
正確な kNN 検索
インデックスの作成
HNSW インデックスの構築をスキップするには、index: false(または空欄)を設定します。
PUT zl-index
{
"mappings": {
"properties": {
"product-vector": {
"type": "dense_vector",
"dims": 5,
"index": false
},
"price": {
"type": "long"
}
}
}
}| パラメーター | 説明 |
|---|---|
type | dense_vector を指定します。 |
dims | ベクターあたりのディメンション数。 |
index | デフォルト値は false です。false を指定するか、空欄のままにすると、正確な kNN 検索の効率が向上します。 |
データの書き込み
POST zl-index/_bulk?refresh=true
{ "index": { "_id": "1" } }
{ "product-vector": [230.0, 300.33, -34.8988, 15.555, -200.0], "price": 1599 }
{ "index": { "_id": "2" } }
{ "product-vector": [-0.5, 100.0, -13.0, 14.8, -156.0], "price": 799 }
{ "index": { "_id": "3" } }
{ "product-vector": [0.5, 111.3, -13.0, 14.8, -156.0], "price": 1099 }正確な kNN 検索の実行
ベクトル関数を含む script_score クエリーをご利用ください。以下の例では cosineSimilarity を使用し、ベクトル関数によって評価されるドキュメント数を制限するためにフィルターを適用しています。これにより、スキャンされるドキュメント数が減少し、パフォーマンスが向上します。
POST zl-index/_search
{
"query": {
"script_score": {
"query": {
"bool": {
"filter": {
"range": {
"price": {
"gte": 1000
}
}
}
}
},
"script": {
"source": "cosineSimilarity(params.queryVector, 'product-vector') + 1.0",
"params": {
"queryVector": [-0.5, 90.0, -10, 14.8, -156.0]
}
}
}
}
}サポートされるベクトル関数
全関数のリファレンスについては、「ベクトルフィールドの関数」をご参照ください。
| 関数 | 説明 |
|---|---|
cosineSimilarity | クエリベクターとドキュメントベクターの間の余弦類似度 |
dotProduct | クエリベクターとドキュメントベクターの内積 |
l1norm | クエリベクターとドキュメントベクターの間の L1 距離(マンハッタン距離) |
l2norm | クエリベクターとドキュメントベクターの間の L2 距離(ユークリッド距離) |
次のステップ
k 近傍 (kNN) 検索 — Elasticsearch リファレンスドキュメント