Búsqueda por similitud textual con campos vectoriales

Esta publicación explora cómo las incrustaciones de texto y el nuevo tipo de dense_vector de Elasticsearch podrían usar para apoyar la búsqueda por similitud.

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.

Desde sus inicios como motor de búsqueda de recetas, Elasticsearch fue diseñado para ofrecer una búsqueda rápida y poderosa en texto completo. Dadas estas orígenes, mejorar la búsqueda de texto fue una motivación importante para nuestro trabajo continuo con vectores. En Elasticsearch 7.0, introdujimos tipos de campo experimentales para vectores de alta dimensión, y ahora la versión 7.3 incorpora soporte para el uso de estos vectores en el puntaje de documentos.

Esta publicación se centra en una técnica particular llamada búsqueda por similitud textual. En este tipo de búsqueda, un usuario introduce una consulta corta en texto libre, y los documentos se clasifican según su similitud con la consulta. La similitud de texto puede ser útil en una variedad de casos de uso:

  • Respuestas a preguntas: Dada una colección de preguntas frecuentes, busca preguntas similares a la que introdujo el usuario.
  • Búsqueda de artículos: En una colección de artículos de investigación, devuelven artículos con un título estrechamente relacionado con la consulta del usuario.
  • Búsqueda de imágenes: En un conjunto de datos de imágenes con subtítulos, encuentra imágenes cuyo pie de foto sea similar a la descripción del usuario.

Un enfoque sencillo para la búsqueda por similitud sería clasificar los documentos según cuántas palabras compartan con la consulta. Pero un documento puede ser similar a la consulta aunque tengan muy pocas palabras en común; una noción más robusta de similitud tendría en cuenta también su contenido sintáctico y semántico .

La comunidad de procesamiento de lenguaje natural (PLN) desarrolló una técnica llamada incrustación de texto que codifica palabras y oraciones como vectores numéricos. Estas representaciones vectoriales están diseñadas para capturar el contenido lingüístico del texto y pueden emplear para evaluar la similitud entre una consulta y un documento.

Esta publicación explora cómo las incrustaciones de texto y el tipo de dense_vector de Elasticsearch podrían usar para apoyar la búsqueda por similitud. Primero daremos una visión general de las técnicas de incrustación y luego pasaremos por un prototipo sencillo de búsqueda por similitud usando Elasticsearch.

Nota: El uso de incrustaciones de texto en la búsqueda es un área compleja y en evolución. Este blog no es una recomendación para una arquitectura o implementación concreta. Empieza aquí para aprender cómo puedes mejorar tu experiencia de búsqueda con el poder de la búsqueda vectorial.

¿Qué son las incrustaciones de texto?

Echemos un vistazo más de cerca a los diferentes tipos de incrustaciones de texto y cómo se comparan con los enfoques tradicionales de búsqueda.

Incrustaciones de palabras

Un modelo de incrustación de palabras representa una palabra como un vector numérico denso. Estos vectores buscan capturar las propiedades semánticas de la palabra: palabras cuyos vectores están muy cerca deben ser similares en términos de significado semántico. En una buena incrustación, las direcciones en el espacio vectorial están ligadas a diferentes aspectos del significado de la palabra. Por ejemplo, el vector de "Canadá" podría estar cerca de "Francia" en una dirección y cerca de "Toronto" en otra.

Las comunidades de PLN y búsqueda llevan tiempo interesadas en representaciones vectoriales de palabras. En los últimos años hubo un resurgimiento del interés por las incrustaciones de palabras, cuando muchas tareas tradicionales se revisaban empleando redes neuronales. Se desarrollaron algunos algoritmos exitosos de incrustación de palabras, incluyendo word2vec y GloVe. Estos enfoques emplean grandes colecciones de texto y examinan el contexto en el que aparece cada palabra para determinar su representación vectorial:

  • El modelo Skip-gram word2vec capacita una red neuronal para predecir las palabras de contexto alrededor de una palabra en una oración. Los pesos internos de la red dan la palabra embeddings.
  • En GloVe, la similitud de las palabras depende de la frecuencia con la que aparecen junto a otras palabras contextuales. El algoritmo capacita un modelo lineal simple sobre los conteos de co-ocurrencia de palabras.

Muchos grupos de investigación distribuyen modelos que fueron preentrenados en grandes corpus de texto como Wikipedia o Common Crawl, lo que los hace cómodos de descargar e integrar en tareas posteriores. Aunque a veces se emplean versiones preentrenadas directamente, puede ser útil ajustar el modelo para ajustarlo al conjunto de datos y tarea objetivo específicos. Esto a menudo se logra ejecutando un paso de 'ajuste fino' sobre el modelo preentrenado.

