次の方法で共有


量子化、ナロー データ型、ストレージ オプションを使用してベクトル サイズを小さくする

この記事では、Azure AI 検索でベクトル量子化やその他の手法を使用してベクトル サイズを小さくする方法について説明します。 検索インデックスは、保存されたデータ型とナロー データ型のプロパティを含むベクトル フィールド定義を指定します。 量子化もインデックスで指定され、ベクトル プロファイルを介してベクトル フィールドに割り当てられます。

これらの機能は、2024-07-01 REST API と、そのバージョンを対象とする Azure SDK パッケージで一般提供されています。 この記事の最後のは、この記事で説明する各アプローチのベクトル サイズのバリエーションを示しています。

オプションを評価する

最初の手順として、ベクトル フィールドが使用するストレージの量を減らすための 3 つのアプローチを確認します。 これらのアプローチは相互に排他的ではなく、組み合わせることでベクトル サイズを最大限に削減できます。

組み込みの量子化をお勧めします。これは、メモリ "および" ディスク上のベクトル サイズを最小限の労力で圧縮し、ほとんどのシナリオで最大のメリットが得られる傾向があるためです。 一方、ナロー型 (float16 以外) では作成に労力を要し、stored で節約できるのは、メモリよりも安価なディスク ストレージです。

アプローチ このオプションを使用する理由
スカラーまたはバイナリ量子化を追加する 量子化を使用して、ネイティブ float32 または float16 埋め込みを int8 (スカラー) または Byte (バイナリ) に圧縮します。 このオプションを使用すると、クエリのパフォーマンスを悪化させずにメモリとディスク上のストレージを削減できます。 int8 や Byte のようなより小さなデータ型を使用すると、より大きな埋め込みよりもコンテンツが豊富ではないベクトル インデックスが生成されます。 情報の損失を緩和するために、組み込みの圧縮機能には、非圧縮の埋め込みとオーバーサンプリングを使用してより関連性の高い結果を返すクエリ後の処理オプションが含まれます。 再ランク付けとオーバーサンプリングは、float32 または float16 フィールドの組み込み量子化の特定の機能であり、カスタム量子化の対象となる埋め込みでは使用できません。
ベクトル フィールドにより小さいプリミティブ データ型を割り当てる float16、int16、int8、および Byte (バイナリ) などのナロー データ型では、メモリとディスクの使用量が少なくなりますが、ベクトルをナロー データ形式で出力する埋め込みモデルが必要です。 または、小さなデータを出力するカスタム量子化ロジックが必要です。 3 番目のユース ケースでは、必要な労力が少なく、ほとんどのモデルによって生成されたネイティブ float32 埋め込みが float16 に再キャストされます。 バイナリ ベクトルの詳細については、バイナリ ベクトルのインデックスに関する記事をご覧ください。
取得可能なベクトルのオプションのストレージを排除する クエリの応答で返されるベクトルは、クエリの実行中に使用されるベクトルとは別に保存されます。 ベクトルを返す必要がない場合は、取得可能なストレージをオフにすることで、フィールドごとの全体的なストレージを最大 50% 削減できます。

これらのオプションはすべて空のインデックス上で定義します。 これらのいずれかを実装するには、Azure portal、REST API、または その API バージョンを対象とする Azure SDK パッケージを使用します。

インデックスが定義されると、別の手順としてドキュメントを読み込み、インデックスを作成できます。

オプション 1: 量子化を構成する

ベクトル サイズを小さくするためには、量子化が推奨されます。これは、float16 および float32 埋め込みのメモリとディスク ストレージの両方の要件を低減するためです。 より小さなインデックスの影響をオフセットするために、非圧縮ベクトルに対してオーバーサンプリングと再ランク付けを追加できます。

量子化は、float 型のベクトルを受け取るベクトル フィールドに適用されます。 この記事の例では、受信 float32 埋め込みのフィールドのデータ型は Collection(Edm.Single) ですが、float16 もサポートされています。 圧縮が構成されたフィールドでベクトルを受信すると、エンジンは自動的に量子化を実行して、メモリおよびディスク上のベクトル データのフットプリントを削減します。

