HNSW_PQ

HNSW_PQ nutzt Hierarchical Navigable Small World (HNSW)-Graphen mit Product Quantization (PQ), um eine fortschrittliche Vektorindizierungsmethode zu schaffen, die einen kontrollierbaren Kompromiss zwischen Größe und Genauigkeit bietet. Im Vergleich zu HNSW_SQ liefert dieser Indextyp eine höhere Wiederauffindungsrate bei gleichem Komprimierungsgrad, wenn auch mit geringerer Abfrageverarbeitungsgeschwindigkeit und längerer Indexerstellungszeit.

Überblick

HNSW_PQ kombiniert zwei Indizierungstechniken: HNSW für schnelle graphbasierte Navigation und PQ für effiziente Vektorkompression.

HNSW

HNSW konstruiert einen mehrschichtigen Graphen, bei dem jeder Knoten einem Vektor im Datensatz entspricht. In diesem Graphen sind die Knoten auf der Grundlage ihrer Ähnlichkeit miteinander verbunden, was eine schnelle Durchquerung des Datenraums ermöglicht. Die hierarchische Struktur ermöglicht es dem Suchalgorithmus, die in Frage kommenden Nachbarn einzugrenzen, wodurch der Suchprozess in hochdimensionalen Räumen erheblich beschleunigt wird.

Weitere Informationen finden Sie unter HNSW.

PQ

PQ ist eine Vektorkomprimierungstechnik, die hochdimensionale Vektoren in kleinere Untervektoren zerlegt, die dann quantisiert und komprimiert werden. Die Komprimierung reduziert den Speicherbedarf erheblich und beschleunigt die Entfernungsberechnungen.

Weitere Informationen finden Sie unter IVF_PQ.

HNSW + PQ

HNSW_PQ kombiniert die Stärken von HNSW und PQ, um eine effiziente ungefähre Suche nach den nächsten Nachbarn zu ermöglichen. Der Algorithmus verwendet PQ, um die Daten zu komprimieren (und damit den Speicherbedarf zu verringern), und baut dann einen HNSW-Graphen auf diesen komprimierten Vektoren auf, um ein schnelles Auffinden von Kandidaten zu ermöglichen. Während der Suche kann der Algorithmus optional die Kandidatenergebnisse mit Hilfe von Daten höherer Präzision verfeinern, um die Genauigkeit zu verbessern. So funktioniert der Prozess:

  1. Datenkomprimierung: PQ teilt jeden Vektor in mehrere Untervektoren auf und quantisiert sie mithilfe eines Codebuchs von Zentroiden, das durch Parameter wie m (Anzahl der Untervektoren) und nbits (Bits pro Untervektor) gesteuert wird.

  2. Konstruktion des Graphen: Die komprimierten Vektoren werden dann zum Aufbau eines HNSW-Graphen verwendet. Da die Vektoren in komprimierter Form gespeichert werden, ist der resultierende Graph in der Regel kleiner, benötigt weniger Speicherplatz und kann schneller durchlaufen werden, was den Schritt des Kandidatenabrufs erheblich beschleunigt.

  3. Abruf von Kandidaten: Wenn eine Abfrage ausgeführt wird, verwendet der Algorithmus die komprimierten Daten im HNSW-Graphen, um effizient einen Pool von Nachbarschaftskandidaten zu identifizieren. Durch diese graphbasierte Suche wird die Anzahl der zu berücksichtigenden Vektoren drastisch reduziert, wodurch sich die Abfragelatenz im Vergleich zu Brute-Force-Suchen verbessert.

  4. (Optional) Verfeinerung der Ergebnisse: Die anfänglichen Kandidatenergebnisse können zur Verbesserung der Genauigkeit anhand der folgenden Parameter verfeinert werden:

    • refine: Steuert, ob dieser Verfeinerungsschritt aktiviert ist. Wenn er auf true gesetzt ist, berechnet das System Entfernungen mit höherer Genauigkeit oder unkomprimierten Darstellungen neu.

    • refine_type: Gibt den Präzisionsgrad der Daten an, die während der Verfeinerung verwendet werden (z. B. SQ6, SQ8, BF16). Eine höhere Genauigkeit wie FP32 kann genauere Ergebnisse liefern, erfordert aber mehr Speicherplatz. Diese muss die Genauigkeit des ursprünglichen komprimierten Datensatzes um sq_type übersteigen.

    • refine_k: Wirkt wie ein Vergrößerungsfaktor. Wenn z. B. Ihr Top k 100 und refine_k 2 ist, ordnet das System die 200 besten Kandidaten neu und gibt die besten 100 zurück, was die Gesamtgenauigkeit erhöht.

