Una breve introducción a la búsqueda vectorial

Este artículo es el primero de un serial de tres que profundizarán en las complexidades de la búsqueda vectorial, también conocida como búsqueda semántica, y cómo se implementa en Elasticsearch.

Elasticsearch ofrece a los desarrolladores el conjunto de herramientas de búsqueda más completo, desde la búsqueda vectorial hasta las potentes API REST. Descubre los cuadernos de muestra en GitHub para probar algo nuevo. También puedes iniciar tu prueba gratuita o ejecutar Elasticsearch localmente hoy mismo.

Este artículo es el primero de un serial de tres que profundizarán en las complexidades de la búsqueda vectorial, también conocida como búsqueda semántica, y cómo se implementa en Elasticsearch.

Esta primera parte se centra en ofrecer una introducción general a los conceptos básicos de incrustación de vectores y cómo funciona la búsqueda vectorial en el interior.

Armado con todo el conocimiento aprendido en el primer artículo, la segunda parte te guiará por los ménsilos de cómo configurar la búsqueda vectorial en Elasticsearch.

En la tercera parte, aprovecharemos lo que aprendimos en las dos primeras partes, construiremos sobre ese conocimiento y profundizaremos en cómo crear poderosas consultas híbridas de búsqueda en Elasticsearch.

Antes de adentrarnos en el asunto real de este artículo, volvamos atrás en el tiempo y repasemos parte de la historia de los vectores, que es un concepto clave en la búsqueda semántica.

Los vectores no son nuevos

Estoy bastante seguro de que todo el mundo estaría de acuerdo en que desde la llegada de ChatGPT en noviembre de 2022, no pasa ni un solo día sin oír o leer sobre la "búsqueda vectorial". Está en todas partes y es tan común que a menudo tenemos la impresión de que es una tecnología de vanguardia que acaba de salir, ¡pero la verdad es que esta tecnología lleva más de seis décadas en el mercado! La investigación sobre el tema comenzó a mediados de los años 60, y los primeros artículos científicos se publicaron en 1978 por Gerard Salton, un experto en recuperación de información, y sus colegas de la Universidad de Cornell. El trabajo de Salton sobre modelos vectoriales densos y dispersos constituye la raíz de la tecnología moderna de búsqueda vectorial.

En los últimos 20 años, se crearon y llevado al mercado muchos SGBD vectoriales diferentes basados en su investigación. Entre ellos se encuentra Elasticsearch, impulsado por el proyecto Apache Lucene, que comenzó a trabajar en búsqueda vectorial en 2019.

Los vectores están ahora en todas partes y son tan omnipresentes que es importante primero comprender bien su teoría subyacente y su funcionamiento interno antes de experimentar con ellos. Antes de profundizar en eso, repasemos rápidamente las diferencias entre la búsqueda léxica y la búsqueda vectorial para entender mejor cómo difieren y cómo pueden complementar entre sí.

Una forma sencilla de introducir la búsqueda vectorial es comparándola con la búsqueda léxica más convencional a la que probablemente estés acostumbrado. La búsqueda vectorial, también conocida comúnmente como búsqueda semántica, y la búsqueda léxica funcionan de forma muy diferente. La búsqueda léxica es el tipo de búsqueda que todos estuvimos usando durante años en Elasticsearch. Resumiéndolo muy brevemente, no intenta entender el verdadero significado de lo que se indexa y consulta, sino que hace un gran esfuerzo por hacer coincidir léxicamente los literales de las palabras o variantes de ellas (piensa en stemming, sinónimos, etc.) que el usuario escribe en una consulta con todos los literales que fueron indexados previamente en la base de datos usando algoritmos de similitud, como la TF-IDF

Como podemos ver, los tres documentos de la esquina superior izquierda están tokenizados y analizados. Luego, los términos resultantes se indexan en un índice invertido, que simplemente mapea los términos analizados a los IDs de los documentos que los contienen. Ten en cuenta que todos los términos solo están presentes una vez y ninguno es compartido por ningún documento. Buscar "buen profesor de alemán" hará coincidir los tres documentos con puntajes variables, aunque ninguno capte realmente el significado real de la consulta.

