Amazon Web Services ブログ
コスト最適化されたベクトルデータベース: Amazon OpenSearch Service の量子化手法の概要
この記事は、Cost Optimized Vector Database: Introduction to Amazon OpenSearch Service quantization techniques を翻訳したものです。
生成 AI アプリケーションの台頭により、セマンティック検索と自然言語検索を実装する必要性が高まっています。これらの高度な検索機能は、企業のコンテンツリポジトリから概念的に関連する文書を検索し、生成 AI モデルのプロンプトとして取得するのに役立ちます。テキスト、画像、音声、動画などの様々なソースリポジトリ内の生データは、埋め込みモデルを使用して、セマンティック検索と自然言語検索を支える標準的な数値表現であるベクトルに変換されます。組織がより高度な大規模言語モデルと基盤モデルを活用して生成 AI アプリケーションを強化するにつれ、補助的な埋め込みモデルも大規模で高次元のベクトル埋め込みを処理できるように進化しています。ベクトル量が拡大するにつれ、メモリ使用量と計算要件が比例して増加し、運用コストが高くなります。この問題を軽減するために、メモリ使用量と計算効率を最適化するための様々な圧縮技術を使用できます。
量子化は、計算量とメモリ使用量を削減し、特に大規模データワークロードのコストを下げることを目的とした、非可逆圧縮技術です。データの種類と量に応じて、様々な圧縮手法があります。一般的な手法は、無限の値 (または比較的大きな有限値のリスト) をより小さな離散値にマッピングすることです。ベクトル圧縮には、主に直積量子化とスカラー量子化の 2 つの手法があります。直積量子化の手法では、元のベクトル次元の配列を複数のサブベクトルに分割し、それぞれのサブベクトルを固定ビット数でエンコードして元のベクトルを表現します。この方法では、元のベクトルではなく、エンコードされたサブベクトルのみを保存し、検索する必要があります。スカラー量子化では、入力ベクトルの各次元が、32 ビット浮動小数点表現からより小さなデータ型にマッピングされます。
Amazon OpenSearch Service は、ベクトルデータベースとして、スカラー量子化と直積量子化の手法をサポートし、メモリ使用量を最適化して運用コストを削減します。
ベクトルデータベースとしての OpenSearch
OpenSearch は、分散型の検索および分析サービスです。OpenSearch の k 最近傍 (k-NN) プラグインを使用すると、ベクトルのインデックス作成、保存、検索できます。ベクトルは knn_vector
型の 32 ビット浮動小数点数配列として OpenSearch に保存され、1 ベクトルあたり最大 16,000 次元までサポートしています。
OpenSearch は、スケーラブルなベクトル検索を提供するために、近似最近傍検索を使用します。近似 k-NN アルゴリズムは、与えられたクエリベクトルに最も近いベクトルを推定して結果を取得します。近似 k-NN を実行する主な手法として、グラフベースの Hierarchical Navigable Small-World (HNSW) とクラスターベースの Inverted File (IVF) の 2 つがあります。これらのデータ構造は、最初のベクトル検索操作中に構築され、メモリにロードされます。ベクトルの量が増加すると、データ構造と検索処理に必要なメモリも比例して増加します。
例えば、32 ビットの浮動小数点データを使用する各 HNSW グラフは、約 1.1 * (4 * d + 8 * m) * num_vectors バイトのメモリを消費します。ここで、num_vectors はインデックス化するベクトルの総数を表し、d はベクトルを生成するために使用する埋め込みモデルによって決定される次元数、m は HSNW グラフの辺の数で、パフォーマンスを調整するためのインデックスパラメータです。この式を使用すると、384 次元で m が 16 の構成におけるベクトル格納のメモリ要件は次のようになります。
- 100 万ベクトル: 1.830 GB (1.1 * (4 * 384 + 8 * 16) * 1,000,000 バイト)
- 10 億ベクトル: 1830 GB (1.1 * (4 * 384 + 8 * 16) * 1,000,000,000 バイト)
近似最近傍検索は、数十億ものベクトルを含む大規模データセットを効率的に処理するように最適化できますが、検索処理中に 32 ビットの完全な精度のベクトルをロードするためのメモリ要件が非常に高くなる可能性があります。この問題を緩和するために、OpenSearch Service では次の 4 つの量子化手法をサポートしています。
- バイナリ量子化
- バイト量子化
- FP16 量子化
- 直積量子化
これらの手法は、前述のスカラー量子化とプロダクト量子化の広範なカテゴリに含まれます。この投稿では、OpenSearch Service でベクトルワークロードを最適化するための量子化手法について、メモリ削減とコスト効率に焦点を当てて説明します。メモリにロードせずにディスクに保存されたベクトルを効率的にクエリできる、新しいディスクベースのベクトル検索アプローチを紹介します。この手法は、on_disk
モードや compression_level
パラメータなどの主要な設定を備え、量子化手法とシームレスに統合されています。これらの設定により、インデックス作成時に組み込みのスカラー量子化がすぐに利用できます。
バイナリ量子化 (最大 32 倍の圧縮)
バイナリ量子化 (BQ) はスカラー量子化の一種です。OpenSearch は FAISS エンジンのバイナリ量子化を活用し、インデックス作成時に最大 32 倍の圧縮を可能にしています。この手法では、デフォルトの 32 ビット浮動小数点からベクトルを 0 と 1 に圧縮することで、ベクトル次元を 1 ビットのバイナリに削減します。OpenSearch はバイナリベクトルのインデックス作成、保存、検索をサポートしています。また、下の例に示すように、目的の圧縮率に応じて、各ベクトル次元を 1、2、または 4 ビットでエンコードすることもできます。圧縮率は bits
設定で調整できます。2 の値では 16 倍の圧縮、4 の値では 8 倍の圧縮になります。デフォルト設定は 1 です。バイナリ量子化では、インデックス作成時に自動的に学習が行われるため、追加の前処理ステップは不要です。
バイナリ量子化を実装するには、ベクトル型を knn_vector
と定義し、encoder
を binary
に指定して、エンコードするビット数 bits
を指定します。encoder パラメータは、インデックスに格納する前にベクトルデータを圧縮する方法を指す点に注意してください。パフォーマンスを最適化するために、space_type
、m
、ef_construction
パラメータを使用します。近似 k-NN の基盤となる設定の詳細については、OpenSearch のドキュメントを参照してください。
FAISS-HNSW を使用したバイナリ量子化の実装におけるメモリ要件はこのようになります。
1.1 * (bits * (d/8)+ 8 * m) * num_vectors バイト
圧縮率 | エンコードビット数 |
10 億ベクトルのメモリ要件 (d=384, m=16, GB単位) |
32x | 1 | 193.6 |
16x | 2 | 246.4 |
8x | 4 | 352.0 |
バイナリ量子化の詳細な実装手順については、OpenSearch のドキュメントを参照してください。
バイト量子化 (4 倍の圧縮)
バイト量子化は、32 ビットの浮動小数点次元を -128 から + 127 の範囲の 8 ビット整数に圧縮し、メモリ使用量を 75% 削減します。OpenSearch では、バイトベクトルのインデックス作成、格納、検索がサポートされており、取り込む前に 8 ビット形式に変換する必要があります。バイトベクトルを実装するには、インデックスマッピングで k-NN ベクトルフィールドの data_type
を byte
と指定します。この機能は Lucene エンジンと FAISS エンジンの両方と互換性があります。バイト量子化ベクトルのインデックスを作成する例を次に示します。
この方法では、バイト量子化ベクトルを OpenSearch に取り込み、k-NN ベクトルフィールド (バイト型) に直接格納する必要があります。しかし、最近導入されたディスクベースのベクトル検索機能により、外部ベクトル量子化の必要がなくなりました。このブログの後半で、この機能について詳しく説明します。
FAISS-HNSW でバイト量子化を実装するためのメモリ要件はこのようになります。
1.1 * (1 * d + 8 * m) * num_vectors バイト
詳細な実装手順については、OpenSearch のドキュメントを参照してください。精度、スループット、レイテンシーに関するパフォーマンスメトリクスについては、OpenSearch のバイト量子化ベクトルを参照してください。
FAISS FP16 量子化 (2 倍の圧縮)
FP16 量子化は、16 ビットの浮動小数点スカラー表現を使用する手法で、メモリ使用量を 50% 削減します。各ベクトル次元は 32 ビットから 16 ビットの浮動小数点に変換され、メモリ要件が実質的に半分になります。圧縮されたベクトル次元は [-65504.0、65504.0] の範囲内でなければなりません。FP16 量子化を実装するには、k-NN ベクトルフィールドでインデックスを作成し、以下を構成します。
- k-NN ベクトルフィールドのメソッドを HNSW に、エンジンを FAISS に設定します。
- エンコーダーパラメーターを定義し、
name
をsq
、type
をfp16
に設定します。
32 ビット浮動小数点ベクトルを OpenSearch にアップロードすると、スカラー量子化 FP16 (SQfp16) が自動的に取り込み時にそれらを 16 ビット浮動小数点ベクトルに量子化し、ベクトルフィールドに格納します。次の例は、FP16 量子化ベクトルを量子化して格納するためのインデックス作成方法を示しています。
FAISS-HNSW を使用して FP16 量子化を実装するためのメモリ要件は以下のようになります。
(1.1 * (2 * d + 8 * m) * num_vectors) バイト
前述の FP16 の例では、clip
というオプショナルな Boolean パラメータが導入されています。これはデフォルトで false
に設定されています。false の場合、範囲外の値 (-65504.0 から + 65504.0 の範囲外の値) を持つベクトルは拒否されます。clip を true に設定すると、範囲外のベクトル値がサポートされる範囲内に丸められます。実装手順の詳細については、OpenSearch のドキュメントを参照してください。精度、スループット、レイテンシーに関するパフォーマンスメトリクスについては、Optimizing OpenSearch with Faiss FP16 scalar quantization: Enhancing memory efficiency and cost-effectiveness を参照してください。
直積量子化
直積量子化 (PQ) は、圧縮レベルを大幅に高めることができる高度な次元削減手法です。従来のスカラー量子化手法は通常 32 倍までの圧縮しか実現できませんが、PQ では最大 64 倍の圧縮が可能なため、ストレージとコストの最適化においてより効率的なソリューションとなります。OpenSearch は、FAISS エンジンの IVF および HNSW の両方の手法で PQ をサポートしています。直積量子化は、ベクトルを m
個のサブベクトルに分割し、各サブベクトルをコードサイズで決まるビット数でエンコードします。結果として得られるベクトルのメモリ使用量は m * code_size ビットになります。
FAISS における直積量子化のプロセスは、以下の 3 つの主要なステップで構成されます。
- PQ モデルを構築するためのトレーニングインデックスを作成し、データを投入して精度を最適化する。
- トレーニングインデックスに対して
_train
API を実行し、量子化モデルを生成する。 - ベクトルインデックスを作成し、kNN フィールドを準備した量子化モデルで構成する。
以下の例では、直積量子化のセットアップ手順を 3 つのステップで説明します。
ステップ 1: トレーニングインデックスを作成します。トレーニングインデックスの仕様と次元数が合うように、適切なデータセットでトレーニングインデックスを構築します。トレーニングインデックスには最低 256 件のドキュメントが必要であることに注意してください。
ステップ 2: 先ほど作成したトレーニングインデックスに対して _train
API を実行し、my-model という名前の量子化モデルを作成します。name
が pq
と定義された encoder
では、ネイティブのベクトル量子化が適用されます。エンコーダーの他のパラメーターには code_size
と m
があります。FAISS-HNSW では code_size
を 8 に設定し、少なくとも 256 (2^code_size) 件のドキュメントからなるトレーニングデータセットが必要です。パラメーターの詳細な仕様については、PQ パラメータを参照してください。
ステップ 3: ベクトルインデックスに量子化モデルをマッピングします。
新しく作成したインデックス my-vector-index
にデータセット全体を取り込みます。エンコーダーは、受け取ったベクトルを自動的に処理し、量子化モデルの設定で指定された圧縮パラメータ(code_size
と m
)に基づいてエンコードおよび量子化を適用します。
FAISS-HNSW を使用した直積量子化を実装するためのメモリ要件はこのようになります。
1.1 * (((code_size / 8) * m + 24 + 8 * m) * num_vectors バイト
ここで code_size
と m
はエンコーダーパラメータ内のパラメータ、num_vectors
はベクトルの総数です。
量子化処理では、各トレーニングベクトルは設定可能な値 m で定義された複数のサブベクトルまたはサブスペースに分割されます。各サブベクトルをエンコードするビット数は、パラメータ code_size
によって決まります。次に、各サブベクトルは k-means クラスタリングを実行してそれぞれ圧縮・量子化されます。この際、クラスタの数 k は 2^code_size と定義されます。この手法では、ベクトルは約 m * code_size ビットで圧縮されます。
直積量子化の詳細な実装手順や設定可能なパラメータについては、OpenSearch ドキュメントを参照してください。FAISS IVF を使用した PQ の精度、スループット、レイテンシーに関するパフォーマンス指標については、OpenSearch における 10 億規模のユースケースに適した k-NN アルゴリズムの選定を参照してください。
ディスクベースのベクトル検索
ディスクベースのベクトル検索は、圧縮されたベクトルをメモリ内で使用しながら、完全な精度のベクトルをディスク上に保持することで、クエリの効率を最適化します。このアプローチにより、OpenSearch は大規模なベクトルデータセットをメモリに完全に読み込む必要がなくなり、スケーラビリティとリソースの効率が向上します。この機能は、インデックス作成時に設定できる mode と compression level という 2 つの新しい構成オプションによって実装されます。OpenSearch 2.17 以降では、インデックス作成時に mode パラメータを in_memory
または on_disk
に設定できます。これまで説明した手法はデフォルトで in-memory モードになります。この構成では、ベクトルインデックスがグラフ (HNSW) またはバケット (IVF) 構造を使用して構築され、検索操作時にネイティブメモリにロードされます。この方法は優れた再現率を提供しますが、メモリ使用量に影響を与え、大量のベクトル処理に対するスケーラビリティが低下する可能性があります。
on_disk
モードは、インデックス作成時にリアルタイムのネイティブ量子化を使用しながら、完全な精度のベクトルをディスクに保存することで、ベクトル検索の効率を最適化します。調整可能な圧縮レベルと組み合わせることで、圧縮されたベクトルのみをメモリにロードするため、メモリおよびリソースの利用効率が向上し、検索パフォーマンスが改善されます。以下の圧縮レベルは、前述の様々なスカラー量子化手法に対応しています。
- 32 倍: バイナリ量子化 (1 ビット次元)
- 4 倍: バイトおよび整数量子化 (8 ビット次元)
- 2 倍: FP16 量子化 (16 ビット次元)
この手法は、in_memory モードでは利用できない 16x や 8x などの他の圧縮レベルもサポートしています。ディスクベースのベクトル検索を有効にするには、次の例のように mode を on_disk
に設定してインデックスを作成します。
モードを on_disk
に設定するだけでは、デフォルトの構成が適用され、FAISS エンジンと HNSW メソッドが使用され、32 倍の圧縮レベル (1 ビット、バイナリ量子化) が使用されます。インデックス作成時の待ち時間を最適化する ef_construction
のデフォルト値は 100 です。より細かい微調整を行う場合は、次の例のように、これらの k-NN パラメータを上書きできます。
量子化は非可逆圧縮の手法なので、圧縮率が高くなるほど再現率が低下する傾向があります。量子化時の再現率を改善するには、次の例のように、検索時の設定パラメータ ef_search
と oversample_factor
を使って、ディスクベースのベクトル検索を 2 段階で実行するよう設定できます。
最初の段階では、メモリ内の量子化ベクトルから oversample_factor * k 個の結果を取得し、スコアを近似計算します。次の段階では、その oversample_factor * k 個の結果の完全な精度ベクトルをディスクからメモリにロードし、完全な精度のクエリベクトルと比較してスコアを再計算します。その後、結果は上位 k 個に絞られます。
リスコア用の oversample_factor
は、インデックス作成時に設定された次元数と圧縮レベルによって決まります。次元が 1,000 未満の場合、係数は 5 に固定されます。1,000 を超える次元の場合、デフォルトのファクターは圧縮レベルに基づいて変わり、次の表のようになります。
圧縮レベル | リスコア用の oversample_factor のデフォルト値 |
32x (デフォルト) | 3 |
16x | 2 |
8x | 2 |
4x | デフォルトのリスコアリングなし |
2x | デフォルトのリスコアリングなし |
前述のように、oversample_factor
は検索時に動的に調整できます。この値は、精度と検索効率の間の重要なトレードオフを表します。高い値を設定すると精度は向上しますが、メモリ使用量が比例して増加し、検索スループットが低下します。ディスクベースのベクトル検索と oversample_factor の適切な使用方法を理解するには、OpenSearch のドキュメントを参照してください。
量子化手法のパフォーマンス評価: メモリ使用量、再現率、クエリレイテンシーの検証
OpenSearch の近似 k-NN 検索に関するドキュメントは、ベクトル類似度検索を実装する際の出発点となります。さらに、OpenSearch における 10 億規模のユースケースに適した k-NN アルゴリズムの選定では、本番環境で数十億規模のベクトルを扱うための効率的なベクトルワークロードの設計に関する貴重な洞察が得られます。この記事では、メモリ使用量を削減し、コストを抑える手法として、直積量子化技術を導入することを提案しています。
次の表は、さまざまな量子化手法を使用して 10 億ベクトルを保存および検索する際のメモリ要件を示しています。この表は、HNSW を使用した完全な精度ベクトルのデフォルトのメモリ消費量と、量子化されたベクトルのメモリ消費量を比較しています。この分析で使用されたモデルは sentence-transformers/all-MiniLM-L12-v2 で、384 次元で動作します。生のメタデータは 100GB 以下と想定されています。
量子化なし (GB 単位) |
直積量子化 (GB 単位) |
スカラー量子化 (GB 単位) |
|||
FP16 ベクトル | バイトベクトル | バイナリベクトル | |||
m |
16 | 16 | 16 | 16 | 16 |
pq_m、code_size | – | 16, 8 | – | – | – |
ネイティブメモリ消費量 (GB) | 1830.4 | 184.8 | 985.6 | 563.2 | 193.6 |
合計ストレージ= 100 GB + ベクトル |
1930.4 | 284.8 | 1085.6 | 663.2 | 293.6 |
前の表を見直すと、10 億ベクトルのデータセットに対して、32 ビットの完全な精度のベクトルを使用する HNSW グラフでは約 1830 GB のメモリが必要になることがわかります。直積量子化などの圧縮技術を使えば、これを 184.8 GB に削減できます。一方、スカラー量子化では、さまざまなレベルの圧縮が可能です。次の表は、圧縮手法とコスト削減、再現率、クエリレイテンシーなどの主要パフォーマンス指標への影響の相関関係をまとめたものです。この分析は、上記のメモリ使用量の評価に基づいており、要件を満たす圧縮手法を選択する際の助けとなります。
この表には、2 つの主要な検索メトリクスが示されています。90 パーセンタイル (p90) での検索レイテンシーと、上位 100 件における再現率です。
- 検索レイテンシー@p90 – 90% の検索クエリがその特定のレイテンシー時間以内に完了することを示します。
- recall@100 – 上位 100 件の正解となる近傍点のうち、返された 100 件の結果に含まれる割合です。
量子化なし (GB 単位) |
直積量子化 (GB 単位) |
スカラー量子化 (GB 単位) |
|||
FP16 量子化 [mode=in_memory] |
バイト量子化 [mode=in_memory] |
バイナリ量子化 [mode=on_disk] |
|||
前提条件/データセット | すべてのデータセットに適用可能 | 再現率は学習データの性質に依存 | 次元値が [-65536 から 65535] の範囲内で動作 |
次元値が [-128 から 127] の範囲内で動作 |
次元数 >= 768 の場合に適している |
前処理の必要性 | なし | あり (前処理/学習が必要) |
なし | なし | なし |
リスコアリング | なし | なし | なし | なし | あり |
再現率 @100 | >=0.99 | >0.7 | >=0.95 | >=0.95 | >=0.90 |
p90 クエリレイテンシー (ms) | <50 ms | <50 ms | <50 ms | <50 ms | <200 ms |
コスト (ベースライン $X) |
$X | $0.1*X (最大 90% の削減) |
$0.5*X (最大 50% の削減) |
$0.25*X (最大 75% の削減) |
$0.15*X (最大 85% の削減) |
10 億ベクトルのサンプルコスト | $20,923.14 | $2,092.31 | $10,461.57 | $5,230.79 | $3,138.47 |
10 億ベクトルのサンプルコストの見積もりは、コストを最適化された構成に基づいています。ただし、実際の削減額は、ワークロードの要件と選択した構成のパラメータによって異なる可能性があることにご注意ください。特に表では、直積量子化を使用すると、ベースラインの HNSW グラフベースのベクトル検索コスト ($X) と比較して最大 90% のコスト削減が可能です。スカラー量子化も同様に、圧縮されたメモリ使用量に応じて 50% から 85% の比例的なコスト削減をもたらします。圧縮手法の選択には、コスト効率、精度、パフォーマンスのバランスが関係し、精度やレイテンシーに影響を与えます。
結論
OpenSearch の量子化手法を活用することで、組織はコスト効率、パフォーマンス、再現率のバランスを考慮した選択が可能になり、最適な結果を得るためにベクトルデータベースの操作を微調整できるようになります。これらの量子化手法は、メモリ要件を大幅に削減し、クエリの効率を向上させ、シームレスな圧縮のための組み込みエンコーダーを提供します。大規模なテキスト埋め込み、画像特徴量、その他の高次元データのいずれを扱う場合でも、OpenSearch の量子化手法はベクトル検索の要件に対する効率的なソリューションを提供し、コスト効率が高く、スケーラブルで高性能なシステムの開発を可能にします。
ベクトルデータベースプロジェクトを進める際は、以下のことをお勧めします。
- OpenSearch の圧縮手法を詳しく検討する。
- 特定のユースケースに適した手法の適用可能性を評価する。
- 再現率と検索レイテンシーの要件に基づいて適切な圧縮レベルを決定する。
- 精度、スループット、レイテンシーに基づいてコスト削減効果を測定し比較する。
この分野は急速に進化しているため、最新の技術動向を常に把握し、さまざまな量子化技術を試すことで、コスト・パフォーマンス・精度の最適なバランスを見つけることが重要です。