HNSW_PQ

O HNSW_PQ aproveita os gráficos Hierarchical Navigable Small World (HNSW) com Product Quantization (PQ), criando um método avançado de indexação de vectores que oferece um compromisso controlável entre tamanho e precisão. Em comparação com o HNSW_SQ, este tipo de índice proporciona uma taxa de recuperação mais elevada com o mesmo nível de compressão, embora com uma velocidade de processamento de consultas inferior e um tempo de construção do índice mais longo.

Síntese

O HNSW_PQ combina duas técnicas de indexação: HNSW para uma navegação rápida baseada em grafos e PQ para uma compressão vetorial eficiente.

HNSW

O HNSW constrói um grafo de várias camadas em que cada nó corresponde a um vetor no conjunto de dados. Neste gráfico, os nós são ligados com base na sua semelhança, permitindo uma rápida deslocação através do espaço de dados. A estrutura hierárquica permite que o algoritmo de pesquisa reduza os vizinhos candidatos, acelerando significativamente o processo de pesquisa em espaços de elevada dimensão.

Para mais informações, consulte HNSW.

PQ

PQ é uma técnica de compressão de vectores que decompõe vectores de elevada dimensão em sub-vectores mais pequenos, que são depois quantizados e comprimidos. A compressão reduz drasticamente os requisitos de memória e acelera os cálculos de distância.

Para mais informações, consulte IVF_PQ.

HNSW + PQ

O HNSW_PQ combina os pontos fortes do HNSW e do PQ para permitir uma pesquisa eficiente do vizinho mais próximo aproximado. Utiliza PQ para comprimir os dados (reduzindo assim a utilização de memória) e, em seguida, constrói um gráfico HNSW nestes vectores comprimidos para permitir uma rápida recuperação de candidatos. Durante a pesquisa, o algoritmo pode, opcionalmente, refinar os resultados dos candidatos utilizando dados de maior precisão para melhorar a exatidão. Eis como funciona o processo:

  1. Compressão de dados: O PQ divide cada vetor em vários sub-vectores e quantifica-os utilizando um livro de códigos de centróides, controlado por parâmetros como m (contagem de sub-vectores) e nbits (bits por sub-vetor).

  2. Construção de gráficos: Os vectores comprimidos são então utilizados para construir um gráfico HNSW. Como os vectores são armazenados de forma comprimida, o gráfico resultante é normalmente mais pequeno, requer menos memória e pode ser percorrido mais rapidamente - acelerando significativamente o passo de recuperação de candidatos.

  3. Recuperação de candidatos: Quando uma consulta é executada, o algoritmo utiliza os dados comprimidos no gráfico HNSW para identificar eficientemente um conjunto de vizinhos candidatos. Esta pesquisa baseada no gráfico reduz drasticamente o número de vectores que devem ser considerados, melhorando a latência da consulta em comparação com as pesquisas de força bruta.

  4. (Opcional) Refinamento de resultados: Os resultados candidatos iniciais podem ser refinados para melhor precisão, com base nos seguintes parâmetros:

    • refine: Controla se esta etapa de refinamento está activada. Quando definido para true, o sistema recalcula as distâncias utilizando representações de maior precisão ou não comprimidas.

    • refine_type: Especifica o nível de precisão dos dados utilizados durante o refinamento (por exemplo, SQ6, SQ8, BF16). Uma escolha de maior precisão, como FP32, pode produzir resultados mais exactos, mas requer mais memória. Isto deve exceder a precisão do conjunto de dados comprimido original em sq_type.

    • refine_k: Actua como um fator de ampliação. Por exemplo, se o seu top k for 100 e refine_k for 2, o sistema volta a classificar os 200 principais candidatos e devolve os 100 melhores, aumentando a precisão geral.

Para obter uma lista completa de parâmetros e valores válidos, consulte Parâmetros do índice.

Criar índice

Para construir um índice HNSW_PQ num campo vetorial em Milvus, utilize o método add_index(), especificando os parâmetros index_type, metric_type, e parâmetros adicionais para o índice.

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
)

Nesta configuração:

  • index_type: O tipo de índice a construir. Neste exemplo, defina o valor para HNSW_PQ.

  • metric_type: O método utilizado para calcular a distância entre vectores. Os valores suportados incluem COSINE, L2, e IP. Para obter detalhes, consulte Tipos de métricas.

  • params: Opções de configuração adicionais para criar o índice. Para obter detalhes, consulte Parâmetros de construção de índice.

Assim que os parâmetros do índice estiverem configurados, pode criar o índice utilizando diretamente o método create_index() ou passando os parâmetros do índice no método create_collection. Para obter detalhes, consulte Criar coleção.

Pesquisar no índice

Depois de o índice ter sido criado e as entidades terem sido inseridas, pode efetuar pesquisas de similaridade no índice.

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
)

Nesta configuração:

Parâmetros de índice

Esta secção fornece uma visão geral dos parâmetros utilizados para construir um índice e executar pesquisas no índice.

Parâmetros de construção de índice

A tabela seguinte lista os parâmetros que podem ser configurados em params ao construir um índice.

Parâmetro

Descrição

Intervalo de valores

Sugestão de ajuste

HNSW

M

Número máximo de ligações (ou arestas) que cada nó pode ter no gráfico, incluindo as arestas de saída e de entrada. Este parâmetro afecta diretamente a construção e a pesquisa do índice.

Tipo: Integer Range: [2, 2048]

Valor predefinido: 30 (até 30 arestas de saída e 30 arestas de entrada por nó)

