Uma breve introdução à busca vetorial

Este artigo é o primeiro de uma série de três que irá explorar as complexidades da busca vetorial, também conhecida como busca semântica, e como ela é implementada no Elasticsearch.

Da busca vetorial às poderosas REST APIs, o Elasticsearch oferece aos desenvolvedores o kit de ferramentas de busca mais abrangente. Mergulhe em notebooks de exemplo no GitHub para experimentar algo novo. Você também pode iniciar seu teste gratuito ou executar o Elasticsearch localmente hoje mesmo.

Este artigo é o primeiro de uma série de três que irá explorar as complexidades da busca vetorial, também conhecida como busca semântica, e como ela é implementada no Elasticsearch.

Esta primeira parte tem como objetivo fornecer uma introdução geral aos conceitos básicos de incorporação de vetores e como a busca vetorial funciona internamente.

Munido de todo o conhecimento adquirido no primeiro artigo, a segunda parte irá guiá-lo pelos meandros de como configurar a pesquisa vetorial no Elasticsearch.

Na terceira parte, aproveitaremos o que aprendemos nas duas primeiras partes, expandiremos esse conhecimento e exploraremos como criar consultas de pesquisa híbridas poderosas no Elasticsearch.

Antes de abordarmos o tema principal deste artigo, vamos voltar no tempo e revisar um pouco da história dos vetores, um conceito fundamental na busca semântica.

Vetores não são novidade

Tenho quase certeza de que todos concordariam que, desde o surgimento do ChatGPT em novembro de 2022, não passa um único dia sem que se ouça ou leia sobre "busca vetorial". Está por toda parte e é tão difundida que muitas vezes temos a impressão de que se trata de uma tecnologia de ponta recém-lançada, quando na verdade ela já existe há mais de seis décadas! A pesquisa sobre o assunto começou em meados da década de 1960, e os primeiros artigos científicos foram publicados em 1978 por Gerard Salton, um especialista em recuperação de informação, e seus colegas da Universidade Cornell. O trabalho de Salton sobre modelos vetoriais densos e esparsos constitui a base da tecnologia moderna de busca vetorial.

Nos últimos 20 anos, muitos SGBDs vetoriais diferentes, baseados em sua pesquisa, foram criados e lançados no mercado. Isso inclui o Elasticsearch, baseado no projeto Apache Lucene, que começou a trabalhar em busca vetorial em 2019.

Os vetores estão por toda parte e são tão difundidos que é importante primeiro compreender bem a teoria subjacente e o funcionamento interno deles antes de começar a usá-los. Antes de nos aprofundarmos nisso, vamos revisar rapidamente as diferenças entre busca lexical e busca vetorial para que possamos entender melhor como elas diferem e como podem se complementar.

Uma maneira fácil de introduzir a busca vetorial é compará-la à busca lexical mais convencional com a qual você provavelmente já está familiarizado. A busca vetorial, também conhecida como busca semântica, e a busca lexical funcionam de maneiras muito diferentes. A busca lexical é o tipo de busca que todos nós usamos há anos no Elasticsearch. Resumindo brevemente, o algoritmo não tenta compreender o significado real do que é indexado e consultado. Em vez disso, ele se esforça para encontrar correspondências lexicais entre os literais das palavras ou suas variantes (como lematização, sinônimos etc.) digitadas pelo usuário em uma consulta e todos os literais previamente indexados no banco de dados, utilizando algoritmos de similaridade como TF-IDF.

Como podemos ver, os três documentos no canto superior esquerdo foram tokenizados e analisados. Em seguida, os termos resultantes são indexados em um índice invertido, que simplesmente mapeia os termos analisados aos IDs dos documentos que os contêm. Note que todos os termos aparecem apenas uma vez e nenhum deles é repetido em qualquer outro documento. A busca por “professor alemão legal” retornará os três documentos com pontuações variadas, embora nenhum deles realmente capture o verdadeiro significado da consulta.

Como pode ser visto na Figura 2, abaixo, a situação fica ainda mais complicada quando se trata de polissemia ou homógrafos, ou seja, palavras que são escritas da mesma forma, mas têm significados diferentes (right, palm, bat, mean, etc.). Vamos pegar a palavra "right", que pode ter três significados diferentes, e ver o que acontece.

