Vector Quantization
La quantification vectorielle remplace chaque vecteur par l’index de l’entrée la plus proche du dictionnaire de codes. Présentation des dictionnaires de codes k-means, de la quantification par produit et des jetons VQ-VAE.
La quantification vectorielle (VQ) est une technique de compression qui remplace chaque vecteur d’un jeu de données par l’indice de l’entrée la plus proche dans un petit ensemble de vecteurs représentatifs appelé dictionnaire de codes. L’encodage ne stocke que l’indice, le décodage recherche la valeur correspondant à cet indice, et l’erreur de reconstruction correspond à la distance entre le vecteur d’origine et son mot de code. Un dictionnaire de codes de K entrées coûte log₂(K) bits par vecteur, quel que soit le nombre de dimensions de celui-ci ; ainsi, un dictionnaire de codes de 256 entrées stocke n’importe quel vecteur sur un octet. La VQ vient du traitement du signal : l’algorithme de Stuart Lloyd, conçu en 1957 aux Bell Labs pour créer des quantificateurs scalaires et publié en 1982, est celui qu’on appelle généralement k-means aujourd’hui, et Yoseph Linde, Andrés Buzo et Robert Gray l’ont étendu aux vecteurs en 1980. En deep learning, la VQ est devenue la méthode standard pour convertir des images, de l’audio et de la vidéo en tokens discrets pour l’IA générative.
Fonctionnement de la quantification vectorielle#
Un dictionnaire est généralement appris par clustering k-means : affecte chaque vecteur d’entraînement à son mot de code le plus proche, déplace chaque mot de code vers la moyenne des vecteurs qui lui sont affectés, puis recommence ; cette opération ne fait jamais augmenter la distorsion moyenne. La quantification des couleurs illustre tout le processus à partir des pixels d’une photo, en utilisant le module scipy.cluster.vq de SciPy :
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")Les 273 280 pixels sont stockés sous forme d’indices de 4 bits dans une palette de 16 couleurs, soit six fois moins de données couleur qu’en RGB 24 bits, avec une erreur quadratique moyenne de 11,3 niveaux d’intensité sur 255.
La quantification scalaire est le cas à une dimension, et la quantification de modèle l’applique aux réseaux neuronaux. Ultralytics YOLO26 l’utilise lors de l’exportation : quantize=8 arrondit chaque poids et chaque activation indépendamment à l’un des 256 niveaux entiers, les plages d’activation étant observées lors d’un passage de calibration sur les images de data. La quantification conjointe de vecteurs entiers exploite les corrélations entre dimensions ; à débit binaire égal, un quantificateur vectoriel optimal n’a jamais une distorsion supérieure à celle d’un quantificateur scalaire optimal appliqué à chaque valeur.
Quantification par produit et résiduelle#
Un dictionnaire de codes unique croît de façon exponentielle avec le budget en bits, puisqu’il faudrait 2⁶⁴ mots de code pour 64 bits. La quantification par produit, introduite par Hervé Jégou, Matthijs Douze et Cordelia Schmid en 2011, divise chaque vecteur en m sous-vecteurs et quantifie chacun à l’aide de son propre dictionnaire de codes de 256 entrées. Avec m = 8, un embedding float32 de 128 dimensions passe de 512 octets à 8, et les distances par rapport à une requête sont calculées à partir de petites tables de consultation. La bibliothèque FAISS de Meta l’associe à un index de fichier inversé, un quantificateur k-means grossier qui limite chaque requête à quelques clusters, pour la recherche vectorielle à l’échelle du milliard.
La quantification résiduelle empile plutôt les dictionnaires : le deuxième quantifie l’erreur laissée par le premier, le troisième l’erreur laissée par le deuxième, et ainsi de suite. SoundStream de Google (2021) et EnCodec de Meta (2022), des codecs audio neuronaux, l’utilisent pour compresser la parole et la musique à quelques kilobits par seconde, tandis que la modélisation autorégressive visuelle (VAR) l’applique à différentes résolutions d’image.
VQ-VAE et tokens d’image#
Aäron van den Oord, Oriol Vinyals et Koray Kavukcuoglu de DeepMind ont présenté le VQ-VAE dans Neural Discrete Representation Learning en 2017. La sortie de l’encodeur d’un autoencodeur à chaque position spatiale est remplacée par son mot de code le plus proche, et le décodeur reconstruit l’entrée à partir des mots de code. La recherche du plus proche voisin ne transmet aucun gradient ; un estimateur à passage direct copie donc le gradient du décodeur au-delà de cette étape pendant la rétropropagation, ce qui s’écrit en PyTorch z_q = z + (z_q - z).detach(). Deux termes de fonction de perte supplémentaires rapprochent les mots de code des sorties de l’encodeur et incitent l’encodeur à conserver les mots de code choisis, le second étant pondéré par 0,25 dans l’article.
Les grilles de tokens obtenues alimentent un deuxième modèle, généralement un transformer, qui apprend à les générer. VQGAN (2021) a ajouté des fonctions de perte antagonistes et perceptuelles pour obtenir des tokens plus nets, et est devenu le tokenizer de nombreux modèles de génération d’images à partir de texte. Un problème courant est l’effondrement du dictionnaire, où la plupart des mots de code ne sont jamais sélectionnés et le vocabulaire effectif se réduit. L’initialisation par k-means, les mises à jour du dictionnaire par moyenne mobile et la réinitialisation des codes inutilisés permettent de l’éviter. La quantification scalaire finie de Google (FSQ, 2023) évite ce problème en arrondissant chacune de quelques dimensions latentes à un petit nombre de niveaux fixes, de sorte que tous les codes du dictionnaire implicite puissent être atteints.
Quantification vectorielle et termes connexes#
- Bases de données vectorielles : Stockent et indexent les embeddings, et utilisent souvent la quantification par produit en interne pour les faire tenir en mémoire.
- Réduction de dimensionnalité : Ramène les vecteurs à un plus petit nombre de dimensions continues, comme le fait l’ACP, tandis que la VQ associe chaque vecteur à un code discret.
- Tokenisation : Divise le texte en unités issues d’un vocabulaire fixe ; la VQ construit le vocabulaire équivalent pour des signaux continus comme les patches d’image et les trames audio.










