🚀 Experimente o Zilliz Cloud, o Milvus totalmente gerenciado, gratuitamente—experimente um desempenho 10x mais rápido! Experimente Agora>>

milvus-logo
LFAI
  • Home
  • Blog
  • Pesquisa eficiente de similaridade de vetores em fluxos de trabalho de recomendação usando Milvus com NVIDIA Merlin

Pesquisa eficiente de similaridade de vetores em fluxos de trabalho de recomendação usando Milvus com NVIDIA Merlin

  • Engineering
December 15, 2023
Burcin Bozkaya

Este post foi publicado pela primeira vez no canal NVIDIA Merlin's Medium e editado e republicado aqui com permissão. Foi escrito em conjunto por Burcin Bozkaya e William Hicks da NVIDIA e Filip Haltmayer e Li Liu da Zilliz.

Introdução

Os sistemas de recomendação modernos (Recsys) consistem em pipelines de formação/inferência que envolvem várias fases de ingestão de dados, pré-processamento de dados, formação de modelos e ajuste de hiperparâmetros para recuperação, filtragem, classificação e pontuação de itens relevantes. Um componente essencial de um sistema de recomendação é a recuperação ou descoberta dos elementos mais relevantes para um utilizador, especialmente na presença de grandes catálogos de itens. Este passo envolve normalmente uma pesquisa aproximada do vizinho mais próximo (ANN) numa base de dados indexada de representações vectoriais de baixa dimensão (ou seja, embeddings) de atributos de produtos e utilizadores criados a partir de modelos de aprendizagem profunda que treinam em interações entre utilizadores e produtos/serviços.

O NVIDIA Merlin, uma estrutura de código aberto desenvolvida para treinar modelos de ponta a ponta para fazer recomendações em qualquer escala, integra-se com um índice de base de dados vetorial eficiente e uma estrutura de pesquisa. Uma dessas estruturas que ganhou muita atenção recentemente é a Milvus, uma base de dados vetorial de código aberto criada pela Zilliz. Ela oferece recursos rápidos de índice e consulta. O Milvus recentemente adicionou suporte à aceleração de GPU que usa GPUs NVIDIA para sustentar fluxos de trabalho de IA. O suporte à aceleração de GPU é uma ótima notícia porque uma biblioteca de pesquisa vetorial acelerada possibilita consultas simultâneas rápidas, impactando positivamente os requisitos de latência nos sistemas de recomendação atuais, onde os desenvolvedores esperam muitas solicitações simultâneas. Milvus tem mais de 5M docker pulls, ~23k estrelas no GitHub (em setembro de 2023), mais de 5.000 clientes corporativos e um componente central de muitos aplicativos (veja casos de uso).

Este blogue demonstra como o Milvus funciona com a estrutura Merlin Recsys no momento da formação e da inferência. Mostramos como o Milvus complementa o Merlin na fase de recuperação de itens com uma pesquisa de incorporação de vetor top-k altamente eficiente e como pode ser utilizado com o Servidor de Inferência NVIDIA Triton (TIS) no momento da inferência (ver Figura 1). Os nossos resultados de referência mostram uma impressionante aceleração de 37x a 91x com o Milvus acelerado por GPU que utiliza o NVIDIA RAFT com as incorporações vectoriais geradas pelos Modelos Merlin. O código que usamos para mostrar a integração Merlin-Milvus e os resultados detalhados do benchmark, juntamente com a biblioteca que facilitou o nosso estudo de benchmark, estão disponíveis aqui.

Figura 1. Sistema de recomendação de múltiplos estágios com o framework Milvus contribuindo para o estágio de recuperação. Fonte da figura original de vários estágios: este post do blogue.

Os desafios que os sistemas de recomendação enfrentam

Dada a natureza multiestágio dos sistemas de recomendação e a disponibilidade de vários componentes e bibliotecas por eles integrados, um desafio significativo é a integração de todos os componentes num pipeline de ponta a ponta. O nosso objetivo é mostrar que a integração pode ser feita com menos esforço nos nossos cadernos de exemplo.