Eine vollständige Liste der Parameter und der gültigen Werte finden Sie unter Indexparametern.

Index erstellen

Um einen HNSW_PQ -Index für ein Vektorfeld in Milvus zu erstellen, verwenden Sie die Methode add_index() und geben Sie die Parameter index_type, metric_type und zusätzliche Parameter für den Index an.

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
)

In dieser Konfiguration:

  • index_type: Der Typ des zu erstellenden Index. In diesem Beispiel setzen Sie den Wert auf HNSW_PQ.

  • metric_type: Die Methode zur Berechnung des Abstands zwischen Vektoren. Unterstützte Werte sind COSINE, L2 und IP. Einzelheiten finden Sie unter Metrische Typen.

  • params: Zusätzliche Konfigurationsoptionen für den Aufbau des Index. Weitere Informationen finden Sie unter Indexerstellungsparameter.

Sobald die Indexparameter konfiguriert sind, können Sie den Index erstellen, indem Sie die Methode create_index() direkt verwenden oder die Indexparameter in der Methode create_collection übergeben. Weitere Informationen finden Sie unter Sammlung erstellen.

Suche im Index

Sobald der Index erstellt und die Entitäten eingefügt sind, können Sie Ähnlichkeitssuchen im Index durchführen.

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
)

In dieser Konfiguration:

Index-Parameter

Dieser Abschnitt gibt einen Überblick über die Parameter, die für den Aufbau eines Index und die Durchführung von Suchen im Index verwendet werden.

Indexaufbau-Parameter

In der folgenden Tabelle sind die Parameter aufgeführt, die in params beim Aufbau eines Index konfiguriert werden können.

Parameter

Beschreibung

Wertebereich

Tuning-Vorschlag

HNSW

M

Maximale Anzahl der Verbindungen (oder Kanten), die jeder Knoten im Graphen haben kann, einschließlich der ausgehenden und eingehenden Kanten. Dieser Parameter wirkt sich direkt auf den Indexaufbau und die Suche aus.

Typ: Integer Bereich: [2, 2048]

Standardwert: 30 (bis zu 30 ausgehende und 30 eingehende Kanten pro Knoten)

Ein größerer M führt im Allgemeinen zu einer höheren Genauigkeit, erhöht jedoch den Speicheraufwand und verlangsamt sowohl den Indexaufbau als auch die Suche. M sollte für Datensätze mit hoher Dimensionalität oder wenn eine hohe Wiederauffindbarkeit entscheidend ist, erhöht werden.

Verringern Sie M, wenn die Speichernutzung und die Suchgeschwindigkeit im Vordergrund stehen.

In den meisten Fällen empfehlen wir Ihnen, einen Wert innerhalb dieses Bereichs zu wählen: [5, 100].

efConstruction

Anzahl der Nachbarschaftskandidaten, die bei der Indexerstellung für eine Verbindung in Betracht gezogen werden. Für jedes neue Element wird ein größerer Pool von Kandidaten ausgewertet, aber die maximale Anzahl der tatsächlich hergestellten Verbindungen ist immer noch durch M begrenzt.

Typ: Integer Bereich: [1, int_max]

Standardwert: 360

Ein höherer efConstruction führt normalerweise zu einem genaueren Index, da mehr potenzielle Verbindungen untersucht werden. Dies führt jedoch auch zu einer längeren Indizierungszeit und einem erhöhten Speicherverbrauch während des Aufbaus. Erwägen Sie, efConstruction zu erhöhen, um die Genauigkeit zu verbessern, insbesondere in Szenarien, in denen die Indizierungszeit weniger kritisch ist.

Ziehen Sie eine Verringerung von efConstruction in Betracht, um den Indexaufbau zu beschleunigen, wenn Ressourcenbeschränkungen ein Problem darstellen.

In den meisten Fällen wird empfohlen, einen Wert innerhalb dieses Bereichs festzulegen: [50, 500].

PQ

m

Die Anzahl der Untervektoren (für die Quantisierung), in die jeder hochdimensionale Vektor während des Quantisierungsprozesses unterteilt wird.

Typ: Integer Bereich: [1, 65536]

Standardwert: Keine

Ein höherer Wert von m kann die Genauigkeit verbessern, erhöht aber auch die Rechenkomplexität und den Speicherverbrauch. m muss ein Divisor der Vektordimension(D) sein, um eine korrekte Zerlegung zu gewährleisten. Ein allgemein empfohlener Wert ist m = D/2.

