スカラー量子化(スカラーリョウシカ)
スカラー量子化(Scalar Quantization)は、埋め込みベクトルの各次元の値を個別にfloat32からint8/uint8に線形マッピングする量子化手法である。実装が単純で精度劣化が小さく、Qdrant・Weaviate・Milvusなど主要ベクトルDBで標準サポートされている。
スカラー量子化(Scalar Quantization, SQ)は、ベクトルの各次元(スカラー値)を独立に低精度整数にマッピングする最も基本的な量子化手法である。「スカラー」の名称は、ベクトル全体ではなく各次元の値(スカラー)を個別に処理することに由来する。Product Quantization(PQ)のようにベクトルをサブベクトルに分割してコードブックを学習する方式と比較して、実装が単純で追加の学習ステップが不要という利点がある。
動作原理
スカラー量子化の手順は以下の通り:
1. 統計量の収集
インデックス内の全ベクトル(またはサンプル)から、各次元ごとの最小値(min_d)と最大値(max_d)を収集する。
2. スケールとゼロポイントの算出
各次元dについて:
- range_d = max_d - min_d
- scale_d = range_d / (2^bits - 1)
- zero_point_d = round(-min_d / scale_d)
uint8(0〜255)の場合、bits = 8 なので 2^8 - 1 = 255 で除算する。
3. 量子化(エンコード)
元のfloat32値 x_d を量子化値 q_d に変換:
- q_d = clamp(round(x_d / scale_d) + zero_point_d, 0, 255)
4. 逆量子化(デコード)
量子化値から近似float32値を復元:
- x'_d = (q_d - zero_point_d) × scale_d
この操作は各次元で独立に行われるため、並列化が容易で SIMD 命令(AVX2/AVX-512/NEON)による高速化と相性が良い。
対称量子化 vs 非対称量子化
| 方式 | ゼロポイント | 値域 | 精度 | 実装 |
|---|---|---|---|---|
| 対称(Symmetric) | 0固定 | [-127, 127] (int8) | やや低い | 単純 |
| 非対称(Asymmetric) | データ依存 | [0, 255] (uint8) | やや高い | やや複雑 |
対称量子化: 値域の中心を0に固定し、abs(max)を基準にスケーリング。ゼロポイント計算が不要なため高速だが、値の分布が非対称(例: ReLU後の非負値)だとビット効率が悪い。
非対称量子化: 実際のmin/maxに基づくため、値域を効率的に使い切る。Qdrant・Weaviateはデフォルトで非対称方式を採用。
主要ベクトルDBでの実装
Qdrant
# コレクション作成時に量子化設定
quantization_config:
scalar:
type: int8
quantile: 0.99 # 外れ値除外(上下1%カット)
always_ram: true # 量子化ベクトルを常にRAM配置
Qdrantのquantileパラメータは、min/max算出時に外れ値を除外する割合を指定する。0.99なら上下0.5%ずつカットし、量子化レンジの効率を向上させる。
Weaviate
Weaviate v1.25+では SQ(Scalar Quantization)をネイティブサポート。HNSWインデックスと組み合わせて使用し、メモリ使用量を75%削減しつつ検索品質を維持する。
Milvus
MilvusではIVF_SQ8インデックスタイプとして提供。IVF(Inverted File Index)のクラスタリングとSQを組み合わせ、検索空間の絞り込みと量子化の両方の恩恵を受ける。
スカラー量子化 vs Product Quantization
| 項目 | スカラー量子化(SQ) | 直積量子化(PQ) |
|---|---|---|
| 圧縮率 | 4x(float32→int8) | 16-64x |
| 精度劣化 | 1-3%(高次元) | 5-15% |
| 学習コスト | なし(統計量のみ) | K-means学習必要 |
| インデックス構築速度 | 高速 | 遅い(学習フェーズ) |
| 追加ベクトルの扱い | 即時量子化可能 | コードブック再学習の可能性 |
| メモリ削減効果 | 中 | 大 |
| リスコアリング必要性 | 低(精度十分) | 高(精度回復必要) |
SQは「精度重視・実装簡易・動的データ対応」、PQは「圧縮率重視・静的データセット向き」として使い分ける。
パフォーマンスベンチマーク
1024次元、100万ベクトルでのベンチマーク(Qdrant公式ブログより参考値):
| 指標 | float32 | int8 SQ | int8 SQ + Rescore |
|---|---|---|---|
| メモリ使用量 | 4.1 GB | 1.1 GB | 5.2 GB(元ベクトル保持) |
| 検索レイテンシ(p99) | 12 ms | 4 ms | 6 ms |
| Recall@10 | 1.000 | 0.985 | 0.998 |
| スループット | 850 QPS | 2,400 QPS | 1,800 QPS |
リスコアリング(Rescore)を使うと元のfloat32ベクトルも保持するためメモリは増加するが、Recall@10が0.998まで回復する。メモリよりレイテンシとスループットの改善が目的の場合に有効。
実装時の注意点
- 外れ値の処理: パーセンタイルベースのクリッピング(quantile=0.99)で外れ値を除外し、量子化レンジの効率を上げる
- 次元数の閾値: 256次元未満ではSQの精度劣化が目立つ。384次元以上を推奨
- 正規化の重要性: L2正規化済みベクトル(コサイン類似度用)はSQとの相性が良い。値域が[-1, 1]に収まるため量子化レンジが安定
- 動的データ: 新規ベクトル追加時、既存のmin/maxから外れる値はクリッピングされる。定期的な再量子化(Re-quantization)を検討
よくある質問(FAQ)
Q1: スカラー量子化はGPU推論のINT8量子化と同じ? A: 原理は同じ(float32→int8のマッピング)だが、適用対象が異なる。GPU推論の量子化はモデルの重み・活性化に適用し推論速度を向上。埋め込みスカラー量子化は推論後のベクトルに適用しストレージ・検索コストを削減する。
Q2: int8とuint8のどちらを選ぶべき? A: L2正規化済みベクトル(値域[-1, 1])にはint8(対称量子化)、非正規化ベクトル(値域が0以上に偏る場合)にはuint8(非対称量子化)が適する。多くのベクトルDBはuint8をデフォルトとし、内部で自動調整する。
Q3: 量子化後にベクトル検索のアルゴリズムは変わる? A: HNSWやIVFなどのANNアルゴリズム自体は変わらない。距離計算の内部表現が変わるだけ。int8同士のドット積はSIMD命令(vpdpbusd等)で高速化され、float32比で2-4倍のスループットを実現する。
まとめ
- スカラー量子化は各次元を独立にfloat32→int8変換する最も基本的な方式
- 学習不要・即時適用可能・動的データ対応が強み
- 4x圧縮でRecall劣化1-3%、リスコアリング併用で1%未満
- Qdrant/Weaviate/Milvusで標準サポート
- 256次元以上・L2正規化済みベクトルで最も効果的