HNSW_PRQ

O HNSW_PRQ aproveita os gráficos Hierarchical Navigable Small World (HNSW) com Product Residual Quantization (PRQ), oferecendo um método avançado de indexação de vectores que permite ajustar a relação entre o tamanho do índice e a precisão. A PRQ vai além da Quantização de Produto (PQ) tradicional, introduzindo uma etapa de quantização residual (RQ) para capturar informações adicionais, resultando em maior precisão ou índices mais compactos em comparação com métodos puramente baseados em PQ. No entanto, os passos adicionais podem levar a um maior custo computacional durante a construção e pesquisa do índice.

Síntese

O HNSW_PRQ combina duas técnicas de indexação: HSNW para uma navegação rápida baseada em grafos e PRQ 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 obter mais informações, consulte HNSW.

PRQ

PRQ é uma abordagem de compressão vetorial em várias fases que combina duas técnicas complementares: PQ e RQ. Ao dividir primeiro um vetor de elevada dimensão em sub-vectores mais pequenos (através de PQ) e depois quantizar qualquer diferença restante (através de RQ), o PRQ consegue uma representação compacta mas precisa dos dados originais.

A figura seguinte mostra o seu funcionamento.

Hnsw Prq Hnsw Prq

  1. Quantização do produto (PQ)

    Nesta fase, o vetor original é dividido em sub-vectores mais pequenos, e cada sub-vetor é mapeado para o seu centróide mais próximo num livro de códigos aprendido. Este mapeamento reduz significativamente o tamanho dos dados, mas introduz algum erro de arredondamento, uma vez que cada sub-vetor é aproximado por um único centróide. Para mais pormenores, consulte IVF_PQ.

  2. Quantização residual (RQ)

    Após a fase PQ, a RQ quantiza o resíduo - a diferença entre o vetor original e a sua aproximação baseada na PQ - utilizando livros de códigos adicionais. Como este resíduo é tipicamente muito mais pequeno, pode ser codificado com mais precisão sem um grande aumento no armazenamento.

    O parâmetro nrq determina o número de vezes que este resíduo é quantizado iterativamente, permitindo-lhe ajustar o equilíbrio entre a eficiência e a precisão da compressão.

  3. Representação de compressão final

    Quando o RQ termina a quantização do resíduo, os códigos inteiros do PQ e do RQ são combinados num único índice comprimido. Ao capturar detalhes refinados que o PQ sozinho poderia perder, o RQ melhora a precisão sem causar um aumento significativo no armazenamento. Esta sinergia entre PQ e RQ é o que define PRQ.

HNSW + PRQ

Ao combinar o HNSW com o PRQ, o HNSW_PRQ mantém a pesquisa rápida baseada em gráficos do HNSW, aproveitando a compactação em vários estágios do PRQ. O fluxo de trabalho tem o seguinte aspeto:

  1. Compressão de dados: Cada vetor é primeiro transformado através de PQ para uma representação grosseira e, em seguida, os resíduos são quantizados através de RQ para um maior refinamento. O resultado é um conjunto de códigos compactos que representam cada vetor.

  2. Construção de gráficos: Os vectores comprimidos (incluindo os códigos PQ e RQ) formam a base para a construção do gráfico HNSW. Como os dados são armazenados numa forma compacta, o gráfico requer menos memória e a navegação através dele é acelerada.

  3. Recuperação de candidatos: Durante a pesquisa, o HNSW usa as representações compactadas para percorrer o gráfico e recuperar um conjunto de candidatos. Isto reduz drasticamente o número de vectores que precisam de ser considerados.

  4. (Opcional) Refinamento de resultados: Os resultados iniciais dos candidatos podem ser refinados para uma 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_PRQ 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_PRQ", # 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,
        "nrq": 1,
        "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 afinação

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].

PRQ

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: Inteiro 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].

nrq

Controla quantos subquantizadores residuais são usados no estágio RQ. Um maior número de subquantizadores pode potencialmente alcançar uma maior compressão, mas pode introduzir uma maior perda de informação.

Tipo: Integer Intervalo: [1, 16]

Valor predefinido: 2

Um valor mais elevado em nrq permite passos adicionais de subquantização residual, levando potencialmente a uma reconstrução mais precisa dos vectores originais. No entanto, também significa armazenar e computar mais subquantizadores, resultando num tamanho de índice maior e numa maior sobrecarga computacional.

refine

Um sinalizador booleano que controla se um passo de refinamento é aplicado 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: Boolean Range: [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].

PRQ

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?