Outro desafio dos fluxos de trabalho de recomendação é a aceleração de certas partes do pipeline. Embora se saiba que desempenham um papel importante no treino de grandes redes neuronais, as GPU são apenas adições recentes às bases de dados vectoriais e à pesquisa de RNA. Com o aumento da dimensão dos inventários de produtos de comércio eletrónico ou das bases de dados de multimédia em fluxo contínuo e o número de utilizadores que utilizam estes serviços, as CPUs têm de fornecer o desempenho necessário para servir milhões de utilizadores em fluxos de trabalho Recsys eficientes. A aceleração de GPU noutras partes do pipeline tornou-se necessária para responder a este desafio. A solução deste blogue aborda este desafio, mostrando que a pesquisa ANN é eficiente quando se utilizam GPUs.

Pilhas de tecnologia para a solução

Vamos começar por rever alguns dos fundamentos necessários para realizar o nosso trabalho.

  • NVIDIA Merlin: uma biblioteca de código aberto com APIs de alto nível que aceleram os recomendadores nas GPUs NVIDIA.

  • NVTabular: para pré-processamento dos dados tabulares de entrada e engenharia de recursos.

  • Modelos Merlin: para treinar modelos de aprendizagem profunda e para aprender, neste caso, vectores de incorporação de utilizadores e itens a partir de dados de interação do utilizador.

  • Sistemas Merlin: para combinar um modelo de recomendação baseado em TensorFlow com outros elementos (por exemplo, armazenamento de recursos, pesquisa ANN com Milvus) a serem servidos com o TIS.

  • Triton Inference Server: para a fase de inferência em que é passado um vetor de caraterísticas do utilizador e são geradas recomendações de produtos.

  • Containerização: todos os itens acima estão disponíveis por meio de container(s) que a NVIDIA fornece no catálogo NGC. Utilizámos o contentor Merlin TensorFlow 23.06 disponível aqui.

  • Milvus 2.3: para realizar indexação e consulta de vetores acelerados por GPU.

  • Milvus 2.2.11: o mesmo que acima, mas para fazer isso na CPU.

  • Pymilvus SDK: para se conectar ao servidor Milvus, criar índices de banco de dados vetoriais e executar consultas por meio de uma interface Python.

  • Feast: para guardar e recuperar atributos de utilizadores e itens num feature store (de código aberto) como parte do nosso pipeline RecSys de ponta a ponta.

Várias bibliotecas e frameworks subjacentes também são usadas nos bastidores. Por exemplo, o Merlin depende de outras bibliotecas da NVIDIA, como cuDF e Dask, ambas disponíveis no RAPIDS cuDF. Da mesma forma, o Milvus baseia-se no NVIDIA RAFT para primitivas sobre aceleração de GPU e bibliotecas modificadas, como HNSW e FAISS, para pesquisa.

Compreender as bases de dados vectoriais e o Milvus

O vizinho mais próximo aproximado (ANN) é uma funcionalidade que as bases de dados relacionais não conseguem suportar. As bases de dados relacionais foram concebidas para tratar dados tabulares com estruturas predefinidas e valores diretamente comparáveis. Os índices das bases de dados relacionais baseiam-se nisto para comparar dados e criar estruturas que tiram partido do facto de se saber se cada valor é inferior ou superior ao outro. Os vectores de incorporação não podem ser diretamente comparados uns com os outros desta forma, uma vez que é necessário saber o que cada valor do vetor representa. Não se pode dizer se um vetor é necessariamente menor do que o outro. A única coisa que podemos fazer é calcular a distância entre os dois vectores. Se a distância entre dois vectores for pequena, podemos assumir que as caraterísticas que representam são semelhantes, e se for grande, podemos assumir que os dados que representam são mais diferentes. No entanto, estes índices eficientes têm um custo; o cálculo da distância entre dois vectores é computacionalmente dispendioso e os índices vectoriais não são facilmente adaptáveis e, por vezes, não são modificáveis. Devido a estas duas limitações, a integração destes índices é mais complexa nas bases de dados relacionais, razão pela qual são necessárias bases de dados vectoriais específicas.