A busca por “I'm not right” retorna um documento que tem o significado exatamente oposto ao do primeiro resultado encontrado. Se você pesquisar exatamente os mesmos termos, mas ordená-los de forma diferente para produzir um significado diferente, por exemplo, "virar à direita" e "virar à direita", o resultado será exatamente o mesmo (ou seja, o terceiro documento "Vire à direita"). É verdade que nossas consultas são excessivamente simplificadas e não utilizam recursos mais avançados, como a correspondência de frases, mas isso ajuda a ilustrar que a busca lexical não compreende o verdadeiro significado por trás do que é indexado e do que é pesquisado. Se isso não estiver claro, não se preocupe, voltaremos a este exemplo no terceiro artigo para ver como a busca vetorial pode ajudar neste caso.

Para fazer justiça à busca lexical, quando você tem controle sobre como indexa seus dados estruturados (pense em mapeamentos, análise de texto, pipelines de ingestão, etc.) e como elabora suas consultas (pense em consultas DSL bem elaboradas, análise de termos de consulta, etc.), você pode fazer maravilhas com mecanismos de busca lexical, não há dúvida! O histórico do Elasticsearch em relação às suas capacidades de busca lexical é simplesmente incrível. O que conseguiu alcançar e o quanto popularizou e aprimorou o campo da busca lexical nos últimos anos é verdadeiramente notável.

No entanto, quando se trata de fornecer suporte para consultas a dados não estruturados (como imagens, vídeos, áudios, texto bruto, etc.) para usuários que precisam fazer perguntas em texto livre, a busca lexical deixa a desejar. Além disso, às vezes a consulta nem sequer é um texto, pode ser uma imagem, como veremos em breve. A principal razão pela qual a busca lexical é inadequada em tais situações é que os dados não estruturados não podem ser indexados nem consultados da mesma forma que os dados estruturados. Ao lidar com dados não estruturados, a semântica entra em jogo. O que significa semântica? Muito simplesmente, o significado!

Vamos pegar o exemplo simples de um mecanismo de busca de imagens (por exemplo, a Busca de Imagens do Google ou o Lens). Você arrasta e solta uma imagem, e o mecanismo de busca semântica do Google encontrará e retornará as imagens mais semelhantes àquela que você pesquisou. Na Figura 3, abaixo, podemos ver à esquerda a imagem de um pastor alemão e à direita todas as imagens semelhantes que foram recuperadas, sendo o primeiro resultado a mesma imagem que a fornecida (ou seja, a mais semelhante).

Mesmo que isso pareça simples e lógico para nós, humanos, para os computadores é uma história completamente diferente. É isso que a busca vetorial possibilita e ajuda a alcançar. O poder desbloqueado pela busca vetorial é imenso, como o mundo testemunhou recentemente. Vamos agora levantar o capô e descobrir o que se esconde por baixo.

Incorporação de vetores

Como vimos anteriormente, com mecanismos de busca lexical, dados estruturados como texto podem ser facilmente tokenizados em termos que podem ser correspondidos no momento da busca, independentemente do significado real dos termos. Os dados não estruturados, no entanto, podem assumir diferentes formas, como grandes objetos binários (imagens, vídeos, áudios, etc.), e não são adequados para o mesmo processo de tokenização. Além disso, o objetivo principal da busca semântica é indexar os dados de forma que possam ser pesquisados com base no significado que representam. Como podemos alcançar isso? A resposta está em duas palavras: Aprendizado de Máquina! Ou, mais precisamente, Aprendizado Profundo!

Aprendizado profundo é uma área específica do aprendizado de máquina que se baseia em modelos de redes neurais artificiais compostas por múltiplas camadas de processamento, capazes de extrair progressivamente o verdadeiro significado dos dados. O funcionamento desses modelos de redes neurais é fortemente inspirado no cérebro humano. A Figura 4, abaixo, mostra a aparência de uma rede neural, com suas camadas de entrada e saída, bem como múltiplas camadas ocultas:

A verdadeira façanha das redes neurais é a capacidade de transformar um único dado não estruturado em uma sequência de valores de ponto flutuante, conhecidos como vetores de incorporação ou simplesmente incorporações. Como seres humanos, conseguimos entender muito bem o que são vetores, desde que os visualizemos em um espaço bidimensional ou tridimensional. Cada componente do vetor representa uma coordenada em um plano xy bidimensional ou em um espaço xyz tridimensional.

