HNSW
L'indice HNSW è un algoritmo di indicizzazione basato su grafi che può migliorare le prestazioni nella ricerca di vettori flottanti ad alta dimensione. Offre un'eccellente precisione di ricerca e una bassa latenza, ma richiede un elevato overhead di memoria per mantenere la sua struttura a grafo gerarchico.
Panoramica
L'algoritmo Hierarchical Navigable Small World (HNSW) costruisce un grafo a più livelli, come una mappa con diversi livelli di zoom. Il livello inferiore contiene tutti i punti dati, mentre i livelli superiori sono costituiti da un sottoinsieme di punti dati campionati dal livello inferiore.
In questa gerarchia, ogni livello contiene nodi che rappresentano i punti di dati, collegati da bordi che indicano la loro vicinanza. Gli strati superiori forniscono salti a lunga distanza per avvicinarsi rapidamente all'obiettivo, mentre gli strati inferiori consentono una ricerca a grana fine per ottenere i risultati più precisi.
Ecco come funziona:
- Punto di ingresso: La ricerca inizia da un punto di ingresso fisso nel livello superiore, che è un nodo predeterminato del grafo.
- Ricerca avida: L'algoritmo si muove avidamente verso il vicino più prossimo del livello corrente, finché non riesce ad avvicinarsi al vettore della domanda. Gli strati superiori hanno una funzione di navigazione, agendo come un filtro grossolano per individuare i potenziali punti di ingresso per la ricerca più fine ai livelli inferiori.
- Discesa del livello: Una volta raggiunto un minimo locale nel livello corrente, l'algoritmo salta al livello inferiore, utilizzando un collegamento prestabilito, e ripete la ricerca avida.
- Raffinamentofinale: Questo processo continua fino al raggiungimento del livello inferiore, dove un'ultima fase di raffinamento identifica i vicini più prossimi.
HNSW
Le prestazioni di HNSW dipendono da diversi parametri chiave che controllano sia la struttura del grafo sia il comportamento della ricerca. Questi includono:
M
: Il numero massimo di spigoli o connessioni che ogni nodo può avere nel grafo a ogni livello della gerarchia. Un numero più elevato diM
determina un grafo più denso e aumenta il richiamo e l'accuratezza, poiché la ricerca ha più percorsi da esplorare, ma consuma anche più memoria e rallenta il tempo di inserimento a causa delle connessioni aggiuntive. Come mostrato nell'immagine precedente, M = 5 indica che ogni nodo del grafo HNSW è collegato direttamente a un massimo di altri 5 nodi. Questo crea una struttura del grafo moderatamente densa, in cui i nodi hanno più percorsi per raggiungere altri nodi.efConstruction
: Numero di candidati considerati durante la costruzione dell'indice. Un numero più alto diefConstruction
generalmente produce un grafo di qualità migliore, ma richiede più tempo per la costruzione.ef
: Il numero di vicini valutati durante la ricerca. L'aumento dief
migliora la probabilità di trovare i vicini più vicini, ma rallenta il processo di ricerca.
Per i dettagli su come regolare queste impostazioni in base alle proprie esigenze, fare riferimento a Parametri indice.
Creare l'indice
Per costruire un indice HNSW
su un campo vettoriale in Milvus, utilizzare il metodo add_index()
, specificando i parametri index_type
, metric_type
e ulteriori per l'indice.
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", # 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": 64, # Maximum number of neighbors each node can connect to in the graph
"efConstruction": 100 # Number of candidate neighbors considered for connection during index construction
} # Index building params
)
In questa configurazione:
index_type
: Il tipo di indice da costruire. In questo esempio, impostare il valore suHNSW
.metric_type
: Il metodo utilizzato per calcolare la distanza tra i vettori. I valori supportati sonoCOSINE
,L2
eIP
. Per maggiori dettagli, consultare Tipi di metriche.params
: Opzioni di configurazione aggiuntive per la creazione dell'indice.M
: Numero massimo di vicini a cui ogni nodo può connettersi.efConstruction
: Numero di vicini candidati considerati per la connessione durante la costruzione dell'indice.
Per conoscere altri parametri di costruzione disponibili per l'indice
HNSW
, fare riferimento a Parametri di costruzione dell'indice.
Una volta configurati i parametri dell'indice, è possibile creare l'indice utilizzando direttamente il metodo create_index()
o passando i parametri dell'indice nel metodo create_collection
. Per i dettagli, fare riferimento a Creare una raccolta.
Ricerca nell'indice
Una volta costruito l'indice e inserite le entità , è possibile eseguire ricerche di similarità sull'indice.
search_params = {
"params": {
"ef": 10, # Number of neighbors to consider during the 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=10, # TopK results to return
search_params=search_params
)
In questa configurazione:
params
: Opzioni di configurazione aggiuntive per la ricerca sull'indice.ef
: Numero di vicini da considerare durante la ricerca.
Per conoscere altri parametri di ricerca disponibili per l'indice
HNSW
, fare riferimento a Parametri di ricerca specifici per l'indice.
Parametri dell'indice
Questa sezione fornisce una panoramica dei parametri utilizzati per la creazione di un indice e per l'esecuzione di ricerche sull'indice.
Parametri di costruzione dell'indice
La tabella seguente elenca i parametri che possono essere configurati in params
quando si costruisce un indice.
Parametro | Descrizione | Valore Intervallo | Suggerimento per la messa a punto |
---|---|---|---|
M | Numero massimo di connessioni (o bordi) che ogni nodo può avere nel grafo, compresi i bordi in uscita e in entrata. Questo parametro influisce direttamente sulla costruzione dell'indice e sulla ricerca. | Tipo: Intero Intervallo: [2, 2048] Valore predefinito: 30 (fino a 30 bordi uscenti e 30 bordi entranti per nodo) | Un M più grande porta generalmente a una maggiore accuratezza, ma aumenta l'overhead di memoria e rallenta la costruzione dell'indice e la ricerca.Considerare l'aumento di M per i set di dati con elevata dimensionalità o quando è fondamentale un richiamo elevato.Considerare di diminuire M quando l'uso della memoria e la velocità di ricerca sono le principali preoccupazioni.Nella maggior parte dei casi, si consiglia di impostare un valore compreso in questo intervallo: [5, 100]. |
efConstruction | Numero di vicini candidati considerati per la connessione durante la costruzione dell'indice. Per ogni nuovo elemento viene valutato un pool più ampio di candidati, ma il numero massimo di connessioni effettivamente stabilite è ancora limitato da M . | Tipo: Intero Intervallo: [1, int_max] Valore predefinito: 360 | Un valore più alto di efConstruction produce in genere un indice più accurato, poiché vengono esplorate più connessioni potenziali. Tuttavia, ciò comporta anche tempi di indicizzazione più lunghi e un maggiore utilizzo della memoria durante la costruzione.Considerare di aumentare efConstruction per migliorare l'accuratezza, soprattutto in scenari in cui il tempo di indicizzazione è meno critico.Considerare di diminuire efConstruction per accelerare la costruzione dell'indice quando le risorse sono limitate.Nella maggior parte dei casi, si consiglia di impostare un valore compreso in questo intervallo: [50, 500]. |
Parametri di ricerca specifici per l'indice
La tabella seguente elenca i parametri che possono essere configurati in search_params.params
durante la ricerca sull'indice.
Parametro | Descrizione | Valore Intervallo | Suggerimento di sintonizzazione |
---|---|---|---|
ef | Controlla l'ampiezza della ricerca durante il recupero dei vicini. Determina il numero di nodi visitati e valutati come potenziali vicini. Questo parametro influisce solo sul processo di ricerca e si applica esclusivamente al livello inferiore del grafo. | Tipo: Intero Intervallo: [1, int_max] Valore predefinito: limit (TopK nearest neighbors da restituire) | Un valore maggiore di ef porta generalmente a una maggiore accuratezza della ricerca, poiché vengono considerati più potenziali vicini. Tuttavia, questo aumenta anche il tempo di ricerca.Considerare di aumentare ef quando è fondamentale ottenere un richiamo elevato e la velocità di ricerca è meno importante.Considerare di diminuire ef per dare priorità a ricerche più veloci, soprattutto in scenari in cui una leggera riduzione dell'accuratezza è accettabile.Nella maggior parte dei casi, si consiglia di impostare un valore compreso in questo intervallo: [K, 10K]. |