O Milvus foi criado para resolver os problemas que as bases de dados relacionais enfrentam com os vectores e foi concebido desde o início para lidar com estes vectores de incorporação e os seus índices em grande escala. Para cumprir o distintivo nativo da nuvem, o Milvus separa a computação e o armazenamento e as diferentes tarefas de computação - consulta, tratamento de dados e indexação. Os utilizadores podem escalar cada parte da base de dados para lidar com outros casos de utilização, quer sejam de inserção de dados ou de pesquisa. Se houver um grande afluxo de pedidos de inserção, o utilizador pode dimensionar temporariamente os nós de índice horizontal e verticalmente para lidar com a ingestão. Da mesma forma, se não estiverem a ser ingeridos dados, mas houver muitas pesquisas, o utilizador pode reduzir os nós de índice e, em vez disso, aumentar os nós de consulta para obter mais rendimento. Este design do sistema (ver Figura 2) exigiu que pensássemos numa mentalidade de computação paralela, resultando num sistema optimizado para computação com muitas portas abertas para mais optimizações.

Figura 2. Projeto do sistema Milvus

O Milvus também utiliza muitas bibliotecas de indexação de última geração para dar aos utilizadores o máximo de personalização possível para o seu sistema. Melhora-as adicionando a capacidade de lidar com operações CRUD, dados em fluxo contínuo e filtragem. Mais adiante, discutiremos como esses índices diferem e quais são os prós e contras de cada um.

Solução de exemplo: integração do Milvus e do Merlin

A solução de exemplo que apresentamos aqui demonstra a integração do Milvus com o Merlin na fase de recuperação de itens (quando os k itens mais relevantes são recuperados através de uma pesquisa ANN). Utilizamos um conjunto de dados reais de um desafio RecSys, descrito abaixo. Treinamos um modelo de aprendizagem profunda Two-Tower que aprende as incorporações vectoriais para utilizadores e itens. Esta secção também fornece o plano do nosso trabalho de avaliação comparativa, incluindo as métricas que recolhemos e a gama de parâmetros que utilizamos.

A nossa abordagem envolve:

  • Ingestão e pré-processamento de dados

  • Treino do modelo de aprendizagem profunda Two-Tower

  • Construção do índice Milvus

  • Pesquisa de semelhanças Milvus

Descrevemos brevemente cada passo e remetemos o leitor para os nossos notebooks para mais pormenores.

Conjunto de dados

A YOOCHOOSE GmbH fornece o conjunto de dados que utilizamos nesta integração e estudo de referência para o desafio RecSys 2015 e está disponível no Kaggle. Contém eventos de clique/compra do utilizador de um retalhista europeu online com atributos como um ID de sessão, registo de data e hora, ID do item associado ao clique/compra e categoria do item, disponíveis no ficheiro yoochoose-clicks.dat. As sessões são independentes e não há indícios de utilizadores que regressam, pelo que tratamos cada sessão como pertencente a um utilizador distinto. O conjunto de dados tem 9.249.729 sessões únicas (utilizadores) e 52.739 itens únicos.

Ingestão e pré-processamento de dados

A ferramenta que utilizamos para o pré-processamento de dados é o NVTabular, um componente de engenharia de caraterísticas e pré-processamento do Merlin acelerado por GPU e altamente escalável. Utilizamos o NVTabular para ler os dados na memória da GPU, reorganizar as caraterísticas conforme necessário, exportar para ficheiros parquet e criar uma divisão de validação de treino para treino. Isto resulta em 7.305.761 utilizadores únicos e 49.008 itens únicos para treinar. Também categorizamos cada coluna e seus valores em valores inteiros. O conjunto de dados está agora pronto para ser treinado com o modelo Two-Tower.

Treinamento do modelo

Utilizamos o modelo de aprendizagem profunda Two-Tower para treinar e gerar embeddings de utilizadores e itens, posteriormente utilizados na indexação e consulta de vectores. Depois de treinar o modelo, podemos extrair as incorporações de utilizador e item aprendidas.