No entanto, os vetores de incorporação nos quais os modelos de redes neurais funcionam podem ter centenas ou até milhares de dimensões e simplesmente representar um ponto em um espaço multidimensional. Cada dimensão vetorial representa uma característica ou um atributo dos dados não estruturados. Vamos ilustrar isso com um modelo de aprendizado profundo que transforma imagens em vetores de incorporação de 2048 dimensões. Esse modelo transformaria a imagem do pastor alemão que usamos na Figura 3 no vetor de incorporação mostrado na tabela abaixo. Note que mostramos apenas os três primeiros e os três últimos elementos, mas haveria mais 2.042 colunas/dimensões na tabela.

é vermelhoé_cachorrocéu azulsem_gramapastor_alemãoé_árvore
Pastor alemão incorporações0,01210,95720,87350,11980,97120,0512

Cada coluna representa uma dimensão do modelo e corresponde a uma característica que a rede neural subjacente procura modelar. Cada entrada fornecida ao modelo será caracterizada dependendo de quão semelhante essa entrada é a cada uma das 2048 dimensões. Assim, o valor de cada elemento no vetor de incorporação denota a similaridade dessa entrada a uma dimensão específica. Neste exemplo, podemos ver que o modelo detectou uma alta similaridade entre cães e pastores alemães, bem como a presença de céu azul.

Ao contrário da busca lexical, onde um termo pode ser correspondido ou não, com a busca vetorial podemos ter uma noção muito melhor de quão semelhante um conjunto de dados não estruturados é a cada uma das dimensões suportadas pelo modelo. Dessa forma, os vetores de incorporação servem como uma representação semântica fantástica de dados não estruturados.

O molho secreto

Agora que sabemos como os dados não estruturados são segmentados e analisados por redes neurais de aprendizado profundo em vetores de incorporação que capturam a similaridade dos dados ao longo de um grande número de dimensões, precisamos entender como funciona a correspondência desses vetores. Acontece que a resposta é bem simples. Os vetores de incorporação que estão próximos uns dos outros representam dados semanticamente semelhantes . Assim, quando consultamos um banco de dados vetorial, a entrada da pesquisa (imagem, texto, etc.) é primeiro transformada em um vetor de incorporação usando o mesmo modelo que foi usado para indexar todos os dados não estruturados, e o objetivo final é encontrar os vetores vizinhos mais próximos desse vetor de consulta. Portanto, tudo o que precisamos fazer é descobrir como medir a "distância" ou "similaridade" entre o vetor de consulta e todos os vetores existentes indexados no banco de dados; é basicamente isso.

Distância e semelhança

Felizmente para nós, medir a distância entre dois vetores é um problema fácil de resolver graças à aritmética vetorial. Vamos então analisar as funções de distância e similaridade mais populares que são suportadas por bancos de dados de busca vetorial modernos, como o Elasticsearch. Atenção, contém matemática!

Distância L1

A distância L1, também chamada de distância de Manhattan, entre dois vetores x e y é medida somando-se a diferença absoluta entre todos os seus elementos. Obviamente, quanto menor a distância d, mais próximos estarão os dois vetores. A fórmula é bastante simples, como pode ser visto abaixo:

Visualmente, a distância L1 pode ser ilustrada como mostrado na Figura 5, abaixo:

Vamos pegar dois vetores x e y, tais como x = (1, 2) e y = (4, 3), então a distância L1 de ambos os vetores seria | 1 - 4 | + | 2 - 3 | = 4.

Distância L2

A distância L2, também chamada de distância euclidiana, entre dois vetores x e y é medida somando-se primeiro o quadrado da diferença entre todos os seus elementos e, em seguida, extraindo-se a raiz quadrada do resultado. É basicamente o caminho mais curto entre dois pontos (também chamado de hipotenusa). De forma semelhante a L1, quanto menor a distância d, mais próximos estão os dois vetores:

A distância L2 é mostrada na Figura 6 abaixo:

Vamos reutilizar os mesmos dois vetores de amostra x e y que usamos para a distância L1, e agora podemos calcular a distância L2 como (14)2+(23)2=10(1 - 4)^2 + (2 - 3)^2 = 10. A raiz quadrada de 10 resulta em 3,16.

Distância Linf