2 種類の量子化がサポートされています。

  • スカラー量子化では、浮動小数点値をより少ないビット数のデータ型に圧縮します。 AI 検索は現在、8 ビットの int8 をサポートしており、ベクトル インデックスのサイズが 4 分の 1 に削減されます。

  • バイナリ量子化は、浮動小数点数を、1 ビットを占有するバイナリ ビットに変換します。 これにより、ベクトル インデックスのサイズが最大 28 分の 1 に削減されます。

組み込みの量子化を使用するには、次の手順に従います。

  • Create Index または Create or Update Index を使用して、ベクトル圧縮を指定する
  • 検索インデックスに vectorSearch.compressions を追加する
  • scalarQuantization または binaryQuantization 構成を追加して名前を付ける
  • オプションのプロパティを設定して、損失のあるインデックス作成の影響を軽減する
  • 名前付き構成を使用する新しいベクトル プロファイルを作成する
  • 新しいベクトル プロファイルを持つ新しいベクトル フィールドを作成する
  • 定義した構成でインデックス作成中に量子化された float32 または float16 データを含むインデックスを読み込む
  • 必要に応じて、既定値をオーバーライドする場合は、オーバーサンプリング パラメーターを使用して量子化されたデータに対してクエリを実行します

検索インデックスに "compressions" を追加する

次の例は、ベクトル フィールドと vectorSearch.compressions セクションを含む fields コレクションを持つ部分インデックス定義を示しています。

この例には scalarQuantizationbinaryQuantization の両方が含まれています。 必要な数の圧縮構成を指定し、必要なものをベクトル プロファイルに割り当てることができます。

POST https://[servicename].search.windows.net/indexes?api-version=2024-07-01

{
  "name": "my-index",
  "fields": [
    { "name": "Id", "type": "Edm.String", "key": true, "retrievable": true, "searchable": true, "filterable": true },
    { "name": "content", "type": "Edm.String", "retrievable": true, "searchable": true },
    { "name": "vectorContent", "type": "Collection(Edm.Single)", "retrievable": false, "searchable": true },
  ],
  "vectorSearch": {
        "profiles": [ ],
        "algorithms": [ ],
        "compressions": [
          {
            "name": "use-scalar",
            "kind": "scalarQuantization",
            "scalarQuantizationParameters": {
              "quantizedDataType": "int8"
            },
            "rerankWithOriginalVectors": true,
            "defaultOversampling": 10
          },
          {
            "name": "use-binary",
            "kind": "binaryQuantization",
            "rerankWithOriginalVectors": true,
            "defaultOversampling": 10
          }
        ]
    }
}

重要なポイント:

  • kindscalarQuantization または binaryQuantization に設定する必要があります

  • rerankWithOriginalVectors は元の非圧縮ベクトルを使用して類似性を再計算し、最初の検索クエリによって返される上位の結果を再ランク付けします。 stored が false の場合でも、非圧縮ベクトルが検索インデックスに存在します。 このプロパティは省略可能です。 既定値は True です。

  • 量子化による情報の減少を緩和するために、defaultOversampling は潜在的な結果のより広範なセットを考慮します。 潜在的な結果の数式は、クエリ内の k とオーバーサンプリング乗数で構成されます。 たとえば、クエリが k を 5 に指定し、オーバーサンプリングが 20 の場合、クエリはその目的のために元の非圧縮ベクトルを使用して、再ランク付けに使用する 100 個のドキュメントを効果的に要求します。 上位の k 個の再ランク付けの結果のみが返されます。 このプロパティは省略可能です。 既定値は 4 です。

  • quantizedDataType は省略可能であり、スカラー量子化にのみ適用されます。 追加する場合は、int8 に設定する必要があります。 これは現時点でスカラー量子化でサポートされている唯一のプリミティブ データ型です。 既定値は int8 です。

HNSW アルゴリズムを追加する

インデックスに Hierarchical Navigable Small Worlds (HNSW) アルゴリズムが組み込まれていることを確認します。 組み込みの量子化は、完全な KNN ではサポートされていません。

"vectorSearch": {
    "profiles": [ ],
    "algorithms": [
      {
          "name": "use-hnsw",
          "kind": "hnsw",
          "hnswParameters": {
              "m": 4,
              "efConstruction": 400,
              "efSearch": 500,
              "metric": "cosine"
          }
      }
    ],
     "compressions": [ <see previous section>] 
}

新しいベクトル プロファイルを作成して割り当てる

