Dense vector field type
dense_vector
フィールドタイプは数値の密なベクトルを格納します。密なベクトルフィールドは主に k-nearest neighbor (kNN) 検索 に使用されます。
dense_vector
タイプは集約やソートをサポートしていません。
dense_vector
フィールドを、element_type
に基づいて数値の配列として追加します (デフォルトでは float
)。
Python
resp = client.indices.create(
index="my-index",
mappings={
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3
},
"my_text": {
"type": "keyword"
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index",
id="1",
document={
"my_text": "text1",
"my_vector": [
0.5,
10,
6
]
},
)
print(resp1)
resp2 = client.index(
index="my-index",
id="2",
document={
"my_text": "text2",
"my_vector": [
-0.5,
10,
10
]
},
)
print(resp2)
Ruby
response = client.indices.create(
index: 'my-index',
body: {
mappings: {
properties: {
my_vector: {
type: 'dense_vector',
dims: 3
},
my_text: {
type: 'keyword'
}
}
}
}
)
puts response
response = client.index(
index: 'my-index',
id: 1,
body: {
my_text: 'text1',
my_vector: [
0.5,
10,
6
]
}
)
puts response
response = client.index(
index: 'my-index',
id: 2,
body: {
my_text: 'text2',
my_vector: [
-0.5,
10,
10
]
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index",
mappings: {
properties: {
my_vector: {
type: "dense_vector",
dims: 3,
},
my_text: {
type: "keyword",
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index",
id: 1,
document: {
my_text: "text1",
my_vector: [0.5, 10, 6],
},
});
console.log(response1);
const response2 = await client.index({
index: "my-index",
id: 2,
document: {
my_text: "text2",
my_vector: [-0.5, 10, 10],
},
});
console.log(response2);
Console
PUT my-index
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3
},
"my_text" : {
"type" : "keyword"
}
}
}
}
PUT my-index/_doc/1
{
"my_text" : "text1",
"my_vector" : [0.5, 10, 6]
}
PUT my-index/_doc/2
{
"my_text" : "text2",
"my_vector" : [-0.5, 10, 10]
}
他のほとんどのデータタイプとは異なり、密なベクトルは常に単一値です。1つの dense_vector
フィールドに複数の値を格納することはできません。
Index vectors for kNN search
k-nearest neighbor (kNN) 検索は、クエリベクトルに最も近い k 個のベクトルを、類似度メトリックによって測定します。
密なベクトルフィールドは、script_score
クエリ でドキュメントをランク付けするために使用できます。これにより、すべてのドキュメントをスキャンし、類似度によってランク付けすることで、ブルートフォース kNN 検索を実行できます。
多くの場合、ブルートフォース kNN 検索は十分に効率的ではありません。この理由から、dense_vector
タイプは、検索 API の knn
オプション を通じて迅速な kNN 取得をサポートするために、ベクトルを特化したデータ構造にインデックス化することをサポートしています。
サイズが 128 から 4096 の間の float 要素の未マッピング配列フィールドは、デフォルトの類似度 cosine
で dense_vector
として動的にマッピングされます。フィールドを dense_vector
として明示的にマッピングすることで、デフォルトの類似度をオーバーライドできます。
密なベクトルフィールドのインデックス作成はデフォルトで有効になっており、int8_hnsw
としてインデックス化されます。インデックス作成が有効な場合、kNN 検索で使用するベクトルの類似度を定義できます:
Python
resp = client.indices.create(
index="my-index-2",
mappings={
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"similarity": "dot_product"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-index-2',
body: {
mappings: {
properties: {
my_vector: {
type: 'dense_vector',
dims: 3,
similarity: 'dot_product'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-2",
mappings: {
properties: {
my_vector: {
type: "dense_vector",
dims: 3,
similarity: "dot_product",
},
},
},
});
console.log(response);
Console
PUT my-index-2
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"similarity": "dot_product"
}
}
}
}
近似 kNN 検索のためのベクトルのインデックス作成は高コストなプロセスです。index
が有効なベクトルフィールドを含むドキュメントを取り込むのにかなりの時間がかかる場合があります。メモリ要件については、k-nearest neighbor (kNN) 検索 を参照してください。
index
パラメータを false
に設定することで、インデックス作成を無効にできます:
Python
resp = client.indices.create(
index="my-index-2",
mappings={
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"index": False
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-index-2',
body: {
mappings: {
properties: {
my_vector: {
type: 'dense_vector',
dims: 3,
index: false
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-2",
mappings: {
properties: {
my_vector: {
type: "dense_vector",
dims: 3,
index: false,
},
},
},
});
console.log(response);
Console
PUT my-index-2
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"index": false
}
}
}
}
Elasticsearch は、効率的な kNN 検索をサポートするために HNSW アルゴリズム を使用します。ほとんどの kNN アルゴリズムと同様に、HNSW は結果の精度を犠牲にして速度を向上させる近似手法です。
Automatically quantize vectors for kNN search
dense_vector
タイプは、float
ベクトルを検索する際に必要なメモリフットプリントを削減するために量子化をサポートします。次の 2 つの量子化戦略がサポートされています:
int8
- ベクトルの各次元を 1 バイトの整数に量子化します。これにより、いくつかの精度を犠牲にしてメモリフットプリントを 75% 削減できます。 int4
- ベクトルの各次元を半バイトの整数に量子化します。これにより、いくつかの精度を犠牲にしてメモリフットプリントを 87% 削減できます。
量子化されたインデックスを使用するには、インデックスタイプを int8_hnsw
または int4_hnsw
に設定できます。float
ベクトルをインデックス化する場合、現在のデフォルトインデックスタイプは int8_hnsw
です。
量子化は、データのライフサイクル全体にわたって再ランク付け、再インデックス作成、および量子化の改善のために、ディスク上に生の float ベクトル値を保持し続けます。これは、量子化されたベクトルと生のベクトルを保存するオーバーヘッドのために、int8
で ~25%、int4
で ~12.5% のディスク使用量が増加することを意味します。
int4
量子化は、ベクトル次元の偶数を必要とします。
バイト量子化インデックスを作成する方法の例を次に示します:
Python
resp = client.indices.create(
index="my-byte-quantized-index",
mappings={
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"index": True,
"index_options": {
"type": "int8_hnsw"
}
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-byte-quantized-index',
body: {
mappings: {
properties: {
my_vector: {
type: 'dense_vector',
dims: 3,
index: true,
index_options: {
type: 'int8_hnsw'
}
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-byte-quantized-index",
mappings: {
properties: {
my_vector: {
type: "dense_vector",
dims: 3,
index: true,
index_options: {
type: "int8_hnsw",
},
},
},
},
});
console.log(response);
Console
PUT my-byte-quantized-index
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"index": true,
"index_options": {
"type": "int8_hnsw"
}
}
}
}
}
半バイト量子化インデックスを作成する方法の例を次に示します:
Python
resp = client.indices.create(
index="my-byte-quantized-index",
mappings={
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 4,
"index": True,
"index_options": {
"type": "int4_hnsw"
}
}
}
},
)
print(resp)
Js
const response = await client.indices.create({
index: "my-byte-quantized-index",
mappings: {
properties: {
my_vector: {
type: "dense_vector",
dims: 4,
index: true,
index_options: {
type: "int4_hnsw",
},
},
},
},
});
console.log(response);
Console
PUT my-byte-quantized-index
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 4,
"index": true,
"index_options": {
"type": "int4_hnsw"
}
}
}
}
}
Parameters for dense vector fields
次のマッピングパラメータが受け入れられます:
element_type
- (オプション、文字列) ベクトルをエンコードするために使用されるデータタイプ。サポートされているデータタイプは
float
(デフォルト)、byte
、およびビットです。
element_type
の有効な値
float
- 各次元ごとに 4 バイトの浮動小数点値をインデックス化します。これがデフォルト値です。
byte
- 各次元ごとに 1 バイトの整数値をインデックス化します。
bit
各次元ごとに 1 ビットをインデックス化します。非常に高次元のベクトルや、特にビットベクトルをサポートするモデルに便利です。注意:
bit
を使用する場合、次元数は 8 の倍数でなければならず、ビット数を表す必要があります。dims
- (オプション、整数) ベクトル次元の数。
4096
を超えることはできません。dims
が指定されていない場合、フィールドに追加された最初のベクトルの長さに設定されます。 index
(オプション、ブール値)
true
の場合、このフィールドを kNN 検索 API を使用して検索できます。デフォルトはtrue
です。similarity
- (オプション*、文字列) kNN 検索で使用するベクトルの類似度メトリック。ドキュメントは、クエリベクトルに対するベクトルフィールドの類似度によってランク付けされます。各ドキュメントの
_score
は、スコアが正であり、より大きなスコアがより高いランクに対応するように、類似度から導出されます。element_type: bit
が指定されていない場合、l2_norm
にデフォルト設定されます。
bit
ベクトルは、l2_norm
を類似度メトリックとしてのみサポートします。
- このパラメータは、
index
がtrue
の場合にのみ指定できます。
- .
similarity
の有効な値
詳細
l2_norm
- ベクトル間の L2 距離(ユークリッド距離とも呼ばれる)に基づいて類似度を計算します。ドキュメント
_score
は1 / (1 + l2_norm(query, vector)^2)
として計算されます。
bit
ベクトルの場合、l2_norm
を使用する代わりに、ベクトル間の hamming
距離が使用されます。_score
変換は (numBits - hamming(a, b)) / numBits
です。
dot_product
- 2 つの単位ベクトルの内積を計算します。このオプションは、コサイン類似度を計算するための最適化された方法を提供します。制約と計算されたスコアは
element_type
によって定義されます。element_type
がfloat
の場合、すべてのベクトルは単位長でなければならず、ドキュメントベクトルとクエリベクトルの両方を含みます。ドキュメント_score
は(1 + dot_product(query, vector)) / 2
として計算されます。element_type
がbyte
の場合、すべてのベクトルは同じ長さでなければならず、ドキュメントベクトルとクエリベクトルの両方を含むか、結果が不正確になります。ドキュメント_score
は0.5 + (dot_product(query, vector) / (32768 * dims))
として計算され、dims
はベクトルごとの次元数です。 cosine
- コサイン類似度を計算します。インデックス作成中、Elasticsearch は自動的に
cosine
類似度を持つベクトルを単位長に正規化します。これにより、類似度を計算するために内部的にdot_product
を使用できるようになり、より効率的になります。元の未正規化ベクトルには、スクリプトを通じて引き続きアクセスできます。ドキュメント_score
は(1 + cosine(query, vector)) / 2
として計算されます。cosine
類似度は、ゼロの大きさのベクトルを許可しません。コサインはこの場合に定義されていないためです。 max_inner_product
- 2 つのベクトルの最大内積を計算します。これは
dot_product
に似ていますが、ベクトルを正規化する必要はありません。これは、各ベクトルの大きさがスコアに大きく影響する可能性があることを意味します。ドキュメント_score
は負の値を防ぐために調整されます。max_inner_product
値< 0
の場合、_score
は1 / (1 + -1 * max_inner_product(query, vector))
です。非負のmax_inner_product
結果の場合、_score
はmax_inner_product(query, vector) + 1
として計算されます。
similarity
パラメータは、概念的には関連していますが、text
フィールド similarity
とは異なり、異なるオプションセットを受け入れます。
index_options
- (オプション*、オブジェクト) kNN インデックス作成アルゴリズムを構成するオプションセクション。HNSW アルゴリズムには、データ構造の構築に影響を与える 2 つの内部パラメータがあります。これらは、インデックス作成速度が遅くなる代わりに、結果の精度を向上させるために調整できます。
- このパラメータは、
index
がtrue
の場合にのみ指定できます。index_options
のプロパティtype
- (必須、文字列) 使用する kNN アルゴリズムのタイプ。次のいずれかである必要があります:
hnsw
- これは、スケーラブルな近似 kNN 検索のために HNSW アルゴリズム を利用します。これはすべてのelement_type
値をサポートします。int8_hnsw
- 浮動小数点ベクトルのデフォルトインデックスタイプです。これは、element_type
のfloat
に対してスケーラブルな近似 kNN 検索のために HNSW アルゴリズム を自動的にスカラー量子化と共に利用します。これにより、いくつかの精度を犠牲にしてメモリフットプリントを 4 倍削減できます。 kNN 検索のための自動量子化ベクトル を参照してください。int4_hnsw
- これは、element_type
のfloat
に対してスケーラブルな近似 kNN 検索のために HNSW アルゴリズム を自動的にスカラー量子化と共に利用します。これにより、いくつかの精度を犠牲にしてメモリフットプリントを 8 倍削減できます。 kNN 検索のための自動量子化ベクトル を参照してください。flat
- これは、正確な kNN 検索のためにブルートフォース検索アルゴリズムを利用します。これはすべてのelement_type
値をサポートします。int8_flat
- これは、自動的にスカラー量子化を行うブルートフォース検索アルゴリズムを利用します。element_type
のfloat
のみをサポートします。int4_flat
- これは、自動的に半バイトスカラー量子化を行うブルートフォース検索アルゴリズムを利用します。element_type
のfloat
のみをサポートします。
m
- (オプション、整数) HNSW グラフ内の各ノードが接続される隣接ノードの数。デフォルトは
16
です。hnsw
、int8_hnsw
、およびint4_hnsw
インデックスタイプにのみ適用されます。 ef_construction
- (オプション、整数) 各新しいノードの最近傍リストを構成する際に追跡する候補の数。デフォルトは
100
です。hnsw
、int8_hnsw
、およびint4_hnsw
インデックスタイプにのみ適用されます。 confidence_interval
- (オプション、浮動小数点)
int8_hnsw
、int4_hnsw
、int8_flat
、およびint4_flat
インデックスタイプにのみ適用されます。ベクトルを量子化する際に使用する信頼区間。0.90
と1.0
の間の任意の値、または正確に0
である必要があります。値が0
の場合、これは最適化された量子化のために動的量子化を計算することを示します。0.90
と1.0
の間の場合、この値は量子化しきい値を計算する際に使用される値を制限します。たとえば、0.95
の値は、量子化しきい値を計算する際に値の中間 95% のみを使用します(最高および最低の 2.5% の値は無視されます)。1/(dims + 1)
はint8
量子化ベクトルに、0
はint4
の動的量子化計算にデフォルト設定されます。
Synthetic _source
合成 _source
は、TSDB インデックス (index.mode
が time_series
に設定されているインデックス) のみで一般に利用可能です。他のインデックスでは、合成 _source
は技術プレビュー中です。技術プレビューの機能は、将来のリリースで変更または削除される可能性があります。Elastic は問題を修正するために取り組みますが、技術プレビューの機能は公式 GA 機能のサポート SLA の対象ではありません。
dense_vector
フィールドは 合成 _source
をサポートします。
Indexing & Searching bit vectors
element_type: bit
を使用すると、すべてのベクトルがビットベクトルとして扱われます。ビットベクトルは、各次元ごとに単一のビットのみを利用し、内部的にはバイトとしてエンコードされます。これは、非常に高次元のベクトルやモデルに便利です。
bit
を使用する場合、次元数は 8 の倍数でなければならず、ビット数を表す必要があります。さらに、bit
ベクトルでは、典型的なベクトル類似度値は実質的にすべて同じスコアになります。たとえば、hamming
距離を使用します。
2 つの byte[]
配列を比較してみましょう。それぞれが 40 個の個別のビットを表します。
[-127, 0, 1, 42, 127]
ビット 1000000100000000000000010010101001111111
[127, -127, 0, 1, 42]
ビット 0111111110000001000000000000000100101010
これら 2 つのビットベクトルを比較する際、最初に hamming
距離 を取ります。
xor
結果:
1000000100000000000000010010101001111111
^
0111111110000001000000000000000100101010
=
1111111010000001000000010010101101010101
次に、xor
結果の 1
ビットのカウントを集めます: 18
。スコアリングのためにスケールするために、ビットの総数から引き、ビットの総数で割ります: (40 - 18) / 40 = 0.55
。これが、これら 2 つのベクトル間の _score
になります。
ビットベクトルのインデックス作成と検索の例を次に示します:
Python
resp = client.indices.create(
index="my-bit-vectors",
mappings={
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 40,
"element_type": "bit"
}
}
},
)
print(resp)
Js
const response = await client.indices.create({
index: "my-bit-vectors",
mappings: {
properties: {
my_vector: {
type: "dense_vector",
dims: 40,
element_type: "bit",
},
},
},
});
console.log(response);
Console
PUT my-bit-vectors
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 40,
"element_type": "bit"
}
}
}
}
ビット数を表す次元数 |
Python
resp = client.bulk(
index="my-bit-vectors",
refresh=True,
operations=[
{
"index": {
"_id": "1"
}
},
{
"my_vector": [
127,
-127,
0,
1,
42
]
},
{
"index": {
"_id": "2"
}
},
{
"my_vector": "8100012a7f"
}
],
)
print(resp)
Js
const response = await client.bulk({
index: "my-bit-vectors",
refresh: "true",
operations: [
{
index: {
_id: "1",
},
},
{
my_vector: [127, -127, 0, 1, 42],
},
{
index: {
_id: "2",
},
},
{
my_vector: "8100012a7f",
},
],
});
console.log(response);
Console
POST /my-bit-vectors/_bulk?refresh
{"index": {"_id" : "1"}}
{"my_vector": [127, -127, 0, 1, 42]}
{"index": {"_id" : "2"}}
{"my_vector": "8100012a7f"}
40 ビット次元ベクトルを表す 5 バイト | |
40 ビット次元ベクトルを表す 16 進数文字列 |
次に、検索時に knn
クエリを使用して、類似のビットベクトルを検索できます:
Python
resp = client.search(
index="my-bit-vectors",
filter_path="hits.hits",
query={
"knn": {
"query_vector": [
127,
-127,
0,
1,
42
],
"field": "my_vector"
}
},
)
print(resp)
Js
const response = await client.search({
index: "my-bit-vectors",
filter_path: "hits.hits",
query: {
knn: {
query_vector: [127, -127, 0, 1, 42],
field: "my_vector",
},
},
});
console.log(response);
Console
POST /my-bit-vectors/_search?filter_path=hits.hits
{
"query": {
"knn": {
"query_vector": [127, -127, 0, 1, 42],
"field": "my_vector"
}
}
}
Console-Result
{
"hits": {
"hits": [
{
"_index": "my-bit-vectors",
"_id": "1",
"_score": 1.0,
"_source": {
"my_vector": [
127,
-127,
0,
1,
42
]
}
},
{
"_index": "my-bit-vectors",
"_id": "2",
"_score": 0.55,
"_source": {
"my_vector": "8100012a7f"
}
}
]
}
}