Os dois passos seguintes são opcionais: um modelo DLRM treinado para classificar os itens recuperados para recomendação e um armazenamento de caraterísticas utilizado (neste caso, Feast) para armazenar e recuperar caraterísticas de utilizadores e itens. Incluímo-las para completar o fluxo de trabalho em várias fases.

Por fim, exportamos os embeddings do utilizador e do item para ficheiros parquet, que podem mais tarde ser recarregados para criar um índice vetorial Milvus.

Construção e consulta do índice Milvus

O Milvus facilita a indexação de vectores e a pesquisa de semelhanças através de um "servidor" lançado na máquina de inferência. No nosso bloco de notas n.º 2, configuramo-lo através da instalação do servidor Milvus e do Pymilvus, iniciando depois o servidor com a sua porta de escuta predefinida. De seguida, demonstramos a construção de um índice simples (IVF_FLAT) e a consulta do mesmo utilizando as funções setup_milvus e query_milvus, respetivamente.

Testes de referência

Concebemos dois benchmarks para demonstrar a necessidade de utilizar uma biblioteca de indexação/pesquisa vetorial rápida e eficiente como o Milvus.

  1. Usando o Milvus para construir índices vectoriais com os dois conjuntos de embeddings que gerámos: 1) embeddings de utilizadores para 7,3 milhões de utilizadores únicos, divididos em 85% de conjunto de treino (para indexação) e 15% de conjunto de teste (para consulta), e 2) embeddings de itens para 49 mil produtos (com uma divisão de 50-50 entre treino e teste). Este teste de referência é feito independentemente para cada conjunto de dados vectoriais e os resultados são apresentados separadamente.

  2. Utilizando o Milvus para construir um índice de vectores para o conjunto de dados de 49K itens incorporados e consultando os 7,3 milhões de utilizadores únicos em relação a este índice para pesquisa de semelhanças.

Nesses benchmarks, usamos os algoritmos de indexação IVFPQ e HNSW executados em GPU e CPU, juntamente com várias combinações de parâmetros. Os detalhes estão disponíveis aqui.

O compromisso entre a qualidade da pesquisa e o rendimento é uma consideração importante de desempenho, especialmente num ambiente de produção. O Milvus permite um controlo total sobre os parâmetros de indexação para explorar esta relação para um determinado caso de utilização, de modo a obter melhores resultados de pesquisa com a verdade fundamental. Isto pode significar um aumento do custo computacional sob a forma de uma taxa de transferência reduzida ou de consultas por segundo (QPS). Medimos a qualidade da pesquisa ANN com uma métrica de recuperação e fornecemos curvas QPS-recall que demonstram o compromisso. Pode então decidir-se sobre um nível aceitável de qualidade de pesquisa, tendo em conta os recursos de computação ou os requisitos de latência/rendimento do caso de negócio.

Além disso, observe o tamanho do lote de consulta (nq) usado em nossos benchmarks. Isto é útil em fluxos de trabalho em que são enviados vários pedidos simultâneos para inferência (por exemplo, recomendações offline solicitadas e enviadas para uma lista de destinatários de correio eletrónico ou recomendações online criadas por agrupamento de pedidos simultâneos que chegam e são processados de uma só vez). Dependendo do caso de utilização, o TIS também pode ajudar a processar estes pedidos em lotes.

Resultados

Relatamos agora os resultados para os três conjuntos de benchmarks em CPU e GPU, usando os tipos de índice HNSW (somente CPU) e IVF_PQ (CPU e GPU) implementados pelo Milvus.