新しい量子化構成を使用するには、"新しい" ベクトル プロファイルを作成する必要があります。 メモリ内に圧縮インデックスを構築するには、新しいベクトル プロファイルを作成する必要があります。 新しいプロファイルでは HNSW を使用します。

  1. 同じインデックス定義で、新しいベクトル プロファイルを作成し、圧縮プロパティとアルゴリズムを追加します。 ここでは、量子化アプローチごとに 1 つずつ、2 つのプロファイルを示します。

    "vectorSearch": {
        "profiles": [
           {
              "name": "vector-profile-hnsw-scalar",
              "compression": "use-scalar", 
              "algorithm": "use-hnsw",
              "vectorizer": null
           },
           {
              "name": "vector-profile-hnsw-binary",
              "compression": "use-binary", 
              "algorithm": "use-hnsw",
              "vectorizer": null
           }
         ],
         "algorithms": [  <see previous section> ],
         "compressions": [ <see previous section> ] 
    }
    
  2. "新しい" ベクトル フィールドにベクトル プロファイルを割り当てます。 フィールドのデータ型は float32 または float16 です。

    Azure AI 検索では、float32 および float16 型のエンティティ データ モデル (EDM) に相当するものはそれぞれ Collection(Edm.Single)Collection(Edm.Half) になります。

    {
       "name": "vectorContent",
       "type": "Collection(Edm.Single)",
       "searchable": true,
       "retrievable": true,
       "dimensions": 1536,
       "vectorSearchProfile": "vector-profile-hnsw-scalar",
    }
    
  3. インデックスを読み込むには、プル モデルのインデックス作成の場合はインデクサーを使用し、プッシュ モデルのインデックス作成の場合は API を使用します。

スカラー量子化により、各ベクトル埋め込み内の各数値の解像度が低下します。 各数値を 16 ビットまたは 32 ビット浮動小数点数として記述する代わりに、8 ビット整数を使用します。 数値の範囲 (通常は 99 パーセンタイルの最小値と最大値) を識別し、それらを有限数のレベルまたはビンに分割することで、各ビンに識別子を割り当てます。 8 ビットスカラー量子化では、2^8 すなわち 256 のビンが存在する可能性があります。

実数を最も近い整数に四捨五入するのに似たプロセスで、ベクトルの各コンポーネントは量子化レベルのこのセット内で最も近い代表値にマッピングされます。 量子化された 8 ビット ベクトルでは、識別子番号が元の値の代わりに表示されます。 量子化後、各ベクトルはそのコンポーネントが属するビンの識別子の配列によって表されます。 これらの量子化されたベクトルでは、元のベクトルと比較して保存すべきビット数がはるかに小さいため、ストレージ要件とメモリ占有領域を削減できます。

バイナリ量子化は、各コンポーネントを 0 または 1 の単一ビットとして表すことによって、高次元ベクトルを圧縮します。 この方法により、メモリ占有領域が大幅に削減され、検索および取得タスクにとって重要なベクトル比較操作が高速化されます。 ベンチマーク テストでは、ベクトル インデックス サイズが最大 96% 削減されることが示されています。

これは、1024 を超える次元の埋め込みに特に効果的です。 より小さな次元の場合は、バイナリ量子化の品質をテストするか、代わりにスカラーを試すことをお勧めします。 さらに、埋め込みの中心がゼロの場合、BQ のパフォーマンスが非常に高いことがわかりました。 OpenAI、Cohere、Mistral などの最も一般的な埋め込みモデルはゼロを中心としています。

オプション 2: ベクトル フィールドに狭いデータ型を割り当てる