In den meisten Fällen wird empfohlen, einen Wert in diesem Bereich zu wählen: [D/8, D].

nbits

Die Anzahl der Bits, die verwendet werden, um den Index des Schwerpunkts jedes Untervektors in komprimierter Form darzustellen. Sie bestimmt direkt die Größe jedes Codebuchs. Jedes Codebuch enthält 2nbits Zentroide. Wenn zum Beispiel nbits auf 8 eingestellt ist, wird jeder Untervektor durch einen 8-Bit-Schwerpunktindex dargestellt. Dies ermöglicht28 (256) mögliche Schwerpunkte im Codebuch für diesen Teilvektor.

Typ: Integer Bereich: [1, 24]

Standardwert: 8

Ein höherer Wert von nbits ermöglicht größere Codebücher, was zu genaueren Darstellungen der ursprünglichen Vektoren führen kann. Allerdings bedeutet dies auch, dass mehr Bits zum Speichern jedes Index verwendet werden, was zu einer geringeren Komprimierung führt. In den meisten Fällen wird empfohlen, einen Wert innerhalb dieses Bereichs zu wählen: [1, 16].

refine

Ein boolesches Flag, das steuert, ob während der Suche ein Verfeinerungsschritt angewendet wird. Bei der Verfeinerung werden die ursprünglichen Ergebnisse neu geordnet, indem die genauen Abstände zwischen dem Abfragevektor und den Kandidaten berechnet werden.

Typ: Boolean Bereich: [true, false]

Standardwert: false

Setzen Sie true, wenn hohe Genauigkeit wichtig ist und Sie etwas langsamere Suchzeiten tolerieren können. Verwenden Sie false, wenn Geschwindigkeit eine Priorität ist und ein kleiner Kompromiss bei der Genauigkeit akzeptabel ist.

refine_type

Bestimmt die Genauigkeit der Daten, die während des Verfeinerungsprozesses verwendet werden. Diese Genauigkeit muss höher sein als die der komprimierten Vektoren (wie durch die Parameter m und nbits festgelegt).

Typ: String Bereich:[ SQ6, SQ8, BF16, FP16, FP32 ]

Standardwert: Keine

Verwenden Sie FP32 für maximale Präzision bei höheren Speicherkosten oder SQ6/SQ8 für eine bessere Komprimierung. BF16 und FP16 bieten eine ausgewogene Alternative.

Indexspezifische Suchparameter

In der folgenden Tabelle sind die Parameter aufgeführt, die in search_params.params für die Suche im Index konfiguriert werden können.

Parameter

Beschreibung

Wertebereich

Tuning-Vorschlag

HNSW

ef

Steuert die Breite der Suche während der Suche nach den nächsten Nachbarn. Er bestimmt, wie viele Knoten besucht und als potenzielle nächste Nachbarn bewertet werden. Dieser Parameter wirkt sich nur auf den Suchprozess aus und gilt ausschließlich für die unterste Schicht des Graphen.

Typ: Integer Bereich: [1, int_max]

Standardwert: limit (TopK nächste Nachbarn, die zurückgegeben werden)

Eine größere ef führt im Allgemeinen zu einer höheren Suchgenauigkeit, da mehr potenzielle Nachbarn berücksichtigt werden. Allerdings erhöht sich dadurch auch die Suchzeit. ef sollte erhöht werden, wenn eine hohe Wiederfindungsrate entscheidend ist und die Suchgeschwindigkeit weniger wichtig ist.

Ziehen Sie in Erwägung, ef zu verringern, um schnelleren Suchen den Vorzug zu geben, insbesondere in Szenarien, in denen eine leichte Verringerung der Genauigkeit akzeptabel ist.

In den meisten Fällen wird empfohlen, einen Wert innerhalb dieses Bereichs zu wählen: [K, 10K].

PQ

refine_k

Der Vergrößerungsfaktor, der steuert, wie viele zusätzliche Kandidaten während der Verfeinerungsphase (Reranking) im Verhältnis zu den angeforderten Top-K-Ergebnissen untersucht werden.

Typ: Float Bereich: [1, float_max)

Standardwert: 1

Höhere Werte von refine_k können die Auffindbarkeit und Genauigkeit verbessern, erhöhen aber auch die Suchzeit und den Ressourcenverbrauch. Ein Wert von 1 bedeutet, dass der Verfeinerungsprozess nur die anfänglichen Top-K-Ergebnisse berücksichtigt.

Try Managed Milvus for Free

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

Get Started
Feedback

War diese Seite hilfreich?