A distância Linf (para L infinito), também chamada de distância de Chebyshev ou distância do tabuleiro de xadrez, entre dois vetores x e y é definida simplesmente como a maior distância entre quaisquer dois de seus elementos ou a maior distância medida ao longo de um dos eixos/dimensões. A fórmula é muito simples e está ilustrada abaixo:

A representação da distância Linf é mostrada na Figura 7 abaixo:

Novamente, tomando os mesmos dois vetores de amostra x e y, podemos calcular a distância infinita L como max ( | 1 - 4 | , | 2 - 3 | ) = max (3, 1) = 3.

Semelhança de cosseno

Ao contrário de L1, L2 e Linf, a similaridade de cosseno não mede a distância entre dois vetores x e y, mas sim o ângulo relativo entre eles, ou seja, se ambos apontam aproximadamente na mesma direção. Quanto maior a similaridade s, mais "próximos" estão os dois vetores. A fórmula é novamente muito simples e está apresentada abaixo:

Uma forma de representar a similaridade de cosseno entre dois vetores é mostrada na Figura 8 abaixo:

Além disso, como os valores do cosseno estão sempre no intervalo [-1, 1], -1 significa similaridade oposta (ou seja, um ângulo de 180° entre os dois vetores), 0 significa similaridade não relacionada (ou seja, um ângulo de 90°) e 1 significa idêntico (ou seja, um ângulo de 0°), conforme mostrado na Figura 9 abaixo:


Mais uma vez, vamos reutilizar os mesmos vetores de amostra x e y e calcular a similaridade de cosseno usando a fórmula acima. Primeiro, podemos calcular o produto escalar de ambos os vetores como (14)+(23)=10(1 · 4) + (2 · 3) = 10. Então, multiplicamos o comprimento (também chamado de magnitude) de ambos os vetores: (12+22)1/2+(42+32)1/2=11,18034.(1^2 + 2^2)^{1/2}+ (4^2 + 3^2)^{1/2} = 11,18034. Finalmente, dividimos o produto escalar pelo comprimento multiplicado 10 / 11,18034 = 0,894427 (ou seja, um ângulo de 26°), que é bastante próximo de 1, então ambos os vetores podem ser considerados bastante semelhantes.

similaridade do produto escalar

Uma desvantagem da similaridade de cosseno é que ela leva em consideração apenas o ângulo entre dois vetores, mas não sua magnitude (ou seja, comprimento), o que significa que, se dois vetores apontam aproximadamente na mesma direção, mas um é muito mais longo que o outro, ambos ainda serão considerados semelhantes. A similaridade por produto escalar, também chamada de produto interno, aprimora isso ao levar em consideração tanto o ângulo quanto a magnitude dos vetores, o que proporciona uma métrica de similaridade muito mais precisa.

Duas fórmulas equivalentes são usadas para calcular a similaridade do produto escalar. A primeira é a mesma que vimos anteriormente no numerador da semelhança de cosseno:

A segunda fórmula simplesmente multiplica o comprimento de ambos os vetores pelo cosseno do ângulo entre eles:

A similaridade do produto escalar é visualizada na Figura 10, abaixo:

Mais uma vez, pegamos os vetores de amostra x e y e calculamos sua similaridade de produto escalar usando a primeira fórmula, como fizemos para a similaridade de cosseno anteriormente, como (1 · 4) + (2 · 3) = 10.

Usando a segunda fórmula, multiplicamos o comprimento de ambos os vetores: (12+22)1/2+(42+32)1/2=11,18034(1^2 + 2^2)^{1/2}+ (4^2 + 3^2)^{1/2} = 11,18034 e multiplicamos isso pelo cosseno do ângulo de 26° entre ambos os vetores, e obtemos 11,18034 · cos(26°) = 10.

Vale ressaltar que, se todos os vetores forem normalizados primeiro (ou seja, seu comprimento for 1), a similaridade do produto escalar se torna exatamente a mesma que a similaridade do cosseno (porque |x| |y| = 1), ou seja, o cosseno do ângulo entre os dois vetores. Como veremos mais adiante, a normalização de vetores é uma boa prática a ser adotada para tornar a magnitude do vetor irrelevante, de modo que a similaridade se concentre simplesmente no ângulo. Isso também acelera o cálculo da distância no momento da indexação e da consulta, o que pode ser um grande problema ao operar com bilhões de vetores.