ベクトル サイズを小さくする簡単な方法は、埋め込みをより小さなデータ形式で保存することです。 ほとんどの埋め込みモデルでは 32 ビット浮動小数点数が出力されますが、ベクトルを量子化する場合、または埋め込みモデルでネイティブにサポートされている場合は、float16、int16、または int8 が出力される可能性があります。この場合、float32 よりも大幅に小さくなります。 ナロー データ型をベクトル フィールドに割り当てることで、これらの小さなベクトル サイズに対応できます。 ベクトル インデックスでは、ナロー データ型の方がストレージの消費量が少なくなります。

  1. 推奨される使用方法については、「ベクトル フィールドに使用されるデータ型」を確認してください。

    • Collection(Edm.Single) 32 ビット浮動小数点 (既定値)
    • Collection(Edm.Half) 16 ビット浮動小数点 (ナロー)
    • Collection(Edm.Int16) 16 ビット符号付き整数 (ナロー)
    • Collection(Edm.SByte) 8 ビット符号付き整数 (ナロー)
    • Collection(Edm.Byte) 8 ビット符号なし整数 (パックされたバイナリ データ型でのみ使用できます)
  2. そのリストから、埋め込みモデルの出力、またはカスタム量子化の対象となるベクトルに対して有効なデータ型を決定します。

    次の表は、追加の量子化なしでナロー データ型 (Collection(Edm.Half)) を使用できるいくつかの埋め込みモデルへのリンクを示しています。 追加の作業なしで float32 から float16 (Collection(Edm.Half) を使用) にキャストできます。

    埋め込みモデル ネイティブ出力 Azure AI 検索でこの型を割り当てる
    text-embedding-ada-002 Float32 Collection(Edm.Single) または Collection(Edm.Half)
    text-embedding-3-small Float32 Collection(Edm.Single) または Collection(Edm.Half)
    text-embedding-3-large Float32 Collection(Edm.Single) または Collection(Edm.Half)
    int8 embedding_type を使用した Cohere V3 埋め込みモデル Int8 Collection(Edm.SByte)

    モデルがより小さなデータ形式で埋め込みを生成する場合、またはベクトルをより小さな形式に変換するカスタム量子化がある場合は、他のナロー データ型を使用できます。

  3. 狭いデータ型のトレードオフを理解していることを確認します。 Collection(Edm.Half) には含まれる情報が少ないため、解像度が低くなります。 データが同種または高密度の場合、追加の詳細情報や微妙な差異が失われると、近くのベクトルを区別するために使用できる詳細情報が少なくなるため、クエリ時に許容できない結果になることがあります。

  4. インデックスを定義してビルドします。 この手順では、Azure portal、Create or Update Index (REST API)、または Azure SDK パッケージを使用できます。

  5. 結果を確認する。 ベクトル フィールドが取得可能としてマークされている場合は、Search エクスプローラーまたは Search - POST を使用して、フィールドのコンテンツがデータ型と一致することを確認します。

    ベクトル インデックスのサイズを確認するには、Azure portal または GET Statistics (REST API) を使用します。

Note

フィールドのデータ型は、物理データ構造を作成するために使用されます。 後でデータ型を変更する場合は、インデックスを削除して再構築するか、新しい定義で 2 つ目のフィールドを作成します。

オプション 3: stored プロパティを設定して、取得可能なストレージを削除する

stored プロパティはベクトル フィールド定義のブール値であり、取得可能なベクトル フィールドのコンテンツにストレージが割り当てられているかどうかを決定します。 stored プロパティの既定値は True です。 クエリ応答にベクトルのコンテンツが必要ない場合は、stored を false に設定することで、フィールドごとに最大 50% のストレージ削減できます。

stored を false に設定する際の考慮事項:

  • ベクトルは人間には判読できないため、RAG シナリオで LLM に送信される結果や、検索ページに表示される結果では省略できます。 ただし、ベクトルの内容を消費するダウンストリーム プロセスでベクトルを使用している場合は、ベクトルを維持してください。

  • なお、インデックス作成戦略にドキュメントの部分的な更新 (ドキュメントの "merge" や "mergeOrUpload" など) を取り入れている場合、stored を false に設定すると、格納されていないフィールドのベクトルがマージ中に省略されますのでご注意ください。 各 "merge" または "mergeOrUpload" 操作では、更新する他の非ベクトル フィールドに加えてベクトル フィールドを指定する必要があり、指定しない場合ベクトルは削除されます。

stored 属性は元に戻せないことに注意してください。 これは、物理データ構造が作成される際、ベクトル フィールドのインデックス作成中に設定されます。 後で取得可能なベクトル コンテンツが必要になった場合は、インデックスを削除して再構築するか、新しい属性を持つ新しいフィールドを作成して読み込む必要があります。

次の例は、検索インデックスのフィールド コレクションを示しています。 ベクトル フィールドの取得可能なストレージを完全に削除するには、stored を false に設定します。

