Vector Quantization
向量量化将每个向量替换为其最近码本条目的索引。介绍 k-means 码本、乘积量化和 VQ-VAE token。
向量量化(VQ)是一种压缩技术,它将数据集中的每个向量替换为一个小型代表向量集合(称为码本)中最近向量的索引。编码时只存储索引,解码时查找该索引,重建误差则是原始向量与其码字之间的距离。一个含 K 个条目的码本无论向量有多少维,每个向量都只需 log₂(K) 位,因此含 256 个条目的码本可以用一个字节存储任意向量。VQ 源自信号处理:Stuart Lloyd 于 1957 年在贝尔实验室提出了设计标量量化器的算法,并于 1982 年发表;如今该算法通常称为 k-means。Yoseph Linde、Andrés Buzo 和 Robert Gray 于 1980 年将其扩展到向量。在深度学习中,VQ 成为将图像、音频和视频转换为离散 token,以供生成式 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 个像素都以 4 位索引存储,对应 16 种颜色;与 24 位 RGB 相比,颜色数据减少了六倍,均方根误差为 11.3 个强度级别(满量程为 255)。
标量量化是一维情形,而模型量化则将其应用于神经网络。Ultralytics YOLO26在导出时会使用量化:quantize=8 将每个权重和激活值分别舍入到 256 个整数级别之一,并在一次校准过程中观察 data 中图像的激活值范围。联合量化整个向量可以利用维度之间的相关性;在相同比特率下,最优向量量化器的失真不会高于对每个值分别应用的最优标量量化器。
乘积量化与残差量化#
单一码本会随位数预算呈指数级增长,因为 64 位需要 2⁶⁴ 个码字。Hervé Jégou、Matthijs Douze 和 Cordelia Schmid 于 2011 年提出了乘积量化:将每个向量拆分成 m 个子向量,并分别用各自含 256 个条目的码本进行量化。当 m = 8 时,一个 128 维的 float32 嵌入向量会从 512 字节缩小到 8 字节,而查询距离则通过小型查找表计算得出。Meta 的 FAISS 库将它与倒排文件索引结合使用;倒排文件索引是一种粗略的 k-means 量化器,可将每次查询限制在少数几个聚类中,从而实现十亿规模的向量搜索。
残差量化则是逐层叠加码本:第二个码本量化第一个码本留下的误差,第三个码本量化第二个码本留下的误差,以此类推。Google 的 SoundStream(2021)和 Meta 的 EnCodec(2022)神经音频编解码器使用残差量化,将语音和音乐压缩到每秒几千比特;视觉自回归建模(VAR)则在不同图像分辨率上应用这种方法。
VQ-VAE 与图像词元#
DeepMind 的 Aäron van den Oord、Oriol Vinyals 和 Koray Kavukcuoglu 于 2017 年在神经离散表示学习中提出了 VQ-VAE。自编码器在每个空间位置的编码器输出都会被替换为最近的码字,解码器再根据这些码字重建输入。最近邻查找没有梯度,因此在反向传播过程中,直通估计器会将解码器的梯度直接传过查找步骤;在 PyTorch 中写作 z_q = z + (z_q - z).detach()。两个额外的损失项分别用于推动码字靠近编码器输出,以及约束编码器使用其选定的码字;论文中第二项的权重为 0.25。
生成的词元网格会输入第二个模型,通常是Transformer,由它学习生成这些词元。VQGAN(2021)加入了对抗式损失和感知损失,以生成更清晰的词元,并成为许多文生图模型使用的分词器。一个常见问题是码本坍塌:大多数码字从未被选中,导致有效词表缩小。使用 k-means 初始化、通过移动平均更新码本,以及重置未使用的码字,都有助于缓解这一问题。Google 于 2023 年提出的有限标量量化(FSQ)则通过将少数潜在维度分别舍入到几个固定级别来避免码本坍塌,这样隐含码本中的每个码字都能被访问到。