Resumo rápido

Uau, já vimos MUITA informação até agora, então vamos parar um minuto e fazer um breve resumo do que temos a dizer. Aprendemos que…

  • …a busca semântica é baseada em modelos de redes neurais de aprendizado profundo que se destacam na transformação de dados não estruturados em vetores de incorporação multidimensionais.
  • …cada dimensão do modelo representa uma característica ou propriedade dos dados não estruturados.
  • …um vetor de incorporação é uma sequência de valores de similaridade (um para cada dimensão) que representam o quão semelhante a cada dimensão um determinado conjunto de dados não estruturados é.
  • …quanto mais “próximos” dois vetores estiverem (ou seja, quanto mais próximos forem os vizinhos), mais eles representarão conceitos semanticamente semelhantes.
  • …as funções de distância (L1, L2, Linf) permitem medir a proximidade entre dois vetores.
  • …as funções de similaridade (cosseno e produto escalar) permitem medir o quanto dois vetores estão apontando na mesma direção.

Agora, a última peça que precisamos analisar é o próprio mecanismo de busca vetorial. Quando uma consulta é recebida, ela é primeiro vetorizada e, em seguida, o mecanismo de busca vetorial encontra os vetores vizinhos mais próximos desse vetor de consulta. A abordagem de força bruta, que consiste em medir a distância ou similaridade entre o vetor de consulta e todos os vetores no banco de dados, pode funcionar para conjuntos de dados pequenos, mas rapidamente se torna insuficiente à medida que o número de vetores aumenta. Em outras palavras, como podemos indexar milhões, bilhões ou até trilhões de vetores e encontrar os vizinhos mais próximos do vetor de consulta em um tempo razoável? É aí que precisamos usar a inteligência e descobrir maneiras ideais de indexar vetores para que possamos localizar os vizinhos mais próximos o mais rápido possível, sem comprometer muito a precisão.

Algoritmos e técnicas de busca vetorial

Ao longo dos anos, muitas equipes de pesquisa diferentes investiram muito esforço no desenvolvimento de algoritmos de busca vetorial muito inteligentes. Aqui, vamos apresentar brevemente os principais. Dependendo do caso de uso, alguns são mais adequados do que outros.

Já mencionamos brevemente a busca linear, ou indexação plana, quando citamos a abordagem de força bruta de comparar o vetor de consulta com todos os vetores presentes no banco de dados. Embora possa funcionar bem em conjuntos de dados pequenos, o desempenho diminui rapidamente à medida que o número de vetores e dimensões aumenta (complexidade O(n)).

Felizmente, existem abordagens mais eficientes chamadas de vizinho mais próximo aproximado (ANN, na sigla em inglês), onde as distâncias entre os vetores de incorporação são pré-computadas e vetores semelhantes são armazenados e organizados de forma a mantê-los próximos uns dos outros, por exemplo, usando clusters, árvores, hashes ou grafos. Essas abordagens são chamadas de "aproximadas" porque geralmente não garantem 100% de precisão. O objetivo final é reduzir o escopo da busca o máximo e o mais rápido possível, a fim de focar apenas nas áreas com maior probabilidade de conter vetores semelhantes, ou reduzir a dimensionalidade dos vetores.

Árvores K-dimensionais

Uma árvore K-dimensional, ou árvore KD, é uma generalização de uma árvore de busca binária que armazena pontos em um espaço k-dimensional e funciona dividindo continuamente o espaço de busca em árvores menores à esquerda e à direita, onde os vetores são indexados. No momento da busca, o algoritmo simplesmente precisa visitar alguns ramos da árvore ao redor do vetor de consulta (o ponto vermelho na Figura 11) para encontrar o vizinho mais próximo (o ponto verde na Figura 11). Se forem solicitados mais de k vizinhos, a área amarela será expandida até que o algoritmo encontre mais vizinhos.

A maior vantagem do algoritmo da árvore KD é que ele nos permite focar rapidamente apenas em alguns ramos localizados da árvore, eliminando assim a maioria dos vetores da análise. No entanto, a eficiência desse algoritmo diminui à medida que o número de dimensões aumenta, pois é necessário visitar muito mais ramos do que em espaços de dimensões inferiores.

Índice de arquivo invertido