PUT https://[service-name].search.windows.net/indexes/demo-index?api-version=2024-07-01 
   Content-Type: application/json  
   api-key: [admin key]  
 
     { 
       "name": "demo-index", 
       "fields": [ 
         { 
           "name": "vectorContent", 
           "type": "Collection(Edm.Single)", 
           "retrievable": false, 
           "stored": false, 
           "dimensions": 1536, 
           "vectorSearchProfile": "vectorProfile" 
         } 
       ] 
     } 

重要なポイント:

  • ベクトル フィールドにのみ適用されます。

  • メモリではなくディスク上のストレージに影響し、クエリにはまったく影響しません。 クエリ実行では、stored プロパティの影響を受けない別のベクトル インデックスが使用されます。

  • stored プロパティはベクトル フィールドのインデックス作成時に設定され、元に戻すことはできません。 後で取得可能なコンテンツが必要になった場合は、インデックスを削除して再構築するか、新しい属性を持つ新しいフィールドを作成して読み込む必要があります。

  • 既定値は、true に設定された stored と false に設定された retrievable です。 既定の構成では、取得可能なコピーが保存されますが、結果では自動的に返されません。 stored が true の場合、インデックスを再構築しなくても、いつでも retrievable を true と false の間で切り替えられます。 stored が false の場合、retrievable は false である必要があり、変更できません。

例: ベクトル圧縮方法

次のコードは、量子化、ナロー データ型、および保存されたプロパティの使用を示す Python コードです。コード サンプル: Python を使用したベクトル量子化とストレージ オプション

このコードでは、各オプションのストレージおよびベクトル インデックス サイズを作成して比較します。

****************************************
Index Name: compressiontest-baseline
Storage Size: 21.3613MB
Vector Size: 4.8277MB
****************************************
Index Name: compressiontest-compression
Storage Size: 17.7604MB
Vector Size: 1.2242MB
****************************************
Index Name: compressiontest-narrow
Storage Size: 16.5567MB
Vector Size: 2.4254MB
****************************************
Index Name: compressiontest-no-stored
Storage Size: 10.9224MB
Vector Size: 4.8277MB
****************************************
Index Name: compressiontest-all-options
Storage Size: 4.9192MB
Vector Size: 1.2242MB

Search API では、インデックス レベルでストレージとベクトル サイズがレポートされるため、フィールドではなくインデックスが比較の基準である必要があります。 ベクトル サイズを取得するには、GET Index Statistics または Azure SDK の同等の API を使用します。

オーバーサンプリングを使用して量子化されたベクトル フィールドのクエリを実行する

圧縮または量子化されたベクトル フィールドのクエリ構文は、オーバーサンプリングまたは元のベクトルによる再ランク付けに関連付けられたパラメーターをオーバーライドしない限り、非圧縮ベクトル フィールドの場合と同じです。

インデックス内のベクトル圧縮定義には、より小さなベクトル インデックスの影響を軽減するための rerankWithOriginalVectorsdefaultOversampling の設定があることを思い出してください。 既定値をオーバーライドして、クエリ時の動作を変更できます。 たとえば、defaultOversampling が 10.0 の場合は、クエリ要求で別のものに変更できます。

インデックスに明示的に rerankWithOriginalVectors または defaultOversampling の定義がない場合でも、オーバーサンプリング パラメータを設定できます。 クエリ時に oversampling を指定すると、そのクエリのインデックス設定をオーバーライドし、有効な rerankWithOriginalVectors を true としてクエリを実行できます。

POST https://[service-name].search.windows.net/indexes/demo-index/docs/search?api-version=2024-07-01   
  Content-Type: application/json   
  api-key: [admin key]   

    {    
       "vectorQueries": [
            {    
                "kind": "vector",    
                "vector": [8, 2, 3, 4, 3, 5, 2, 1],    
                "fields": "myvector",
                "oversampling": 12.0,
                "k": 5   
            }
      ]    
    }

重要なポイント:

  • ベクトル プロファイルの割り当てに従い、ベクトル圧縮の対象となるベクトル フィールドに適用されます。

  • インデックスの圧縮構成でオーバーサンプリングまたは再ランク付けオプションが指定されていない場合でも、defaultOversampling 値をオーバーライドするか、クエリ時にオーバーサンプリングを実施します。

関連項目