IVF_PQ
L'index IVF_PQ est un algorithme d'indexation basé sur la quantification pour la recherche approximative du plus proche voisin dans des espaces de haute dimension. Bien qu'il ne soit pas aussi rapide que certaines méthodes basées sur les graphes, IVF_PQ nécessite souvent beaucoup moins de mémoire, ce qui en fait un choix pratique pour les grands ensembles de données.
Vue d'ensemble
IVF_PQ signifie Inverted File with Product Quantization (fichier inversé avec quantification de produit). Il s'agit d'une approche hybride qui combine l'indexation et la compression pour une recherche vectorielle et une récupération efficaces. Elle s'appuie sur deux composants essentiels : le fichier inversé (IVF) et la quantification de produit (PQ).
FICHIER INVERSÉ
L'IVF est comparable à la création d'un index dans un livre. Au lieu de parcourir chaque page (ou, dans notre cas, chaque vecteur), vous recherchez des mots-clés spécifiques (clusters) dans l'index pour trouver rapidement les pages (vecteurs) pertinentes. Dans notre scénario, les vecteurs sont regroupés en grappes et l'algorithme recherche dans quelques grappes proches du vecteur de la requête.
Voici comment cela fonctionne :
- Regroupement : Votre ensemble de données vectorielles est divisé en un nombre déterminé de grappes, à l'aide d'un algorithme de regroupement tel que les k-moyennes. Chaque grappe possède un centroïde (vecteur représentatif de la grappe).
- Affectation : Chaque vecteur est affecté à la grappe dont le centroïde est le plus proche.
- Index inversé : Un index est créé, mettant en correspondance chaque centroïde de grappe avec la liste des vecteurs assignés à cette grappe.
- Recherche : Lorsque vous recherchez les voisins les plus proches, l'algorithme de recherche compare le vecteur de votre requête aux centroïdes des clusters et sélectionne le(s) cluster(s) le(s) plus prometteur(s). La recherche est alors limitée aux vecteurs contenus dans les grappes sélectionnées.
Pour en savoir plus sur les détails techniques, reportez-vous à IVF_FLAT.
PQ
Laquantification de produit (PQ) est une méthode de compression pour les vecteurs à haute dimension qui réduit considérablement les besoins de stockage tout en permettant des opérations de recherche de similarité rapides.
Le processus de quantification de produit comprend les étapes suivantes :
processus pq-1
- Décomposition des dimensions: L'algorithme commence par décomposer chaque vecteur à haute dimension en
m
sous-vecteurs de taille égale. Cette décomposition transforme l'espace original à D dimensions enm
sous-espaces disjoints, où chaque sous-espace contient D/m dimensions. Le paramètrem
contrôle la granularité de la décomposition et influence directement le taux de compression. - Génération d'un codebook de sous-espace: Dans chaque sous-espace, l'algorithme applique le regroupement k-means pour apprendre un ensemble de vecteurs représentatifs (centroïdes). Ces centroïdes forment collectivement un livre de codes pour ce sous-espace. Le nombre de centroïdes dans chaque codebook est déterminé par le paramètre
nbits
, où chaque codebook contient 2^nbits de centroïdes. Par exemple, sinbits = 8
, chaque livre de codes contiendra 256 centroïdes. Chaque centroïde se voit attribuer un index unique denbits
bits. - Quantification duvecteur: Pour chaque sous-vecteur du vecteur original, PQ identifie le centroïde le plus proche dans le sous-espace correspondant à l'aide d'un type de métrique spécifique. Ce processus permet de faire correspondre chaque sous-vecteur à son vecteur représentatif le plus proche dans le livre de codes. Au lieu de stocker les coordonnées complètes du sous-vecteur, seul l'index du centroïde correspondant est conservé.
- Représentation comprimée: La représentation comprimée finale se compose de
m
indices, un pour chaque sous-espace, collectivement appelés codes PQ. Ce codage réduit le besoin de stockage de D × 32 bits (en supposant des nombres à virgule flottante de 32 bits) à m × nbits bits, ce qui permet une compression substantielle tout en préservant la capacité d'approximation des distances vectorielles.
Pour plus de détails sur le réglage et l'optimisation des paramètres, voir Index params.
Exemple de compression
Considérons un vecteur de D = 128 dimensions utilisant des nombres à virgule flottante de 32 bits. Avec les paramètres PQ m = 64 (sous-vecteurs) et nbits = 8 (donc k = 2^8 = 256 centroïdes par sous-espace), nous pouvons comparer les besoins de stockage :
- Vecteur original : 128 dimensions × 32 bits = 4 096 bits
- Vecteur compressé PQ : 64 sous-vecteurs × 8 bits = 512 bits
Cela représente une réduction de 8 fois les besoins en stockage.
Calcul de la distance avec PQ
Lors d'une recherche de similarité avec un vecteur d'interrogation, PQ permet un calcul efficace de la distance grâce aux étapes suivantes :
Prétraitement de la requête
- Le vecteur d'interrogation est décomposé en
m
sous-vecteurs, ce qui correspond à la structure de décomposition originale de PQ. - Pour chaque sous-vecteur de requête et son livre de codes correspondant (contenant 2^nbits de centroïdes), les distances entre tous les centroïdes sont calculées et stockées.
- Cela génère
m
tables de recherche, où chaque table contient 2^nbits de distances.
- Le vecteur d'interrogation est décomposé en
Approximation de la distance
Pour tout vecteur de base de données représenté par des codes PQ, sa distance approximative par rapport au vecteur d'interrogation est calculée comme suit :
- Pour chacun des sous-vecteurs
m
, récupérer la distance précalculée à partir de la table de recherche correspondante en utilisant l'indice de centroïde stocké. - Additionner ces distances
m
pour obtenir la distance approximative basée sur un type de métrique spécifique (par exemple, la distance euclidienne).
- Pour chacun des sous-vecteurs
pq-process-1
IVF + PQ
L'index IVF_PQ combine les forces de l'IVF et du PQ pour accélérer les recherches. Le processus se déroule en deux étapes :
- Filtrage grossier avec IVF: IVF divise l'espace vectoriel en grappes, ce qui réduit l'étendue de la recherche. Au lieu d'évaluer l'ensemble des données, l'algorithme se concentre uniquement sur les grappes les plus proches du vecteur de la requête.
- Comparaison fine avec PQ: à l'intérieur des grappes sélectionnées, PQ utilise des représentations vectorielles compressées et quantifiées pour calculer rapidement des distances approximatives.
Les performances de l'index IVF_PQ sont fortement influencées par les paramètres qui contrôlent les algorithmes IVF et PQ. Le réglage de ces paramètres est essentiel pour obtenir des résultats optimaux pour un ensemble de données et une application donnés. Des informations plus détaillées sur ces paramètres et sur la manière de les régler sont disponibles dans Index params.
Création d'un index
Pour construire un index IVF_PQ
sur un champ de vecteurs dans Milvus, utilisez la méthode add_index()
, en spécifiant les paramètres index_type
, metric_type
et des paramètres supplémentaires pour l'index.
from pymilvus import MilvusClient
# Prepare index building params
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="your_vector_field_name", # Name of the vector field to be indexed
index_type="IVF_PQ", # Type of the index to create
index_name="vector_index", # Name of the index to create
metric_type="L2", # Metric type used to measure similarity
params={
"m": 4, # Number of sub-vectors to split eahc vector into
} # Index building params
)
Dans cette configuration :
index_type
: Le type d'index à construire. Dans cet exemple, la valeur estIVF_PQ
.metric_type
: La méthode utilisée pour calculer la distance entre les vecteurs. Les valeurs prises en charge sontCOSINE
,L2
etIP
. Pour plus d'informations, reportez-vous à la section Types de métriques.params
: Options de configuration supplémentaires pour la construction de l'index.m
: Nombre de sous-vecteurs à diviser en vecteurs.
Pour en savoir plus sur les paramètres de construction disponibles pour l'index
IVF_PQ
, reportez-vous à Paramètres de construction de l'index.
Une fois les paramètres de l'index configurés, vous pouvez créer l'index en utilisant directement la méthode create_index()
ou en passant les paramètres de l'index dans la méthode create_collection
. Pour plus d'informations, reportez-vous à la section Créer une collection.
Recherche sur l'index
Une fois l'index construit et les entités insérées, vous pouvez effectuer des recherches de similarité sur l'index.
search_params = {
"params": {
"nprobe": 10, # Number of clusters to search
}
}
res = MilvusClient.search(
collection_name="your_collection_name", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector
limit=3, # TopK results to return
search_params=search_params
)
Dans cette configuration :
params
: Options de configuration supplémentaires pour la recherche sur l'index.nprobe
: Nombre de clusters à rechercher.
Pour en savoir plus sur les paramètres de recherche disponibles pour l'index
IVF_PQ
, reportez-vous à Paramètres de recherche spécifiques à l'index.
Paramètres de l'index
Cette section présente une vue d'ensemble des paramètres utilisés pour construire un index et effectuer des recherches sur l'index.
Paramètres de construction d'index
Le tableau suivant répertorie les paramètres qui peuvent être configurés sur params
lors de la création d'un index.
Paramètre | Description de l'index | Plage de valeurs | Suggestion de réglage | |
---|---|---|---|---|
IVF | nlist | Le nombre de grappes à créer à l'aide de l'algorithme k-means pendant la construction de l'index. | Type: Entier Plage de valeurs: [1, 65536] Valeur par défaut: 128 | Les valeurs plus élevées de nlist améliorent le rappel en créant des grappes plus fines, mais augmentent le temps de construction de l'index. Optimisez en fonction de la taille du jeu de données et des ressources disponibles.Dans la plupart des cas, nous vous recommandons de définir une valeur comprise dans cet intervalle : [32, 4096]. |
PQ | m | Le nombre de sous-vecteurs (utilisés pour la quantification) à diviser chaque vecteur à haute dimension pendant le processus de quantification. | Type: Entier Plage de valeurs: [1, 65536] Valeur par défaut: Aucune | Une valeur plus élevée de m peut améliorer la précision, mais elle augmente également la complexité du calcul et l'utilisation de la mémoire.m doit être un diviseur de la dimension du vecteur(D) pour garantir une décomposition correcte. Une valeur couramment recommandée est m = D/2.Dans la plupart des cas, nous vous recommandons de choisir une valeur comprise dans cet intervalle : [D/8, D]. |
nbits | Le nombre de bits utilisés pour représenter l'indice du centroïde de chaque sous-vecteur sous forme comprimée. Il détermine directement la taille de chaque livre de codes. Chaque livre de codes contiendra 2^nbits de centroïdes. Par exemple, si nbits est fixé à 8, chaque sous-vecteur sera représenté par un indice de centroïde de 8 bits. Cela permet d'avoir 2^8 (256) centroïdes possibles dans le livre de codes pour ce sous-vecteur. | Type: Entier Plage de valeurs: [1, 64] Valeur par défaut: 8 | Une valeur plus élevée de nbits permet d'obtenir des livres de codes plus importants, ce qui peut conduire à des représentations plus précises des vecteurs originaux. Toutefois, cela signifie également qu'il faut utiliser plus de bits pour stocker chaque index, ce qui se traduit par une compression moindre.Dans la plupart des cas, nous vous recommandons de choisir une valeur comprise dans cette fourchette : [1, 16]. |
Paramètres de recherche spécifiques aux index
Le tableau suivant répertorie les paramètres qui peuvent être configurés dans search_params.params
lors d'une recherche sur l'index.
Paramètre | Description | Plage de valeurs | Suggestion de réglage | |
---|---|---|---|---|
IVF | nprobe | Le nombre de grappes à rechercher pour les candidats. | Type: Entier Plage de valeurs: [1, nlist] Valeur par défaut: 8 | Des valeurs plus élevées permettent de rechercher davantage de grappes, ce qui améliore le rappel en élargissant la portée de la recherche, mais au prix d'une latence accrue de la requête. Réglez nprobe proportionnellement à nlist pour équilibrer la vitesse et la précision.Dans la plupart des cas, nous vous recommandons de définir une valeur comprise dans cette fourchette : [1, nlist]. |