A abordagem de índice de arquivo invertido (IVF) também é um algoritmo de particionamento espacial que atribui vetores próximos uns dos outros ao seu centroide comum. No espaço bidimensional, isso é melhor visualizado com um diagrama de Voronoi, como mostrado na Figura 12:

Podemos ver que o espaço 2D acima está dividido em 20 clusters, cada um com seu centroide representado por pontos pretos. Todos os vetores de incorporação no espaço são atribuídos ao cluster cujo centroide está mais próximo deles. No momento da busca, o algoritmo primeiro determina o cluster no qual se concentrar, encontrando o centroide mais próximo do vetor de consulta. Em seguida, ele pode simplesmente focar nessa área e nas áreas vizinhas, se necessário, para encontrar os vizinhos mais próximos.

Este algoritmo sofre do mesmo problema que as árvores KD quando usado em espaços de alta dimensionalidade. Isso é chamado de maldição da dimensionalidade e ocorre quando o volume do espaço aumenta tanto que todos os dados parecem esparsos e a quantidade de dados necessária para obter resultados mais precisos cresce exponencialmente. Quando os dados são esparsos, torna-se mais difícil para esses algoritmos de particionamento espacial organizarem os dados em clusters. Felizmente para nós, existem outros algoritmos e técnicas que atenuam esse problema, conforme detalhado abaixo.

quantização

A quantização é uma abordagem baseada em compressãoque nos permite reduzir o tamanho total do banco de dados, diminuindo a precisão dos vetores de incorporação. Isso pode ser alcançado usando quantização escalar (SQ) , convertendo os valores vetoriais de ponto flutuante em valores inteiros. Isso não apenas reduz o tamanho do banco de dados em um fator de 8, mas também diminui o consumo de memória e acelera o cálculo da distância entre vetores no momento da busca.

Outra técnica é chamada de quantização de produto (PQ), que primeiro divide o espaço em subespaços de dimensão inferior e, em seguida, os vetores que estão próximos uns dos outros são agrupados em cada subespaço usando um algoritmo de agrupamento (semelhante ao k-means).

Note que a quantização é diferente da redução de dimensionalidade, onde o número de dimensões é reduzido, ou seja, os vetores simplesmente se tornam mais curtos.

Mundos Pequenos Navegáveis Hierárquicos (HNSW)

Se o nome parece complexo, não se preocupe, na verdade não é! Em resumo, o Hierarchical Navigable Small Worlds é um algoritmo baseado em grafos multicamadas muito popular e eficiente. É utilizado por diversos bancos de dados vetoriais, incluindo o Apache Lucene. Uma representação conceitual do HNSW pode ser vista na Figura 13, abaixo.

Na camada superior, podemos ver um gráfico com muito poucos vetores que possuem as ligações mais longas entre si, ou seja, um gráfico de vetores conectados com a menor similaridade. Quanto mais nos aprofundamos nas camadas mais baixas, mais vetores encontramos e mais denso o grafo se torna, com cada vez mais vetores próximos uns dos outros. Na camada mais baixa, podemos encontrar todos os vetores, sendo que os mais semelhantes estão localizados mais próximos uns dos outros.

No momento da busca, o algoritmo começa na camada superior, em um ponto de entrada arbitrário, e encontra o vetor mais próximo do vetor de consulta (indicado pelo ponto cinza). Em seguida, o algoritmo desce uma camada e repete o mesmo processo, partindo do mesmo vetor que deixou na camada anterior, e assim por diante, camada após camada, até atingir a camada mais baixa e encontrar o vizinho mais próximo do vetor de consulta.

Hashing sensível à localidade (LSH)

Da mesma forma que todas as outras abordagens apresentadas até agora, o hashing sensível à localidade busca reduzir drasticamente o espaço de busca para aumentar a velocidade de recuperação. Com essa técnica, os vetores de incorporação são transformados em valores de hash, preservando as informações de similaridade, de modo que o espaço de busca se torna, em última análise, uma tabela hash simples que pode ser consultada em vez de um grafo ou árvore que precisa ser percorrido. A principal vantagem dos métodos baseados em hash é que vetores contendo um número arbitrário (grande) de dimensões podem ser mapeados para hashes de tamanho fixo, o que acelera enormemente o tempo de recuperação sem sacrificar muita precisão.