Las incrustaciones de palabras demostraron ser bastante robustas y efectivas, y ahora es práctica común usar incrustaciones en lugar de tokens individuales en tareas de PLN como la traducción automática y la clasificación de sentimiento.

Incrustaciones de sentencias

Más recientemente, los investigadores empezaron a centrar en técnicas de incrustación que representan no solo palabras, sino también secciones más largas de texto. La mayoría de los enfoques actuales se basan en arquitecturas de redes neuronales complejas y, a veces, incorporan datos etiquetados durante el entrenamiento para ayudar a capturar información semántica.

Una vez capacitados, los modelos pueden tomar una oración y producir un vector para cada palabra en contexto, así como un vector para toda la oración. De forma similar a la incrustación de palabras, existen versiones preentrenadas de muchos modelos, lo que permite a los usuarios saltar el costoso proceso de entrenamiento. Aunque el proceso de entrenamiento puede ser muy intensivo en recursos, invocar el modelo es mucho más ligero — los modelos de incrustación de oraciones suelen ser lo suficientemente rápidos como para usar como parte de aplicaciones en tiempo real.

Algunas técnicas comunes de incrustación de oraciones incluyen InferSent, Universal Sentence Encoder, ELMo y BERT. Mejorar la incrustación de palabras y frases es un área activa de investigación, y es probable que se introduzcan modelos más estables.

Comparación con los enfoques tradicionales de búsqueda

En la recuperación tradicional de información, una forma común de representar el texto como un vector numérico es asignar una dimensión a cada palabra del vocabulario. El vector de un fragmento de texto se basa entonces en el número de veces que aparece cada término en el vocabulario. Esta forma de representar el texto suele denominar "bolsa de palabras", porque simplemente contamos las apariciones de palabras sin tener en cuenta la estructura de las oraciones.

Las incrustaciones de texto difieren de las representaciones vectoriales tradicionales en algunos aspectos importantes:

  • Los vectores codificados son densos y relativamente de baja dimensión, a menudo con una dimensión que oscila entre 100 y 1.000 dimensiones. En cambio, los vectores de la bolsa de palabras son escasos y pueden comprender 50.000+ dimensiones. Los algoritmos de incrustación codifican el texto en un espacio de dimensión inferior como parte del modelado de su significado semántico. Idealmente, las palabras y frases sinónimas terminan con una representación similar en el nuevo espacio vectorial.
  • Las incrustaciones de oraciones pueden tener en cuenta el orden de las palabras al determinar la representación vectorial. Por ejemplo, la frase "tune in" puede asignar como un vector muy diferente a "in tune".
  • En la práctica, las incrustaciones de oraciones a menudo no se generalizan bien a grandes secciones de texto. No se usan comúnmente para representar textos más largos que un párrafo corto.

Supongamos que tuviéramos una gran colección de preguntas frecuentes. Un usuario puede hacer una pregunta, y queremos recuperar la pregunta más similar de nuestra colección para ayudarlo a encontrar una respuesta.

Podríamos usar incrustaciones de texto para permitir recuperar preguntas similares:

  • Durante la indexación, cada pregunta se pasa por un modelo de incrustación de oraciones para producir un vector numérico.
  • Cuando un usuario introduce una consulta, esta se ejecuta a través del mismo modelo de incrustación de frases para producir un vector. Para clasificar las respuestas, calculamos la similitud del vector entre cada pregunta y el vector de consulta. Al comparar vectores de incrustación, es común usar similitud coseno.

Este repositorio ofrece un ejemplo sencillo de cómo esto podría lograr en Elasticsearch. El script principal indexa ~20.000 preguntas del conjunto de datos StackOverflow, y luego permite al usuario introducir consultas en texto libre sobre el conjunto de datos.

Pronto repasaremos cada parte del guion en detalle, pero primero veamos algunos resultados de ejemplo. En muchos casos, el método es capaz de captar similitudes incluso cuando no hubo una fuerte superposición de palabras entre la consulta y la pregunta indexada:

  • "comprimir archivos" devuelve "Comprimir / Descomprimir carpetas y archivos"
  • "determinar si algo es una IP" devuelve "¿Cómo sabes si una cadena es una IP o un nombre de host"
  • "translate bytes to doubles" devuelve "Convert Bytes to Floating Points Numbers in Python"

Detalles de implementación

