HNSW_PQ

HNSW_PQ exploite les graphes Hierarchical Navigable Small World (HNSW) avec la quantification de produit (PQ), créant une méthode d'indexation vectorielle avancée qui offre un compromis contrôlable entre la taille et la précision. Comparé au HNSW_SQ, ce type d'index offre un taux de rappel plus élevé au même niveau de compression, bien que la vitesse de traitement des requêtes soit plus faible et le temps de construction de l'index plus long.

Vue d'ensemble

HNSW_PQ combine deux techniques d'indexation : HNSW pour une navigation rapide dans les graphes et PQ pour une compression vectorielle efficace.

HNSW

HNSW construit un graphe multicouche où chaque nœud correspond à un vecteur de l'ensemble de données. Dans ce graphe, les nœuds sont connectés en fonction de leur similarité, ce qui permet de parcourir rapidement l'espace de données. La structure hiérarchique permet à l'algorithme de recherche de réduire le nombre de voisins candidats, ce qui accélère considérablement le processus de recherche dans les espaces à haute dimension.

Pour plus d'informations, voir HNSW.

PQ

PQ est une technique de compression vectorielle qui décompose les vecteurs de haute dimension en sous-vecteurs plus petits, qui sont ensuite quantifiés et compressés. La compression réduit considérablement les besoins en mémoire et accélère les calculs de distance.

Pour plus d'informations, voir IVF_PQ.

HNSW + PQ

HNSW_PQ combine les forces de HNSW et de PQ pour permettre une recherche efficace du plus proche voisin. Il utilise PQ pour compresser les données (réduisant ainsi l'utilisation de la mémoire), puis construit un graphe HNSW sur ces vecteurs compressés pour permettre une recherche rapide des candidats. Au cours de la recherche, l'algorithme peut éventuellement affiner les résultats des candidats en utilisant des données de plus grande précision pour améliorer l'exactitude. Voici comment fonctionne le processus :

  1. Compression des données: PQ divise chaque vecteur en plusieurs sous-vecteurs et les quantifie à l'aide d'un livre de codes de centroïdes, contrôlé par des paramètres tels que m (nombre de sous-vecteurs) et nbits (bits par sous-vecteur).

  2. Construction du graphique: Les vecteurs compressés sont ensuite utilisés pour construire un graphe HNSW. Comme les vecteurs sont stockés sous une forme compressée, le graphe résultant est généralement plus petit, nécessite moins de mémoire et peut être parcouru plus rapidement, ce qui accélère considérablement l'étape de recherche des candidats.

  3. Recherche de candidats: Lorsqu'une requête est exécutée, l'algorithme utilise les données compressées du graphe HNSW pour identifier efficacement un ensemble de voisins candidats. Cette recherche basée sur le graphe réduit considérablement le nombre de vecteurs à prendre en compte, ce qui améliore la latence de la requête par rapport aux recherches brutes.

  4. Affinage des résultats (facultatif): Les résultats initiaux des candidats peuvent être affinés pour une meilleure précision, en fonction des paramètres suivants :

    • refine: Contrôle si cette étape d'affinage est activée. Lorsqu'il est défini sur true, le système recalcule les distances à l'aide de représentations non compressées ou de précision supérieure.

    • refine_type: Spécifie le niveau de précision des données utilisées pendant l'affinage (par exemple, SQ6, SQ8, BF16). Un choix de précision plus élevé, tel que FP32, peut donner des résultats plus précis, mais nécessite plus de mémoire. La précision doit être supérieure à celle de l'ensemble de données compressées d'origine de sq_type.

    • refine_k: Agit comme un facteur d'agrandissement. Par exemple, si votre top k est 100 et que refine_k est 2, le système reclasse les 200 premiers candidats et renvoie les 100 meilleurs, ce qui améliore la précision globale.

Pour obtenir la liste complète des paramètres et des valeurs valides, reportez-vous à la section Paramètres de l'index.

Création d'un index

Pour construire un index HNSW_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 d'autres paramètres 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="HNSW_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": 30, # Maximum number of neighbors each node can connect to in the graph
        "efConstruction": 360, # Number of candidate neighbors considered for connection during index construction
        "m": 384, 
        "nbits": 8,
        "refine": true, # Whether to enable the refinement step
        "refine_type": "SQ8" # Precision level of data used for refinement
    } # Index building params
)

Dans cette configuration :

  • index_type: Le type d'index à construire. Dans cet exemple, la valeur est HNSW_PQ.

  • metric_type: La méthode utilisée pour calculer la distance entre les vecteurs. Les valeurs prises en charge sont COSINE, L2 et IP. Pour plus d'informations, reportez-vous à la section Types de métriques.

  • params: Options de configuration supplémentaires pour la construction de l'index. Pour plus d'informations, reportez-vous à la section 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 transmettant 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": {
        "ef": 10, # Parameter controlling query time/accuracy trade-off
        "refine_k": 1 # The magnification factor
    }
}