Existem muitas maneiras diferentes de realizar o hash de dados em geral e de incorporar vetores em particular, mas este artigo não se aprofundará nos detalhes de cada uma delas. Os métodos convencionais de hashing geralmente produzem hashes muito diferentes para dados que parecem muito semelhantes. Como os vetores de incorporação são compostos de valores de ponto flutuante, vamos pegar dois valores de ponto flutuante de exemplo que são considerados muito próximos um do outro na aritmética vetorial (por exemplo, 0,73 e 0,74) e executá-los através de algumas funções de hash comuns. Analisando os resultados abaixo, fica bastante óbvio que as funções de hash comuns não preservam a similaridade entre as entradas.

Função de hash0,730,74
MD51342129d04cd2924dd06cead4cf0a3ca0aec1b15371bd979cfa66b0a50ebecc5
SHA149d2c3e0e44bff838e1db571a121be5ea874e8d9a534e76482ade9d9fe4bff3035a7f31f2f363d77
SHA25699d03fc3771fe6848d675339fc49eeb1cb8d99a12e6358173336b99a2ec530ea5ecbc825ba5c16856edfdaf0abc5c6c41d0d8a9c508e34188239521dc7645663

Enquanto os métodos de hashing convencionais tentam minimizar as colisões de hashing entre dados semelhantes, o principal objetivo do hashing sensível à localidade é fazer exatamente o oposto, ou seja, maximizar as colisões de hashing para que dados semelhantes caiam no mesmo bucket com alta probabilidade. Dessa forma, vetores de incorporação que estejam próximos uns dos outros em um espaço multidimensional serão agrupados em um valor de tamanho fixo, pertencendo ao mesmo grupo. Como o LSH permite que esses vetores hash mantenham sua proximidade, essa técnica é muito útil para agrupamento de dados e buscas por vizinhos mais próximos.

Todo o trabalho pesado ocorre no momento da indexação, quando os hashes precisam ser calculados, enquanto no momento da busca precisamos apenas aplicar o hash ao vetor de consulta para localizar o bucket que contém os vetores de incorporação mais próximos. Uma vez encontrado o bucket candidato, geralmente ocorre uma segunda rodada para identificar os vetores vizinhos mais próximos do vetor de consulta.

Vamos concluir

Para introduzir a busca vetorial, tivemos que abordar bastante conteúdo neste artigo. Após comparar as diferenças entre a busca lexical e a busca vetorial, aprendemos como os modelos de redes neurais de aprendizado profundo conseguem capturar a semântica de dados não estruturados e transcodificar seu significado em vetores de incorporação de alta dimensão, uma sequência de números de ponto flutuante que representa a similaridade dos dados ao longo de cada uma das dimensões do modelo. Vale ressaltar também que a busca vetorial e a busca lexical não são técnicas de recuperação de informação concorrentes, mas sim complementares (como veremos na terceira parte desta série, quando nos aprofundaremos na busca híbrida).

Em seguida, introduzimos um elemento fundamental da busca vetorial, ou seja, as funções de distância (e similaridade) que nos permitem medir a proximidade de dois vetores e avaliar a similaridade dos conceitos que eles representam.

Por fim, analisamos diferentes variações dos algoritmos e técnicas de busca vetorial mais populares, que podem ser baseados em árvores, grafos, clusters ou hashes, cujo objetivo é restringir rapidamente a uma área específica do espaço multidimensional para encontrar os vizinhos mais próximos sem ter que percorrer todo o espaço, como faria uma busca linear por força bruta.

Se você gostou do que leu, não deixe de conferir as outras partes desta série:

Perguntas frequentes

Qual a diferença entre busca vetorial e busca lexical?

A busca lexical não tenta compreender o significado real do que é indexado e consultado; ela busca correspondências entre os literais das palavras ou suas variantes. Em contraste, a busca vetorial indexa os dados de uma forma que permite pesquisá-los com base no significado que representam.

Conteúdo relacionado

Pronto para criar buscas de última geração?

Uma pesquisa suficientemente avançada não se consegue apenas com o esforço de uma só pessoa. O Elasticsearch é impulsionado por cientistas de dados, especialistas em operações de aprendizado de máquina, engenheiros e muitos outros que são tão apaixonados por buscas quanto você. Vamos nos conectar e trabalhar juntos para construir a experiência de busca mágica que lhe trará os resultados desejados.

Experimente você mesmo(a)