El script comienza descargando y creando el modelo de incrustación en TensorFlow. Elegimos el Codificador Universal de Oraciones de Google, pero es posible usar muchos otros métodos de incrustación. El script emplea el modelo de incrustación tal cual, sin ningún entrenamiento o ajuste fino adicional.

A continuación, creamos el índice Elasticsearch, que incluye mapeos para el título de la pregunta, las etiquetas y también el título de la pregunta codificado como vector:

En el mapeo para dense_vector, debemos especificar el número de dimensiones que contendrán los vectores. Al indexar un campo title_vector, Elasticsearch comprueba que tenga el mismo número de dimensiones especificado en el mapeo.

Para indexar documentos, pasamos el título de la pregunta por el modelo de incrustación para obtener un array numérico. Este array se agrega al documento en el campo title_vector.

Cuando un usuario introduce una consulta, el texto se pasa primero por el mismo modelo de incrustación y se almacena en el parámetro query_vector. A partir de la versión 7.3, Elasticsearch proporciona una función cosineSimilarity en su lenguaje de scripting nativo. Así que para clasificar las preguntas según su similitud con la consulta del usuario, usamos una consulta script_score:

Nos cercioramos de pasar el vector de consulta como parámetro de script para evitar recompilar el script() en cada nueva consulta. Como Elasticsearch no permite puntajes negativos, es necesario agregar una a la similitud coseno.

| Nota: esta entrada de blog originalmente usaba una sintaxis diferente para funciones vectoriales que estaba disponible en Elasticsearch 7.3, pero que fue obsoleta en la 7.6.
|

Limitaciones importantes

La consulta script_score está diseñada para envolver una consulta restrictiva y modificar los puntajes de los documentos que devuelve. Sin embargo, proporcionamos una consulta match_all, lo que significa que el script se ejecutará sobre todos los documentos del índice. Esta es una limitación actual de la similitud vectorial en Elasticsearch: los vectores pueden usar para puntuar documentos, pero no en el paso inicial de recuperación. El soporte para la recuperación basado en la similitud vectorial es un área importante de trabajo en curso.

Para evitar escanear todos los documentos y mantener un rendimiento rápido, la consulta de match_all puede ser reemplazada por una consulta más selectiva. La consulta adecuada para la recuperación probablemente dependerá del caso de uso específico.

Aunque vimos algunos ejemplos alentadores arriba, es importante señalar que los resultados también pueden ser ruidosos y poco intuitivos. Por ejemplo, "comprimir archivos" también asigna puntajes altos a "Partial .csproj Archivos" y "Cómo evitar .pyc ¿archivos?". Y cuando el método arroja resultados sorprendentes, no siempre está claro cómo depurar el problema: el significado de cada componente vectorial suele ser opaco y no corresponde a un concepto interpretable. Con las técnicas tradicionales de puntaje basadas en solapamientos de palabras, a menudo es más fácil responder a la pregunta "¿por qué este documento está muy bien clasificado?"

Como se mencionó antes, este prototipo está pensado como un ejemplo de cómo los modelos de incrustación podrían usar con campos vectoriales, y no como una solución lista para producción. Al desarrollar una nueva estrategia de búsqueda, es fundamental probar cómo funciona el enfoque con tus propios datos, cerciorándote de comparar con una línea base estable como una consulta de coincidencia. Puede ser necesario realizar cambios importantes en la estrategia antes de que logre resultados estables, incluyendo afinar el modelo de incrustación para el conjunto de datos objetivo o probar diferentes formas de incorporar incrustaciones como la expansión de consultas a nivel de palabra.

Conclusiones

Las técnicas de incrustación proporcionan una forma poderosa de captar el contenido lingüístico de un texto. Indexando incrustaciones y puntaje basándonos en la distancia vectorial, podemos comparar documentos usando una noción de similitud que va más allá de su solapamiento a nivel de palabra.

Esperamos introducir más funcionalidades basadas en el tipo de campo vectorial. El uso de vectores para la búsqueda es un área matizada y en desarrollo — como siempre, nos encantaría conocer vuestros casos de uso y experiencias en Github y en los foros de discusión.

Preguntas frecuentes

¿Qué es la búsqueda por similitud textual?

La búsqueda por similitud de texto es un tipo de búsqueda en la que un usuario introduce una consulta corta de texto libre, y los documentos se clasifican en función de su similitud con la consulta. Puede ser útil en una variedad de casos de uso, como la respuesta a preguntas, la búsqueda de artículos y la búsqueda de imágenes.

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