Com este conjunto de dados mais pequeno, cada execução para uma determinada combinação de parâmetros utiliza 50% dos vectores de itens como vectores de consulta e consulta os 100 principais vectores semelhantes dos restantes. O HNSW e o IVF_PQ produzem uma elevada recuperação com as definições de parâmetros testadas, no intervalo 0,958-1,0 e 0,665-0,997, respetivamente. Este resultado sugere que o HNSW tem um melhor desempenho no que diz respeito à recuperação, mas o IVF_PQ com definições de nlist pequenas produz uma recuperação muito comparável. Também devemos notar que os valores de recuperação podem variar muito, dependendo dos parâmetros de indexação e consulta. Os valores que reportamos foram obtidos após uma experimentação preliminar com intervalos de parâmetros gerais e uma análise mais aprofundada de um subconjunto selecionado.

O tempo total para executar todas as consultas na CPU com HNSW para uma determinada combinação de parâmetros varia entre 5,22 e 5,33 s (mais rápido à medida que m aumenta, relativamente inalterado com ef) e com IVF_PQ entre 13,67 e 14,67 s (mais lento à medida que nlist e nprobe aumentam). A aceleração da GPU tem de facto um efeito notável, como se pode ver na Figura 3.

A Figura 3 mostra a troca entre a recuperação e a taxa de transferência em todas as execuções concluídas na CPU e na GPU com este pequeno conjunto de dados usando IVF_PQ. Verificamos que a GPU fornece um aumento de velocidade de 4x a 15x em todas as combinações de parâmetros testadas (maior aumento de velocidade à medida que o nprobe aumenta). Isto é calculado tomando o rácio de QPS de GPU sobre QPS de execuções de CPU para cada combinação de parâmetros. De um modo geral, este conjunto apresenta um pequeno desafio para a CPU ou GPU e mostra perspectivas de aumento de velocidade com os conjuntos de dados maiores, conforme discutido abaixo.

Figura 3. Aumento de velocidade da GPU com o algoritmo Milvus IVF_PQ em execução na GPU NVIDIA A100 (pesquisa de similaridade item-item)

Com o segundo conjunto de dados muito maior (7,3 milhões de utilizadores), reservámos 85% (~6,2 milhões) dos vectores como "treino" (o conjunto de vectores a indexar) e os restantes 15% (~1,1 milhões) como "teste" ou conjunto de vectores de consulta. O HNSW e o IVF_PQ têm um desempenho excecional neste caso, com valores de recuperação de 0,884-1,0 e 0,922-0,999, respetivamente. No entanto, são computacionalmente muito mais exigentes, especialmente com IVF_PQ na CPU. O tempo total para executar todas as consultas na CPU com o HNSW varia entre 279,89 e 295,56 s e com o IVF_PQ entre 3082,67 e 10932,33 s. Note-se que estes tempos de consulta são cumulativos para 1,1 milhões de vectores consultados, pelo que se pode dizer que uma única consulta ao índice continua a ser muito rápida.

No entanto, a consulta baseada em CPU pode não ser viável se o servidor de inferência esperar muitos milhares de solicitações simultâneas para executar consultas em um inventário de milhões de itens.

A GPU A100 oferece uma velocidade incrível de 37x a 91x (média de 76,1x) em todas as combinações de parâmetros com IVF_PQ em termos de taxa de transferência (QPS), mostrada na Figura 4. Isto é consistente com o que observámos com o pequeno conjunto de dados, o que sugere que o desempenho da GPU é razoavelmente bem dimensionado utilizando o Milvus com milhões de vectores de incorporação.

Figura 4. Aumento da velocidade da GPU com o algoritmo Milvus IVF_PQ em execução na GPU NVIDIA A100 (pesquisa de semelhança utilizador-utilizador)

A Figura 5 detalhada a seguir mostra a troca de QPS de recuperação para todas as combinações de parâmetros testadas em CPU e GPU com IVF_PQ. Cada conjunto de pontos (superior para GPU, inferior para CPU) neste gráfico representa a troca enfrentada ao alterar os parâmetros de indexação/consulta de vectores para obter uma maior recuperação à custa de um menor rendimento. Note-se a perda considerável de QPS no caso da GPU quando se tenta atingir níveis de recuperação mais elevados.

Figura 5. Troca entre taxa de recuperação e taxa de transferência para todas as combinações de parâmetros testadas em CPU e GPU com IVF_PQ (utilizadores vs. utilizadores)

