Choisir la dimension de ses embeddings

La dimension d’un embedding est un paramètre qu’on subit souvent, parce qu’il est imposé par le modèle choisi. C’est pourtant lui qui fixe la facture mémoire de l’index, et donc son coût d’exploitation.

Le calcul de base

Un vecteur de dimension d stocké en flottant 32 bits occupe 4 × d octets. Pour d = 768, cela fait un peu plus de 3 Ko par vecteur, soit de l’ordre de 3 Go pour un million de vecteurs — avant tout index.

À cela s’ajoute la structure de recherche. Un graphe HNSW conserve pour chaque nœud une liste de voisins par couche ; avec un paramètre M de 16, on stocke typiquement autour de 32 identifiants pour la couche de base, plus les couches supérieures dont la population décroît géométriquement. En comptant 4 octets par identifiant, le surcoût du graphe est de l’ordre de 150 à 200 octets par vecteur. Il reste modeste face aux données brutes en dimension 768, mais il devient dominant en basse dimension ou après une quantification agressive.

L’ordre de grandeur à retenir : la mémoire d’un index dense est d’abord pilotée par d, ensuite par M.

Ce que la dimension apporte, et jusqu’où

Augmenter d donne au modèle plus de capacité pour séparer des concepts voisins. Le gain n’est pas linéaire : au-delà d’un certain point, les dimensions supplémentaires encodent de la variance de moins en moins utile pour la tâche de recherche, alors que le coût mémoire, lui, continue de croître proportionnellement.

Un effet plus subtil intervient dans les grandes dimensions : la concentration des distances. À mesure que d augmente, les distances entre points tirés d’une même distribution se resserrent autour d’une valeur moyenne, et le contraste entre le plus proche voisin et les suivants s’amenuise. Les embeddings appris échappent partiellement à ce phénomène parce qu’ils occupent une variété de dimension intrinsèque bien inférieure à d, mais cela explique pourquoi doubler la dimension n’améliore pas mécaniquement le rappel.

Réduire sans réentraîner

Deux leviers permettent de baisser le coût sans changer de modèle.

La troncature, d’abord, quand le modèle a été entraîné pour cela. Les modèles à représentation matriochka ordonnent l’information par importance décroissante : on peut couper le vecteur aux k premières composantes et renormaliser, avec une dégradation graduelle du rappel. Avec un modèle qui n’a pas cette propriété, tronquer coupe de l’information au hasard et la dégradation est brutale.

La quantification, ensuite. Passer de float32 à un entier 8 bits par composante divise la mémoire par quatre pour une perte de précision généralement faible. La quantification binaire, qui ne conserve que le signe de chaque composante, va jusqu’à un facteur 32 et permet de comparer par distance de Hamming ; elle exige en contrepartie une phase de reclassement des résultats présélectionnés sur les vecteurs pleine précision pour récupérer un rappel acceptable.

Une méthode d’arbitrage

Constituez un jeu d’évaluation de quelques centaines de requêtes avec les documents attendus. Calculez le rappel@k exact par recherche exhaustive, qui sert de plafond. Comparez ensuite les configurations envisagées — dimension, quantification, paramètres d’index — sur ce même jeu, et retenez la moins coûteuse dont le rappel reste dans votre budget de perte.

Ce budget est une décision produit, pas technique. Pour un pipeline RAG qui récupère vingt passages avant reclassement, quelques points de rappel@20 sont souvent invisibles en sortie. Pour de la déduplication, où l’on cherche un unique voisin quasi identique, la tolérance est bien plus faible.