Como se puede ver en la Figura 2, más abajo, se complica aún más cuando se trata de polisemia u homógrafos, es decir, palabras que se escriben igual pero tienen significados diferentes (derecha, palma, murciélago, media, etc.) Tomemos la palabra "correcto", que puede significar tres cosas diferentes, y veamos qué ocurre.

Buscar "I'm not right" devuelve un documento que tiene el significado exactamente opuesto al resultado original. Si buscas exactamente los mismos términos pero los ordenas de forma diferente para producir un significado distinto, por ejemplo, "voltea a la derecha" y "giro a la derecha", obtienes el mismo resultado exacto (es decir, el tercer documento "Toma un giro a la derecha"). Es cierto que nuestras consultas son excesivamente simplificadas y no emplean consultas más avanzadas como la comparación de frases, pero esto ayuda a ilustrar que la búsqueda léxica no entiende el verdadero significado detrás de lo que se indexa y lo que se busca. Si no queda claro, no te preocupes, retomaremos este ejemplo en el tercer artículo para ver cómo la búsqueda vectorial puede ayudar en este caso.

Para hacer justicia a la búsqueda léxica, cuando tienes control sobre cómo indexas tus datos estructurados (piensa en mapeos, análisis de texto, pipelines de ingest, etc.) y cómo elaboras tus consultas (piensa en consultas DSL ingeniosamente diseñadas, análisis de términos de consulta, etc.), puedes hacer maravillas con motores de búsqueda léxicos, ¡no hay duda! El historial de Elasticsearch en cuanto a sus capacidades de búsqueda léxica es simplemente asombroso. Lo que logró y cuánto popularizó y mejorado el campo de la búsqueda léxica en los últimos años es realmente notable.

Sin embargo, cuando se te encarga proporcionar soporte para consultar datos no estructurados (piensa en imágenes, videos, audios, texto en bruto, etc.) a usuarios que necesitan hacer preguntas de texto libre, la búsqueda léxica no funciona. Además, a veces la consulta ni siquiera es texto, podría ser una imagen, como veremos en breve. La principal razón por la que la búsqueda léxica es inadecuada en estas situaciones es que los datos no estructurados no pueden ni indexar ni consultar de la misma manera que los datos estructurados. Cuando se trata de datos no estructurados, entra en juego la semántica . ¿Qué significa la semántica? Muy simplemente, ¡el significado!

Tomemos el ejemplo sencillo de un motor de búsqueda de imágenes (por ejemplo, Google Image Search o Lens). Arrastras y soltas una imagen, y el motor de búsqueda semántica de Google encontrará y devolverá las imágenes más similares a la que consultaste. En la Figura 3, a continuación, podemos ver a la izquierda la imagen de un pastor alemán y a la derecha todas las imágenes similares que se recuperaron, siendo el primer resultado la misma imagen que la proporcionada (es decir, la más parecida).

Aunque esto parezca simple y lógico para nosotros, para las computadoras es otra historia completamente distinta. Eso es lo que permite y ayuda a lograr la búsqueda vectorial. El poder desbloqueado por la búsqueda vectorial es enorme, como el mundo presenció recientemente. Ahora levantemos la capucha y descubramos qué se esconde debajo.

Vectores de incrustación

Como vimos antes, con los motores de búsqueda léxicos, los datos estructurados como el texto pueden tokenizarse fácilmente en términos que pueden coincidir en el momento de la búsqueda, independientemente del significado real de los términos. Sin embargo, los datos no estructurados pueden adoptar diferentes formas, como grandes objetos binarios (imágenes, videos, audios, etc.), y no son en absoluto adecuados para el mismo proceso de tokenización. Además, el propósito principal de la búsqueda semántica es indexar los datos de tal manera que puedan buscar según el significado que representan. ¿Cómo lo logramos? La respuesta está en dos palabras: ¡Aprendizaje Automático! ¡O más concretamente, Aprendizaje Profundo!

El aprendizaje profundo es un área específica del aprendizaje automático que se basa en modelos basados en redes neuronales artificiales compuestas por múltiples capas de procesamiento que pueden extraer progresivamente el verdadero significado de los datos. La forma en que funcionan esos modelos de redes neuronales está fuertemente inspirada en el cerebro humano. La figura 4, a continuación, muestra cómo es una red neuronal, con sus capas de entrada y salida, así como múltiples capas ocultas:

La verdadera hazaña de las redes neuronales es que son capaces de convertir un solo dato no estructurado en una secuencia de valores de punto flotante, conocidos como vectores de incrustación o simplemente incrustaciones. Como seres humanos, podemos entender bastante bien qué son los vectores siempre que los visualizemos en un espacio bidimensional o tridimensional. Cada componente del vector representa una coordenada en un plano x-y 2D o en un espacio 3D x-y-z.

Sin embargo, los vectores de incrustación sobre los que trabajan los modelos de redes neuronales pueden tener varios cientos o incluso miles de dimensiones y simplemente representar un punto en un espacio multidimensional. Cada dimensión vectorial representa una característica, o una característica, de los datos no estructurados. Ilustremos esto con un modelo de aprendizaje profundo que convierte imágenes en vectores de incrustación de 2048 dimensiones. Ese modelo convertiría la imagen del pastor alemán que usamos en la Figura 3 en el vector de incrustación mostrado en la tabla siguiente. Ten en cuenta que solo mostramos el primer y último tres elementos, pero habría 2.042 columnas/dimensiones más en la tabla.

is_redis_dogblue_skyno_grasgerman_shepherdis_tree
Pastor alemán Incrustaciones0.01210.95720.87350.11980.97120.0512

Cada columna es una dimensión del modelo y representa una característica, o característica, que la red neuronal subyacente busca modelar. Cada entrada dada al modelo se caracterizará dependiendo de lo similar que sea esa entrada a cada una de las 2048 dimensiones. Por tanto, el valor de cada elemento en el vector de incrustación denota la similitud de esa entrada con una dimensión específica. En este ejemplo, podemos ver que el modelo detectó una alta similitud entre perros y pastores alemanes, así como la presencia de algo de cielo azul.

A diferencia de la búsqueda léxica, donde un término puede ser emparejado o no, con la búsqueda vectorial podemos obtener una idea mucho mejor de cuán similar es un dato no estructurado a cada una de las dimensiones soportadas por el modelo. Por tanto, los vectores de incrustación sirven como una representación semántica fantástica de los datos no estructurados.

La salsa secreta

Ahora que sabemos cómo los datos no estructurados son segmentados y fragmentados por redes neuronales de aprendizaje profundo en vectores de incrustación que capturan la similitud de los datos a lo largo de un gran número de dimensiones, necesitamos entender cómo funciona la coincidencia de esos vectores. Resulta que la respuesta es bastante sencilla. Los vectores de incrustación que están cerca entre sí representan piezas de datos semánticamente similares . Así que, cuando consultamos una base de datos vectorial, la entrada de búsqueda (imagen, texto, etc.) se convierte primero en un vector de incrustación usando el mismo modelo que se usó para indexar todos los datos no estructurados, y el objetivo final es encontrar los vectores vecinos más cercanos a ese vector de consulta. Por tanto, solo tenemos que averiguar cómo medir la "distancia" o "similitud" entre el vector de consulta y todos los vectores existentes indexados en la base de datos, y eso es básicamente todo.

Distancia y similitud

Por suerte para nosotros, medir la distancia entre dos vectores es un problema fácil de resolver gracias a la aritmética vectorial. Así que, veamos las funciones de distancia y similitud más populares que soportan las bases de datos modernas de búsqueda vectorial, como Elasticsearch. ¡Aviso, matemáticas adelante!

Distancia L1

La distancia L1, también llamada distancia de Manhattan, de dos vectores x e y se mide sumando la diferencia absoluta por pares de todos sus elementos. Obviamente, cuanto menor es la distancia d, más cerca están los dos vectores. La fórmula es bastante sencilla, como se puede ver a continuación:

Visualmente, la distancia L1 puede ilustrar como se muestra en la Figura 5, a continuación:

Tomemos dos vectores x e y, como x = (1, 2) y y = (4, 3), entonces la distancia L1 de ambos vectores sería | 1 - 4 | + | 2 - 3 | = 4.

Distancia L2

La distancia L2, también llamada distancia euclidiana, de dos vectores x e y se mide primero sumando el cuadrado de la diferencia de pares de todos sus elementos y luego tomando la raíz cuadrada del resultado. Básicamente es el camino más corto entre dos puntos (también llamado hipotenusa). De forma similar a L1, cuanto menor sea la distancia d, más cerca estarán los dos vectores:

La distancia L2 se muestra en la Figura 6 a continuación:

Reutilicemos los mismos dos vectores de muestra x e y que usamos para la distancia L1, y ahora podemos calcular la distancia L2 como (14)2+(23)2=10(1 - 4)^2 + (2 - 3)^2 = 10. Tomando la raíz cuadrada de 10, obtendría 3,16.

Distancia de Linf

La distancia de Linf (por L infinito), también llamada distancia de Chebyshev o distancia del tablero de ajedrez, de dos vectores x e y se define simplemente como la distancia más larga entre dos de sus elementos o la distancia más larga medida a lo largo de uno de los ejes/dimensiones. La fórmula es muy sencilla y se muestra a continuación:

Una representación de la distancia Linf se muestra en la Figura 7 a continuación:

De nuevo, tomando los mismos dos vectores muestrales x e y, podemos calcular la distancia infinita L como max ( | 1 - 4 | , | 2 - 3 | ) = max (3, 1) = 3.

Similitud coseno

A diferencia de L1, L2 y Linf, la similitud coseno no mide la distancia entre dos vectores x e y, sino su ángulo relativo, es decir, si ambos apuntan aproximadamente en la misma dirección. Cuanto mayor sea la similitud s, más "cerca" están los dos vectores. La fórmula es de nuevo muy sencilla y se muestra a continuación:

Una forma de representar la similitud coseno entre dos vectores se muestra en la Figura 8 a continuación:

Además, como los valores del coseno siempre están en el intervalo [-1, 1], -1 significa similitud opuesta (es decir, un ángulo de 180° entre ambos vectores), 0 significa similitud no relacionada (es decir, un ángulo de 90°) y 1 significa idéntico (es decir, un ángulo 0°), como se muestra en la Figura 9 más abajo:


Una vez más, reutilicemos los mismos vectores muestrales x e y calculemos la similitud coseno usando la fórmula anterior. Primero, podemos calcular el producto escalar de ambos vectores como (14)+(23)=10(1 · 4) + (2 · 3) = 10. Luego, multiplicamos la longitud (también llamada magnitud) de ambos vectores: (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 el producto escalar por la longitud multiplicada 10 / 11,18034 = 0,894427 (es decir, un ángulo de 26°), que es bastante cercano a 1, por lo que ambos vectores pueden considerar bastante similares.

Similitud del producto escalar

Una desventaja de la similitud entre coseno es que solo tiene en cuenta el ángulo entre dos vectores pero no su magnitud (es decir, la longitud), lo que significa que si dos vectores apuntan aproximadamente en la misma dirección pero uno es mucho más largo que el otro, ambos seguirán considerar similares. La similitud del producto escalar, también llamada escalar o producto interior, mejora esto teniendo en cuenta tanto el ángulo como la magnitud de los vectores, lo que proporciona una métrica de similitud mucho más precisa.

Se emplean dos fórmulas equivalentes para calcular la similitud del producto escalar. La primera es la misma que vimos anteriormente en el numerador de similitud coseno:

La segunda fórmula simplemente multiplica la longitud de ambos vectores por el coseno del ángulo entre ellos:

La similitud del producto escalar se visualiza en la Figura 10, a continuación:

Una última vez, tomamos los vectores de muestra x e y calculamos su similitud del producto escalar usando la primera fórmula, como hicimos antes para la similitud coseno, como (1 · 4) + (2 · 3) = 10.

Usando la segunda fórmula, multiplicamos la longitud de ambos vectores: (12+22)1/2+(42+32)1/2=11,18034(1^2 + 2^2)^{1/2}+ (4^2 + 3^2)^{1/2} = 11,18034 y multiplicamos eso por el coseno del ángulo de 26° entre ambos vectores, y obtenemos 11,18034 · cos(26°) = 10.

Algo que vale la pena señalar es que si todos los vectores se normalizan primero (es decir, su longitud es 1), entonces la similitud del producto escalar se convierte exactamente en la misma que la similitud del coseno (porque |x| |y| = 1), es decir, el coseno del ángulo entre ambos vectores. Como veremos más adelante, normalizar vectores es una buena práctica para hacer que la magnitud del vector sea irrelevante y que la similitud se centre simplemente en el ángulo. También acelera el cálculo de distancias en el tiempo de indexación y consulta, lo que puede ser un gran problema al operar con miles de millones de vectores.

Resumen rápido

Vaya, revisamos MUCHÍSIMA información hasta ahora, así que vamos a hacer una pausa un momento y hacer un breve resumen de dónde estamos. Aprendimos que...

  • … La búsqueda semántica se basa en modelos de redes neuronales de aprendizaje profundo que destacan en transformar datos no estructurados en vectores de incrustación multidimensionales.
  • … Cada dimensión del modelo representa una característica o característica de los datos no estructurados.
  • … Un vector de incrustación es una secuencia de valores de similitud (uno para cada dimensión) que representa lo similar que es a cada dimensión un dato no estructurado dado.
  • … cuanto más "cercanos" estén dos vectores (es decir, los vecinos más cercanos), más representan conceptos semánticamente similares.
  • … Las funciones de distancia (L1, L2, Linf) nos permiten medir la proximidad de dos vectores.
  • … Las funciones de similitud (coseno y producto escalar) nos permiten medir cuánto se dirigen dos vectores en la misma dirección.

Ahora, la última pieza en la que tenemos que profundizar es el propio motor de búsqueda vectorial. Cuando llega una consulta, primero se vectoriza y luego el motor de búsqueda vectorial encuentra los vectores vecinos más cercanos a ese vector. El enfoque de fuerza bruta de medir la distancia o similitud entre el vector de consulta y todos los vectores de la base de datos puede funcionar para conjuntos de datos pequeños, pero pronto se queda corto a medida que aumenta el número de vectores. Dicho de otro modo, ¿cómo podemos indexar millones, miles de millones o incluso billones de vectores y encontrar los vecinos más cercanos del vector de consulta en un tiempo razonable? Ahí es donde necesitamos ser inteligentes y encontrar formas óptimas de indexar vectores para poder centrarnos en los vecinos más cercanos lo más rápido posible sin degradar demasiado la precisión.

Algoritmos y técnicas de búsqueda vectorial

A lo largo de los años, muchos equipos de investigación invirtieron mucho esfuerzo en desarrollar algoritmos de búsqueda vectorial muy ingeniosos. Aquí vamos a presentar brevemente los principales. Dependiendo del caso de uso, algunos son más adecuados que otros.

Hablamos brevemente de la búsqueda lineal, o indexación plana, cuando mencionamos el enfoque de fuerza bruta de comparar el vector de consulta con todos los vectores presentes en la base de datos. Aunque puede funcionar bien en conjuntos de datos pequeños, el rendimiento disminuye rápidamente a medida que aumenta el número de vectores y dimensiones (complejidad O(n)).

Por suerte, existen enfoques más eficientes llamados vecinos aproximados (ANN), donde las distancias entre vectores de incrustación se precalculan y se almacenan y organizan vectores similares de forma que se mantengan cerca unos de otros, por ejemplo usando clústeres, árboles, hashes o grafos. Estos enfoques se denominan "aproximados" porque normalmente no garantizan una precisión del 100%. El objetivo final es reducir el alcance de la búsqueda tanto y lo más rápido posible para centrar solo en las áreas que tienen más probabilidades de contener vectores similares o reducir la dimensionalidad de los vectores.

Árboles de dimensión K

Un árbol de dimensión K, o árbol KD, es una generalización de un árbol binario de búsqueda que almacena puntos en un espacio de dimensión k y funciona dividiendo continuamente el espacio de búsqueda en árboles más pequeños a la izquierda y a la derecha donde se indexan los vectores. En el momento de buscar, el algoritmo simplemente tiene que visitar algunas ramas del árbol alrededor del vector de consulta (el punto rojo de la Figura 11) para encontrar el vecino más cercano (el punto verde de la Figura 11). Si se aplicar más de k vecinos, entonces el área amarilla se extiende hasta que el algoritmo encuentre más vecinos.

El mayor beneficio del algoritmo del árbol KD es que nos permite centrarnos rápidamente solo en algunas ramas localizadas del árbol, eliminando así la mayoría de los vectores de la consideración. Sin embargo, la eficiencia de este algoritmo disminuye a medida que aumenta el número de dimensiones, ya que es necesario visitar muchas más ramas que en espacios de dimensiones inferiores.

Índice de archivos invertido

El enfoque de índice de archivos invertido (IVF) también es un algoritmo de partición de espacio que asigna vectores cercanos entre sí a su centroide compartido. En el espacio 2D, esto se visualiza mejor con un diagrama de Voronoi, como se muestra en la Figura 12:

Podemos ver que el espacio 2D anterior está dividido en 20 grupos, cada uno con su centroide denotado como puntos negros. Todos los vectores de incrustación en el espacio se asignan al clúster cuyo centroide está más cercano a ellos. En el momento de buscar, el algoritmo primero determina el clúster en el que centrar encontrando el centroide más cercano al vector de consulta, y luego puede simplemente enfocar en esa zona, y también en las circundantes si es necesario, para encontrar los vecinos más cercanos.

Este algoritmo sufre el mismo problema que los árboles KD cuando se usa en espacios de alta dimensión. Esto se llama la maldición de la dimensionalidad, y ocurre cuando el volumen del espacio aumenta tanto que todos los datos parecen escasos y la cantidad de datos que se necesitaría para obtener resultados más precisos crece exponencialmente. Cuando los datos son escasos, resulta más difícil para estos algoritmos de partición del espacio organizar los datos en clústeres. Por suerte para nosotros, existen otros algoritmos y técnicas que alivian este problema, como se detalla a continuación.

Cuantificación

La cuantización es un enfoque basado en compresiónque nos permite reducir el tamaño total de la base de datos disminuyendo la precisión de los vectores de incrustación. Esto se puede lograr usando cuantización escalar (SQ) convirtiendo los valores vectoriales de punto flotante en valores enteros. Esto no solo reduce el tamaño de la base de datos en un factor de 8, sino que también disminuye el consumo de memoria y acelera el cálculo de distancias entre vectores en el momento de búsqueda.

Otra técnica se llama cuantización por producto (PQ), que primero divide el espacio en subespacios de dimensión inferior, y luego los vectores muy cercanos se agrupan en cada subespacio usando un algoritmo de agrupamiento (similar a las k-medias).

Cabe señalar que la cuantización es diferente de la reducción de dimensionalidad, donde se reduce el número de dimensiones, es decir, los vectores simplemente se acortan.

Pequeños Mundos Jerárquicos Navegables (HNSW)

Si parece complejo solo con leer el nombre, no te preocupes, ¡no lo es realmente! En resumen, Jerarchical Navigable Small Worlds es un algoritmo basado en grafos de múltiples capas que es muy popular y eficiente. Es empleado por muchas bases de datos vectoriales diferentes, incluyendo Apache Lucene. Una representación conceptual de HNSW puede ver en la Figura 13, a continuación.

En la capa superior, podemos ver un grafo de muy pocos vectores que tienen los enlaces más largos entre ellos, es decir, un grafo de vectores conectados con la menor similitud. Cuanto más profundizamos en capas inferiores, más vectores encontramos y más denso se vuelve el grafo, con cada vez más vectores más cerca entre sí. En la capa más baja, podemos encontrar todos los vectores, siendo los más similares los más cercanos entre sí.

En el momento de la búsqueda, el algoritmo comienza desde la capa superior en un punto de entrada arbitrario y encuentra el vector más cercano al vector de consulta (mostrado por el punto gris). Luego, se mueve una capa por debajo y repite el mismo proceso, empezando por el mismo vector que dejó en la capa anterior, y así sucesivamente, capa tras capa, hasta llegar a la capa más baja y encontrar al vecino más cercano al vector de consulta.

Hashing sensible a la localidad (LSH)

En la misma línea que todos los demás enfoques presentados hasta ahora, el hashing sensible a la localidad busca reducir significativamente el espacio de búsqueda para aumentar la velocidad de recuperación. Con esta técnica, los vectores de incrustación se transforman en valores hash, todo preservando la información de similitud, de modo que el espacio de búsqueda se convierte finalmente en una simple tabla hash que se puede consultar en lugar de un grafo o árbol que hay que recorrer. El principal beneficio de los métodos basados en hash es que los vectores que contienen un número arbitrario (grande) de dimensiones pueden mapearse a hashes de tamaño fijo, lo que acelera enormemente el tiempo de recuperación sin sacrificar demasiada precisión.

Existen muchas formas diferentes de hacer hashing de datos en general, y de incrustar vectores en individuo, pero este artículo no profundizará en los detalles de cada una de ellas. Los métodos de hashing convencionales suelen producir hashes muy diferentes para datos que parecen muy similares. Dado que los vectores de incrustación están compuestos por valores flotantes, tomemos dos valores de flotación de muestra que se consideran muy cercanos entre sí en aritmética vectorial (por ejemplo, 0,73 y 0,74) y los pasemos por algunas funciones de hash comunes. Al mirar los resultados a continuación, es bastante obvio que las funciones de hash comunes no mantienen la similitud entre las entradas.

Función de hash0.730.74
MD51342129d04cd2924dd06cead4cf0a3ca0aec1b15371bd979cfa66b0a50ebecc5
SHA149d2c3e0e44bff838e1db571a121be5ea874e8d9a534e76482ade9d9fe4bff3035a7f31f2f363d77
SHA25699d03fc3771fe6848d675339fc49eeb1cb8d99a12e6358173336b99a2ec530ea5ecbc825ba5c16856edfdaf0abc5c6c41d0d8a9c508e34188239521dc7645663

Mientras que los métodos convencionales de hashing intentan minimizar las colisiones de hashing entre fragmentos de datos similares, el objetivo principal del hashing sensible a la localidad es hacer exactamente lo contrario, es decir, maximizar las colisiones de hashing para que datos similares caigan dentro del mismo cubo con alta probabilidad. Al hacerlo, los vectores de incrustación que están muy cerca en un espacio multidimensional se hashearán hasta un valor de tamaño fijo que cae en el mismo cubo. Dado que LSH permite que esos vectores hasheados mantengan su proximidad, esta técnica resulta muy útil para agrupar datos y búsquedas de vecinos más cercanos.

Todo el trabajo pesado ocurre en el momento de indexación, cuando hay que calcular los hashes, mientras que en busca solo necesitamos hacer hash del vector de consulta para buscar el cubo que contiene los vectores de incrustación más cercanos. Una vez encontrado el cubo candidato, normalmente se realiza una segunda ronda para identificar los vectores vecinos más cercanos al vector de consulta.

Concluyamos

Para introducir la búsqueda vectorial, tuvimos que cubrir bastante terreno en este artículo. Tras comparar las diferencias entre la búsqueda léxica y la búsqueda vectorial, aprendimos cómo los modelos de redes neuronales de aprendizaje profundo logran capturar la semántica de los datos no estructurados y transcodificar su significado en vectores de incrustación de alta dimensión, una secuencia de números de coma flotante que representan la similitud de los datos a lo largo de cada una de las dimensiones del modelo. También cabe destacar que la búsqueda vectorial y la búsqueda léxica no son técnicas de recuperación de información complementarias en competencia (como veremos en la tercera parte de este serial cuando profundizaremos en la búsqueda híbrida).

Luego de eso, introdujimos un bloque fundamental de la búsqueda vectorial, a saber, las funciones de distancia (y similitud) que nos permiten medir la proximidad de dos vectores y evaluar la similitud de los conceptos que representan.

Por último, revisamos diferentes variantes de los algoritmos y técnicas de búsqueda vectorial más populares, que pueden basar en árboles, grafos, clústeres o hashes, cuyo objetivo es acotar rápidamente una zona específica del espacio multidimensional para encontrar a los vecinos más cercanos sin tener que recorrer todo el espacio como haría una búsqueda lineal por fuerza bruta.

Si te gusta lo que estás leyendo, cerciórate de echar un vistazo a las otras partes de este serial:

Preguntas frecuentes

¿Cuál es la diferencia entre la búsqueda vectorial y la búsqueda léxica?

La búsqueda léxica no intenta entender el significado real de lo que se indexa y consulta: coincide con los literales de las palabras o sus variantes. En cambio, la búsqueda vectorial indexa los datos de una manera que permite buscarlos según el significado que representan.

Contenido relacionado

¿Estás listo para crear experiencias de búsqueda de última generación?

No se logra una búsqueda suficientemente avanzada con los esfuerzos de uno. Elasticsearch está impulsado por científicos de datos, operaciones de ML, ingenieros y muchos más que son tan apasionados por la búsqueda como tú. Conectemos y trabajemos juntos para crear la experiencia mágica de búsqueda que te dará los resultados que deseas.

Pruébalo tú mismo