Finalmente, consideramos outro caso de utilização realista em que os vectores de utilizadores são consultados em relação a vectores de itens (como demonstrado no Notebook 01 acima). Neste caso, 49 mil vectores de itens são indexados e 7,3 milhões de vectores de utilizadores são consultados para obter os 100 itens mais semelhantes.

É aqui que as coisas ficam interessantes, pois a consulta de 7,3 milhões em lotes de 1.000 em um índice de 49 mil itens parece consumir muito tempo na CPU, tanto para o HNSW quanto para o IVF_PQ. A GPU parece lidar melhor com este caso (ver Figura 6). Os níveis de precisão mais elevados do IVF_PQ na CPU quando nlist = 100 são calculados em cerca de 86 minutos, em média, mas variam significativamente à medida que o valor de nprobe aumenta (51 min. quando nprobe = 5 vs. 128 min. quando nprobe = 20). A GPU NVIDIA A100 acelera consideravelmente o desempenho por um fator de 4x a 17x (acelerações mais elevadas à medida que nprobe aumenta). Recorde-se que o algoritmo IVF_PQ, através da sua técnica de quantização, também reduz o espaço de memória e fornece uma solução de pesquisa ANN computacionalmente viável combinada com a aceleração da GPU.

Figura 6. Aceleração da GPU com o algoritmo Milvus IVF_PQ em execução na GPU NVIDIA A100 (pesquisa de semelhança entre itens de utilizador)

Semelhante à Figura 5, o compromisso entre recuperação e taxa de transferência é mostrado na Figura 7 para todas as combinações de parâmetros testadas com IVF_PQ. Aqui, ainda é possível ver como pode ser necessário abrir mão de alguma precisão na pesquisa ANN em favor do aumento da taxa de transferência, embora as diferenças sejam muito menos perceptíveis, especialmente no caso de execuções de GPU. Isto sugere que se pode esperar níveis relativamente elevados e consistentes de desempenho computacional com a GPU, ao mesmo tempo que se obtém uma elevada recuperação.

Figura 7. Troca entre a recuperação e a taxa de transferência para todas as combinações de parâmetros testadas na CPU e na GPU com IVF_PQ (utilizadores vs. itens)

Conclusão

Teremos todo o gosto em partilhar algumas observações finais se chegou até aqui. Queremos lembrar que a complexidade e a natureza de várias etapas do Recsys moderno exigem desempenho e eficiência em cada etapa. Esperamos que este blogue lhe tenha dado razões convincentes para considerar a utilização de duas funcionalidades críticas nos seus pipelines RecSys:

  • A biblioteca Merlin Systems da NVIDIA Merlin permite-lhe ligar facilmente o Milvus, um eficiente motor de pesquisa de vectores acelerado por GPU.

  • Utilize a GPU para acelerar os cálculos para a indexação de bases de dados vectoriais e a pesquisa ANN com tecnologia como o RAPIDS RAFT.

Estes resultados sugerem que a integração Merlin-Milvus apresentada tem um elevado desempenho e é muito menos complexa do que outras opções para formação e inferência. Além disso, ambas as estruturas estão a ser ativamente desenvolvidas e muitas das novas funcionalidades (por exemplo, novos índices de bases de dados vectoriais acelerados por GPU por Milvus) são adicionadas em cada versão. O facto de a pesquisa de semelhanças vectoriais ser um componente crucial em vários fluxos de trabalho, como a visão computacional, a modelação de grandes linguagens e os sistemas de recomendação, faz com que este esforço valha ainda mais a pena.

Para terminar, gostaríamos de agradecer a todos os membros das equipas Zilliz/Milvus e Merlin e RAFT que contribuíram para o esforço de produção deste trabalho e da publicação no blogue. Aguardamos o seu contacto, caso tenha oportunidade de implementar o Merlin e o Milvus nos seus recsys ou noutros fluxos de trabalho.

Like the article? Spread the word

Continue Lendo