res = MilvusClient.search(
    collection_name="your_collection_name", # Collection name
    anns_field="vector_field",  # Vector field 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 :

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 dans 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

HNSW

M

Nombre maximal de connexions (ou d'arêtes) que chaque nœud peut avoir dans le graphe, y compris les arêtes sortantes et entrantes. Ce paramètre affecte directement la construction de l'index et la recherche.

Type: Integer (nombre entier) Plage: [2, 2048]

Valeur par défaut: 30 (jusqu'à 30 arêtes sortantes et 30 arêtes entrantes par nœud)

Une valeur plus élevée de M entraîne généralement une plus grande précision, mais augmente la charge de mémoire et ralentit à la fois la construction de l'index et la recherche. Envisagez d'augmenter M pour les ensembles de données de grande dimensionnalité ou lorsqu'un rappel élevé est crucial.

Pensez à diminuer M lorsque l'utilisation de la mémoire et la vitesse de recherche sont des préoccupations majeures.

Dans la plupart des cas, nous vous recommandons de définir une valeur comprise dans cette fourchette : [5, 100].

efConstruction

Un plus grand nombre de candidats est évalué pour chaque nouvel élément, mais le nombre maximum de connexions réellement établies est toujours limité par M.

Type: Integer (nombre entier) Plage: [1, int_max]

Valeur par défaut: 360

Une valeur plus élevée de efConstruction se traduit généralement par un index plus précis, étant donné que davantage de connexions potentielles sont explorées. Cependant, cela entraîne également un allongement du temps d'indexation et une utilisation accrue de la mémoire lors de la construction. Envisagez d'augmenter efConstruction pour améliorer la précision, en particulier dans les scénarios où le temps d'indexation est moins critique.

Pensez à diminuer efConstruction pour accélérer la construction de l'index lorsque les ressources sont limitées.

Dans la plupart des cas, nous vous recommandons de définir une valeur comprise dans cette fourchette : [50, 500].

PQ

m

Le nombre de sous-vecteurs (utilisés pour la quantification) à diviser chaque vecteur de haute dimension pendant le processus de quantification.

Type: Entier Plage: [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 des centroïdes de 2nbits. 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'avoir28 (256) centroïdes possibles dans le livre de codes pour ce sous-vecteur.

Type: Entier Plage: [1, 24]

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 d'origine. Dans la plupart des cas, nous vous recommandons de choisir une valeur comprise dans cette fourchette : [1, 16].

refine

Indicateur booléen qui contrôle l'application d'une étape d'affinage pendant la recherche. L'affinage consiste à reclasser les résultats initiaux en calculant les distances exactes entre le vecteur de la requête et les candidats.

Type: booléen : Plage booléenne : [true, false]

Valeur par défaut: false

Définissez true si une grande précision est essentielle et que vous pouvez tolérer des temps de recherche légèrement plus lents. Utilisez false si la rapidité est une priorité et qu'un compromis mineur sur la précision est acceptable.

refine_type

Cette précision doit être supérieure à celle des vecteurs compressés (définie par les paramètres m et nbits ).

Type: Plage:[ SQ6, SQ8, BF16, FP16, FP32 ]

Valeur par défaut: Aucune

Utilisez FP32 pour une précision maximale avec un coût de mémoire plus élevé, ou SQ6/SQ8 pour une meilleure compression. BF16 et FP16 offrent une alternative équilibrée.

Paramètres de recherche spécifiques à l'index

Le tableau suivant répertorie les paramètres qui peuvent être configurés dans search_params.params lors d'une recherche dans l'index.

Paramètre

Paramètre Description

Plage de valeurs

Suggestion de réglage

HNSW

ef

Contrôle l'étendue de la recherche lors de l'extraction des plus proches voisins. Il détermine le nombre de nœuds visités et évalués en tant que plus proches voisins potentiels. Ce paramètre n'affecte que le processus de recherche et s'applique exclusivement à la couche inférieure du graphe.

Type: Entier Portée: [1, int_max]

Valeur par défaut: limit (TopK plus proches voisins à retourner)

Une valeur plus élevée de ef permet généralement d'améliorer la précision de la recherche, car davantage de voisins potentiels sont pris en compte. Envisagez d'augmenter ef lorsqu'il est essentiel d'obtenir un rappel élevé et que la vitesse de recherche n'est pas une préoccupation majeure.

Pensez à diminuer ef pour privilégier les recherches plus rapides, en particulier dans les scénarios où une légère réduction de la précision est acceptable.

Dans la plupart des cas, nous vous recommandons de fixer une valeur comprise dans cette fourchette : [K, 10K].

PQ

refine_k

Facteur d'agrandissement qui contrôle le nombre de candidats supplémentaires examinés au cours de l'étape d'affinage (reranking), par rapport aux K premiers résultats demandés.

Type: Flottant Plage: [1, float_max)

Valeur par défaut: 1

Des valeurs élevées de refine_k peuvent améliorer le rappel et la précision, mais augmentent également le temps de recherche et l'utilisation des ressources. Une valeur de 1 signifie que le processus d'affinage ne prend en compte que les K premiers résultats.

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

Cette page a-t - elle été utile ?