Um M maior geralmente leva a uma maior precisão, mas aumenta a sobrecarga de memória e torna mais lenta a construção do índice e a pesquisa. Considere aumentar o M para conjuntos de dados com elevada dimensionalidade ou quando é crucial uma elevada recuperação.

Considere diminuir M quando a utilização da memória e a velocidade de pesquisa forem as principais preocupações.

Na maioria dos casos, recomendamos que você defina um valor dentro deste intervalo: [5, 100].

efConstruction

Número de vizinhos candidatos considerados para conexão durante a construção do índice. Um conjunto maior de candidatos é avaliado para cada novo elemento, mas o número máximo de conexões realmente estabelecidas ainda é limitado por M.

Tipo: Integer Range: [1, int_max]

Valor predefinido: 360

Um valor mais elevado em efConstruction resulta normalmente num índice mais preciso, uma vez que são exploradas mais ligações potenciais. No entanto, isto também leva a um tempo de indexação mais longo e a uma maior utilização de memória durante a construção. Considere aumentar efConstruction para melhorar a precisão, especialmente em cenários em que o tempo de indexação é menos crítico.

Considere diminuir efConstruction para acelerar a construção do índice quando as restrições de recursos são uma preocupação.

Na maioria dos casos, recomendamos que defina um valor dentro deste intervalo: [50, 500].

PQ

m

O número de sub-vectores (utilizados para quantização) para dividir cada vetor de alta dimensão durante o processo de quantização.

Tipo: Integer Intervalo: [1, 65536]

Valor predefinido: Nenhum

Um valor m mais elevado pode melhorar a precisão, mas também aumenta a complexidade computacional e a utilização de memória. m tem de ser um divisor da dimensão do vetor(D) para garantir uma decomposição adequada. Um valor geralmente recomendado é m = D/2.

Na maioria dos casos, recomendamos que defina um valor dentro deste intervalo: [D/8, D].

nbits

O número de bits utilizados para representar o índice do centróide de cada sub-vetor na forma comprimida. Determina diretamente o tamanho de cada livro de códigos. Cada livro de códigos conterá centroides de 2nbits. Por exemplo, se nbits estiver definido para 8, cada sub-vetor será representado por um índice de centróide de 8 bits. Isto permite28 (256) centróides possíveis no livro de códigos para esse sub-vetor.

Tipo: Integer Intervalo: [1, 24]

Valor por defeito: 8

Um valor nbits mais alto permite livros de códigos maiores, potencialmente levando a representações mais precisas dos vectores originais. No entanto, também significa utilizar mais bits para armazenar cada índice, resultando numa menor compressão. Na maioria dos casos, recomendamos que defina um valor dentro deste intervalo: [1, 16].

refine

Um sinalizador booleano que controla se uma etapa de refinamento é aplicada durante a pesquisa. O refinamento envolve a reordenação dos resultados iniciais através do cálculo de distâncias exactas entre o vetor de consulta e os candidatos.

Tipo: Booleano Intervalo: [true, false]

Valor predefinido: false

Defina como true se for essencial uma precisão elevada e puder tolerar tempos de pesquisa ligeiramente mais lentos. Utilize false se a velocidade for uma prioridade e for aceitável um pequeno compromisso na precisão.

refine_type

Determina a precisão dos dados utilizados durante o processo de refinamento. Esta precisão tem de ser superior à dos vectores comprimidos (tal como definido pelos parâmetros m e nbits ).

Tipo: String Intervalo:[ SQ6, SQ8, BF16, FP16, FP32 ]

Valor por defeito: Nenhum

Utilize FP32 para obter a máxima precisão com um custo de memória mais elevado, ou SQ6/SQ8 para uma melhor compressão. BF16 e FP16 oferecem uma alternativa equilibrada.

Parâmetros de pesquisa específicos do índice

A tabela seguinte lista os parâmetros que podem ser configurados em search_params.params ao pesquisar no índice.

Parâmetro

Descrição

Intervalo de valores

Sugestão de ajuste

HNSW

ef

Controla a amplitude da pesquisa durante a recuperação do vizinho mais próximo. Ele determina quantos nós são visitados e avaliados como possíveis vizinhos mais próximos. Este parâmetro afecta apenas o processo de pesquisa e aplica-se exclusivamente à camada inferior do gráfico.

Tipo: Integer Intervalo: [1, int_max]

Valor por defeito: limite (TopK vizinhos mais próximos a devolver)

Um ef maior conduz geralmente a uma maior precisão de pesquisa, uma vez que são considerados mais vizinhos potenciais. Considere aumentar ef quando a obtenção de uma alta recuperação é crítica e a velocidade de pesquisa é menos preocupante.

Considere diminuir ef para dar prioridade a pesquisas mais rápidas, especialmente em cenários em que uma ligeira redução na precisão é aceitável.

Na maioria dos casos, recomendamos que defina um valor dentro deste intervalo: [K, 10K].

PQ

refine_k

O fator de ampliação que controla quantos candidatos extra são examinados durante a fase de refinamento (reranking), relativamente aos K resultados principais solicitados.

Tipo: Float Intervalo: [1, float_max)

Valor por defeito: 1

Valores mais elevados de refine_k podem melhorar a recuperação e a precisão, mas também aumentam o tempo de pesquisa e a utilização de recursos. Um valor de 1 significa que o processo de refinamento considera apenas os K resultados principais iniciais.

Try Managed Milvus for Free

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

Get Started
Feedback

Esta página foi útil?