Vector Quantization
ベクトル量子化では、各ベクトルを最も近いコードブックエントリのインデックスに置き換えます。k-meansコードブック、積量子化、VQ-VAEトークンについて解説します。
ベクトル量子化(VQ)は、データセット内の各ベクトルを、コードブックと呼ばれる少数の代表ベクトル集合の中で最も近いエントリーのインデックスに置き換える圧縮技術です。エンコードではインデックスのみを保存し、デコードではインデックスを参照します。再構成誤差は、元のベクトルとコードワード間の距離です。K個のエントリーを持つコードブックは、ベクトルの次元数にかかわらず、ベクトルあたりlog₂(K)ビットを必要とするため、256エントリーのコードブックでは任意のベクトルを1バイトで保存できます。VQは信号処理に由来します。Stuart Lloydが1957年にBell Labsで考案し、1982年に発表したスカラー量子化器設計アルゴリズムは、現在一般にk-meansと呼ばれているアルゴリズムです。Yoseph Linde、Andrés Buzo、Robert Grayは1980年にこれをベクトルに拡張しました。ディープラーニングでは、VQは画像、音声、動画をトークンに変換して生成AIで扱うための標準的な方法になりました。
ベクトル量子化の仕組み#
コードブックは通常、k-meansクラスタリングで学習します。学習用ベクトルをそれぞれ最も近いコードワードに割り当て、各コードワードを割り当てられたベクトルの平均位置に移動する操作を繰り返します。この処理で平均歪みが増加することはありません。画像のピクセルを使う色量子化では、SciPyのscipy.cluster.vqモジュールを用いて、一連の処理全体を確認できます。
import numpy as np
from scipy.cluster.vq import kmeans2, vq
from sklearn.datasets import load_sample_image
image = load_sample_image("china.jpg") # 427 x 640 RGB photo bundled with scikit-learn
pixels = image.reshape(-1, 3).astype(np.float64) # one 3-D color vector per pixel
# Learn a 16-entry codebook with k-means (Lloyd's algorithm) on a sample of pixels
rng = np.random.default_rng(0)
codebook, _ = kmeans2(rng.choice(pixels, 5000), 16, minit="++", seed=0)
# Encode: replace each pixel with the index of its nearest codeword (4 bits instead of 24)
indices, _ = vq(pixels, codebook)
# Decode: look each index up in the codebook
reconstruction = codebook[indices]
rmse = np.sqrt(((pixels - reconstruction) ** 2).mean())
print(f"{len(pixels):,} pixels, {len(codebook)} codewords, 24 -> 4 bits per pixel")
print(f"Reconstruction RMSE: {rmse:.1f} on the 0-255 scale")273,280個すべてのピクセルは、16色への4ビットインデックスとして保存されます。これは24ビットRGBと比べて色情報が6分の1であり、二乗平均平方根誤差は255段階中11.3です。
スカラー量子化は1次元の場合であり、モデル量子化はこれをニューラルネットワークに適用します。Ultralytics YOLO26では、エクスポート時にこれを利用します。quantize=8は各重みと活性化を個別に256段階の整数値のいずれかに丸め、data内の画像を使った1回のキャリブレーションパスで活性化の範囲を測定します。ベクトル全体をまとめて量子化すると、次元間の相関を活用できます。同じビットレートなら、最適なベクトル量子化器の歪みは、各値に最適なスカラー量子化器を適用した場合を上回りません。
プロダクト量子化と残差量子化#
単一のコードブックはビット数に応じて指数関数的に大きくなり、64ビットの場合は2⁶⁴個のコードワードが必要になります。Hervé Jégou、Matthijs Douze、Cordelia Schmidが2011年に提案した積量子化では、各ベクトルをm個のサブベクトルに分割し、それぞれを独自の256エントリーのコードブックで量子化します。m = 8の場合、128次元のfloat32 埋め込みは512バイトから8バイトに縮小され、クエリとの距離は小さなルックアップテーブルから求められます。MetaのFAISSライブラリは、これを反転ファイルインデックス、つまり各クエリの対象を数個のクラスタに絞る粗いk-means量子化器と組み合わせ、数十億規模のベクトル検索を実現します。
残差量子化では、コードブックを段階的に重ねます。2番目のコードブックは1番目が残した誤差を量子化し、3番目は2番目が残した誤差を量子化するというように続きます。GoogleのSoundStream(2021)とMetaのEnCodec(2022)は、ニューラル音声コーデックでこの手法を使い、音声や音楽を毎秒数キロビットに圧縮します。また、視覚的自己回帰モデリング(VAR)では、画像の解像度にまたがって適用されます。
VQ-VAEと画像トークン#
DeepMindのAäron van den Oord、Oriol Vinyals、Koray Kavukcuogluは、2017年のNeural Discrete Representation LearningでVQ-VAEを提唱しました。オートエンコーダーのエンコーダー出力は、各空間位置で最も近いコードワードに置き換えられ、デコーダーはコードワードから入力を再構成します。最近傍検索には勾配がないため、バックプロパゲーション中に、ストレートスルー推定器がデコーダーの勾配をそのまま通過させます。PyTorchではz_q = z + (z_q - z).detach()のように記述します。さらに2つの損失項によって、コードワードをエンコーダー出力に近づけるとともに、エンコーダーを選択したコードワードに対応するよう学習させます。論文では、後者に0.25の重みを設定しています。
得られたトークングリッドは、通常はTransformerである第2のモデルに入力され、トークングリッドの生成を学習します。VQGAN(2021)は、より鮮明なトークンを得るために敵対的損失と知覚損失を加え、多くのテキスト画像生成モデルのトークナイザーになりました。よくある問題はコードブック崩壊で、ほとんどのコードワードが選択されず、実効的な語彙が縮小します。k-meansによる初期化、移動平均を使ったコードブック更新、未使用コードのリセットで対処できます。Googleの有限スカラー量子化(FSQ、2023)は、少数の潜在次元をそれぞれ少数の固定レベルに丸めることで、この問題を回避します。そのため、暗黙のコードブックにあるすべてのコードが選択可能です。
ベクトル量子化と関連用語#
- ベクトルデータベース: 埋め込みベクトルを保存、インデックス化し、多くの場合、メモリー使用量を抑えるため内部でプロダクト量子化を適用します。
- 次元削減: PCAのように、ベクトルをより少ない連続値の次元に写像します。一方、VQは各ベクトルを1つの離散コードに写像します。
- トークナイズ: テキストを固定語彙内の単位に分割します。VQは、画像パッチや音声フレームなどの連続信号に対して、同等の語彙を構築します。










