Búsqueda eficiente de vectores de similitud en flujos de trabajo de recomendación utilizando Milvus con NVIDIA Merlin
Este artículo se publicó por primera vez en el canal de NVIDIA Merlin en Medium y se ha editado y publicado aquí con permiso. Ha sido escrito conjuntamente por Burcin Bozkaya y William Hicks de NVIDIA y Filip Haltmayer y Liu de Zilliz.
Introducción
Los sistemas de recomendación modernos (Recsys) consisten en procesos de entrenamiento e inferencia que incluyen múltiples etapas de entrada de datos, preprocesamiento de datos, entrenamiento de modelos y ajuste de hiperparámetros para recuperar, filtrar, clasificar y puntuar elementos relevantes. Un componente esencial de un sistema de recomendación es la recuperación o descubrimiento de los elementos más relevantes para un usuario, sobre todo en presencia de grandes catálogos de artículos. Este paso suele implicar una búsqueda aproximada del vecino más cercano (RNA ) en una base de datos indexada de representaciones vectoriales de baja dimensión (es decir, incrustaciones) de atributos de productos y usuarios creadas a partir de modelos de aprendizaje profundo que se entrenan en interacciones entre usuarios y productos/servicios.
NVIDIA Merlin, un marco de código abierto desarrollado para entrenar modelos de extremo a extremo para hacer recomendaciones a cualquier escala, se integra con un índice de base de datos vectorial eficiente y un marco de búsqueda. Milvus, una base de datos vectorial de código abierto creada por Zilliz, es uno de estos marcos que ha suscitado gran interés recientemente. Ofrece funciones rápidas de índice y consulta. Recientemente, Milvus ha añadido soporte de aceleración en la GPU que utiliza las GPU NVIDIA para sostener los flujos de trabajo de IA. El soporte de la aceleración de GPU es una gran noticia porque una biblioteca de búsqueda vectorial acelerada hace posibles las consultas concurrentes rápidas, impactando positivamente en los requisitos de latencia en los sistemas de recomendación de hoy en día, donde los desarrolladores esperan muchas solicitudes concurrentes. Milvus tiene más de 5 millones de docker pulls, ~23.000 estrellas en GitHub (en septiembre de 2023), más de 5.000 clientes empresariales y es un componente central de muchas aplicaciones (véanse los casos de uso).
Este blog muestra cómo funciona Milvus con el marco Merlin Recsys en el momento de la formación y la inferencia. Mostramos cómo Milvus complementa a Merlin en la fase de recuperación de elementos con una búsqueda de incrustación vectorial top-k de alta eficiencia y cómo puede utilizarse con NVIDIA Triton Inference Server (TIS) en el momento de la inferencia (véase la Figura 1). Nuestros resultados de referencia muestran un impresionante aumento de la velocidad de 37 a 91 veces con Milvus acelerado en la GPU que utiliza NVIDIA RAFT con las incrustaciones vectoriales generadas por Merlin Models. El código que utilizamos para mostrar la integración Merlin-Milvus y los resultados detallados de las pruebas de rendimiento, junto con la biblioteca que facilitó nuestro estudio comparativo, están disponibles aquí.
Figura 1. Sistema de recomendación multietapa con Merlin-Milvus Sistema de recomendación multietapa con el marco Milvus contribuyendo a la etapa de recuperación. Fuente de la figura original: esta entrada de blog.
Los retos de los recomendadores
Dada la naturaleza multietapa de los recomendadores y la disponibilidad de varios componentes y bibliotecas que integran, un reto importante es integrar todos los componentes a la perfección en una canalización de extremo a extremo. En nuestros cuadernos de ejemplo pretendemos demostrar que la integración puede realizarse con menos esfuerzo.
Otro reto de los flujos de trabajo de recomendación es acelerar ciertas partes del proceso. Aunque se sabe que desempeñan un papel muy importante en el entrenamiento de grandes redes neuronales, las GPU son una incorporación reciente a las bases de datos vectoriales y la búsqueda de RNA. A medida que aumenta el tamaño de los inventarios de productos de comercio electrónico o las bases de datos de streaming multimedia y el número de usuarios que utilizan estos servicios, las CPU deben proporcionar el rendimiento necesario para atender a millones de usuarios en flujos de trabajo de Recsys de alto rendimiento. Para hacer frente a este reto, se ha hecho necesaria la aceleración en la GPU de otras partes del pipeline. La solución de este blog aborda este reto demostrando que la búsqueda RNA es eficiente cuando se utilizan GPU.
Pilas tecnológicas para la solución
Empecemos por repasar primero algunos de los fundamentos necesarios para llevar a cabo nuestro trabajo.
NVIDIA Merlin: una biblioteca de código abierto con API de alto nivel que acelera los recomendadores en las GPU NVIDIA.
NVTabular: para el preprocesamiento de los datos tabulares de entrada y la ingeniería de características.
Merlin Models: para entrenar modelos de aprendizaje profundo y aprender, en este caso, vectores de incrustación de usuarios y elementos a partir de datos de interacción de usuarios.
Merlin Systems: para combinar un modelo de recomendación basado en TensorFlow con otros elementos (por ejemplo, almacén de características, búsqueda RNA con Milvus) que se servirán con TIS.
Triton Inference Server: para la etapa de inferencia en la que se pasa un vector de características del usuario y se generan recomendaciones de productos.
Containerización: todo lo anterior está disponible a través de los contenedores que NVIDIA proporciona en el catálogo NGC. Hemos utilizado el contenedor Merlin TensorFlow 23.06 disponible aquí.
Milvus 2.3: para realizar indexaciones y consultas vectoriales aceleradas en la GPU.
Milvus 2.2.11: igual que el anterior, pero para hacerlo en CPU.
Pymilvus SDK: para conectarse al servidor Milvus, crear índices de bases de datos vectoriales y ejecutar consultas a través de una interfaz Python.
Feast: para guardar y recuperar atributos de usuarios y elementos en un almacén de características (de código abierto) como parte de nuestro proceso RecSys de extremo a extremo.
También se utilizan varias bibliotecas y marcos subyacentes. Por ejemplo, Merlin se basa en otras librerías de NVIDIA, como cuDF y Dask, ambas disponibles en RAPIDS cuDF. Del mismo modo, Milvus se basa en NVIDIA RAFT para las primitivas de aceleración de la GPU y en librerías modificadas como HNSW y FAISS para la búsqueda.
Comprensión de las bases de datos vectoriales y Milvus
El vecino más cercano aproximado (RNA ) es una funcionalidad que las bases de datos relacionales no pueden manejar. Las bases de datos relacionales están diseñadas para manejar datos tabulares con estructuras predefinidas y valores directamente comparables. Los índices de las bases de datos relacionales se basan en esto para comparar datos y crear estructuras que aprovechen la ventaja de saber si cada valor es menor o mayor que el otro. Los vectores incrustados no pueden compararse directamente entre sí de este modo, ya que necesitamos saber qué representa cada valor del vector. No se puede decir si un vector es necesariamente menor que el otro. Lo único que podemos hacer es calcular la distancia entre los dos vectores. Si la distancia entre dos vectores es pequeña, podemos suponer que las características que representan son similares, y si es grande, podemos suponer que los datos que representan son más diferentes. Sin embargo, estos índices eficientes tienen un coste: calcular la distancia entre dos vectores es costoso desde el punto de vista computacional, y los índices vectoriales no son fácilmente adaptables y a veces no son modificables. Debido a estas dos limitaciones, la integración de estos índices es más compleja en las bases de datos relacionales, por lo que se necesitan bases de datos vectoriales creadas específicamente.
Milvus se creó para resolver los problemas a los que se enfrentan las bases de datos relacionales con vectores y se diseñó desde cero para manejar estos vectores incrustados y sus índices a gran escala. Para cumplir el distintivo de "nativo de la nube", Milvus separa la computación y el almacenamiento y las distintas tareas informáticas: la consulta, la gestión de datos y la indexación. Los usuarios pueden escalar cada parte de la base de datos para gestionar otros casos de uso, ya sea de inserción de datos o de búsqueda. Si hay una gran afluencia de solicitudes de inserción, el usuario puede escalar temporalmente los nodos de indexación horizontal y verticalmente para gestionar la ingestión. Del mismo modo, si no se están ingiriendo datos, pero hay muchas búsquedas, el usuario puede reducir los nodos de índice y, en su lugar, escalar los nodos de consulta para obtener un mayor rendimiento. Este diseño del sistema (véase la Figura 2) nos obligó a pensar en computación paralela, lo que dio como resultado un sistema optimizado para computación con muchas puertas abiertas para nuevas optimizaciones.
Figura 2. Diseño del sistema Milvus Diseño del sistema Milvus
Milvus también utiliza muchas bibliotecas de indexación de última generación para ofrecer a los usuarios tanta personalización para su sistema como sea posible. Las mejora añadiendo la capacidad de manejar operaciones CRUD, datos en flujo y filtrado. Más adelante analizaremos en qué se diferencian estos índices y cuáles son los pros y los contras de cada uno.
Ejemplo de solución: integración de Milvus y Merlin
La solución de ejemplo que presentamos aquí demuestra la integración de Milvus con Merlin en la fase de recuperación de elementos (cuando se recuperan los k elementos más relevantes mediante una búsqueda RNA). Utilizamos un conjunto de datos reales de un desafío RecSys, descrito a continuación. Entrenamos un modelo de aprendizaje profundo Two-Tower que aprende incrustaciones vectoriales para usuarios y elementos. En esta sección también se describe nuestro trabajo de evaluación comparativa, incluidas las métricas que recopilamos y la gama de parámetros que utilizamos.
Nuestro enfoque incluye
Introducción y preprocesamiento de datos
Entrenamiento del modelo de aprendizaje profundo Two-Tower
Creación del índice Milvus
Búsqueda de similitud Milvus
Describimos brevemente cada paso y remitimos al lector a nuestros cuadernos para más detalles.
Conjunto de datos
YOOCHOOSE GmbH proporciona el conjunto de datos que utilizamos en este estudio de integración y evaluación comparativa para el desafío RecSys 2015 y está disponible en Kaggle. Contiene eventos de clic/compra de usuarios de un minorista online europeo con atributos como un ID de sesión, una marca de tiempo, un ID de artículo asociado al clic/compra y una categoría de artículo, disponibles en el archivo yoochoose-clicks.dat. Las sesiones son independientes y no hay indicios de usuarios que regresan, por lo que tratamos cada sesión como perteneciente a un usuario distinto. El conjunto de datos tiene 9.249.729 sesiones únicas (usuarios) y 52.739 artículos únicos.
Captura y preprocesamiento de datos
La herramienta que utilizamos para el preprocesamiento de datos es NVTabular, un componente de Merlin de ingeniería de características y preprocesamiento altamente escalable y acelerado en la GPU. Utilizamos NVTabular para leer los datos en la memoria de la GPU, reorganizar las características según sea necesario, exportar a archivos parquet y crear una división de entrenamiento-validación para el entrenamiento. El resultado son 7.305.761 usuarios únicos y 49.008 elementos únicos con los que entrenar. También categorizamos cada columna y sus valores en enteros. El conjunto de datos ya está listo para el entrenamiento con el modelo de dos torres.
Entrenamiento del modelo
Utilizamos el modelo de aprendizaje profundo Two-Tower para entrenar y generar incrustaciones de usuarios y elementos, que posteriormente se utilizan en la indexación y consulta de vectores. Después de entrenar el modelo, podemos extraer las incrustaciones de usuario y elemento aprendidas.
Los dos pasos siguientes son opcionales: un modelo DLRM entrenado para clasificar los elementos recuperados con fines de recomendación y un almacén de características utilizado (en este caso, Feast) para almacenar y recuperar características de usuarios y elementos. Los incluimos para completar el flujo de trabajo en varias fases.
Por último, exportamos las incrustaciones de usuarios e ítems a archivos parquet, que pueden recargarse posteriormente para crear un índice vectorial Milvus.
Creación y consulta del índice Milvus
Milvus facilita la indexación vectorial y la búsqueda de similitud a través de un "servidor" lanzado en la máquina de inferencia. En nuestro cuaderno nº 2, lo configuramos instalando mediante pip el servidor Milvus y Pymilvus, e iniciando el servidor con su puerto de escucha predeterminado. A continuación, demostramos la creación de un índice sencillo (IVF_FLAT) y la consulta del mismo mediante las funciones setup_milvus
y query_milvus
, respectivamente.
Pruebas de rendimiento
Hemos diseñado dos pruebas comparativas para demostrar la conveniencia de utilizar una biblioteca de indexación/búsqueda vectorial rápida y eficiente como Milvus.
Usando Milvus para construir índices vectoriales con los dos conjuntos de incrustaciones que generamos: 1) incrustaciones de usuarios para 7,3 millones de usuarios únicos, divididos en un 85% para el conjunto de entrenamiento (para indexación) y un 15% para el conjunto de prueba (para consulta), y 2) incrustaciones de artículos para 49.000 productos (con una división 50-50 entre entrenamiento y prueba). Esta prueba se realiza de forma independiente para cada conjunto de datos vectoriales, y los resultados se presentan por separado.
Utilización de Milvus para crear un índice vectorial para el conjunto de datos de 49.000 elementos incrustados y consulta de los 7,3 millones de usuarios únicos en este índice para la búsqueda de similitudes.
En estas pruebas, utilizamos los algoritmos de indexación IVFPQ y HNSW ejecutados en GPU y CPU, junto con varias combinaciones de parámetros. Los detalles están disponibles aquí.
El equilibrio entre la calidad y el rendimiento de la búsqueda es un aspecto importante del rendimiento, especialmente en un entorno de producción. Milvus permite un control total sobre los parámetros de indexación para explorar este compromiso en un caso de uso determinado y lograr mejores resultados de búsqueda con la verdad sobre el terreno. Esto puede suponer un aumento del coste computacional en forma de reducción de la tasa de rendimiento o de las consultas por segundo (QPS). Medimos la calidad de la búsqueda RNA con una métrica de recuperación y proporcionamos curvas QPS-recall que demuestran el compromiso. De este modo, se puede decidir cuál es el nivel aceptable de calidad de la búsqueda en función de los recursos informáticos o de los requisitos de latencia/rendimiento de la empresa.
Obsérvese también el tamaño del lote de consulta (nq) utilizado en nuestras pruebas comparativas. Esto resulta útil en flujos de trabajo en los que se envían varias solicitudes simultáneas a la inferencia (por ejemplo, recomendaciones fuera de línea solicitadas y enviadas a una lista de destinatarios de correo electrónico o recomendaciones en línea creadas agrupando las solicitudes concurrentes que llegan y procesándolas todas a la vez). Dependiendo del caso de uso, TIS también puede ayudar a procesar estas solicitudes por lotes.
Resultados
A continuación presentamos los resultados de los tres conjuntos de pruebas tanto en CPU como en GPU, utilizando los tipos de índice HNSW (sólo CPU) e IVF_PQ (CPU y GPU) implementados por Milvus.
Búsqueda de similitud vectorial de ítems frente a ítems
Con este conjunto de datos más pequeño, cada ejecución para una combinación de parámetros determinada toma el 50% de los vectores de artículos como vectores de consulta y consulta los 100 vectores más similares del resto. HNSW e IVF_PQ consiguen una alta recuperación con los parámetros probados, en el intervalo 0,958-1,0 y 0,665-0,997, respectivamente. Este resultado sugiere que HNSW obtiene mejores resultados en cuanto a recall, pero IVF_PQ con ajustes pequeños de nlist produce un recall muy comparable. También hay que tener en cuenta que los valores de recuperación pueden variar mucho en función de los parámetros de indexación y consulta. Los valores que presentamos se han obtenido tras una experimentación preliminar con rangos de parámetros generales y una ampliación de un subconjunto selecto.
El tiempo total de ejecución de todas las consultas en la CPU con HNSW para una combinación de parámetros dada oscila entre 5,22 y 5,33 s (más rápido a medida que aumenta m, relativamente invariable con ef) y con IVF_PQ entre 13,67 y 14,67 s (más lento a medida que aumentan nlist y nprobe). La aceleración en la GPU tiene un efecto notable, como puede verse en la Figura 3.
La Figura 3 muestra la relación entre recuperación y rendimiento en todas las ejecuciones realizadas en CPU y GPU con este pequeño conjunto de datos utilizando IVF_PQ. Se observa que la GPU proporciona un incremento de velocidad de entre 4 y 15 veces en todas las combinaciones de parámetros probadas (mayor a medida que aumenta nprobe). Esto se calcula tomando la relación entre los QPS de la GPU y los QPS de la CPU para cada combinación de parámetros. En general, este conjunto de datos supone un pequeño reto para la CPU o la GPU y muestra perspectivas de mayor aceleración con conjuntos de datos más grandes, como se explica a continuación.
Figura 3. Aceleración de la GPU con Milvus Aceleración en GPU con el algoritmo IVF_PQ de Milvus ejecutado en la GPU NVIDIA A100 (búsqueda de similitud entre elementos)
Búsqueda vectorial de similitudes entre usuarios
Con el segundo conjunto de datos, mucho mayor (7,3 millones de usuarios), reservamos el 85% (~6,2 millones) de los vectores como "entrenamiento" (el conjunto de vectores que se indexarán) y el 15% restante (~1,1 millones) como "prueba" o conjunto de vectores de consulta. Los resultados de HNSW e IVF_PQ son excepcionalmente buenos en este caso, con valores de recuperación de 0,884-1,0 y 0,922-0,999, respectivamente. Sin embargo, son mucho más exigentes desde el punto de vista computacional, especialmente con IVF_PQ en la CPU. El tiempo total de ejecución de todas las consultas en la CPU con HNSW oscila entre 279,89 y 295,56 s y con IVF_PQ entre 3082,67 y 10932,33 s. Obsérvese que estos tiempos de consulta son acumulativos para 1,1 millones de vectores consultados, por lo que puede decirse que una sola consulta contra el índice sigue siendo muy rápida.
Sin embargo, las consultas basadas en la CPU pueden no ser viables si el servidor de inferencia espera muchos miles de peticiones simultáneas para ejecutar consultas contra un inventario de millones de elementos.
La GPU A100 proporciona una velocidad de 37x a 91x (con una media de 76,1x) en todas las combinaciones de parámetros con IVF_PQ en términos de rendimiento (QPS), como se muestra en la Figura 4. Esto es coherente con lo observado con la GPU A100. Esto concuerda con lo observado con el pequeño conjunto de datos, lo que sugiere que el rendimiento de la GPU se escala razonablemente bien utilizando Milvus con millones de vectores de incrustación.
Figura 4. Aumento de la velocidad de la GPU con Milvus Aceleración de la GPU con el algoritmo IVF_PQ de Milvus ejecutado en la GPU NVIDIA A100 (búsqueda de similitud usuario-usuario)
La siguiente Figura 5 muestra en detalle la compensación recall-QPS para todas las combinaciones de parámetros probadas en CPU y GPU con IVF_PQ. Cada conjunto de puntos (arriba para la GPU, abajo para la CPU) de este gráfico representa la compensación que se produce al cambiar los parámetros de indexación/consulta de vectores para conseguir una mayor recuperación a expensas de un menor rendimiento. Obsérvese la considerable pérdida de QPS en el caso de la GPU cuando se intentan alcanzar mayores niveles de recuperación.
Figura 5. Equilibrio entre recuperación y rendimiento para todas las combinaciones de parámetros probadas en CPU y GPU con IVF_PQ (usuarios frente a usuarios)
Usuarios frente a elementos Búsqueda por similitud vectorial
Por último, consideramos otro caso de uso realista en el que se consultan vectores de usuarios frente a vectores de elementos (como se demostró en el cuaderno 01). En este caso, se indexan 49.000 vectores de artículos y se consultan 7,3 millones de vectores de usuarios en busca de los 100 artículos más similares.
Aquí es donde las cosas se ponen interesantes porque la consulta de 7,3M en lotes de 1000 contra un índice de 49K elementos parece consumir mucho tiempo en la CPU tanto para HNSW como para IVF_PQ. La GPU parece manejar mejor este caso (véase la Figura 6). Los niveles de precisión más altos de IVF_PQ en la CPU cuando nlist = 100 se calculan en unos 86 minutos de media, pero varían significativamente a medida que aumenta el valor de nprobe (51 min. cuando nprobe = 5 frente a 128 min. cuando nprobe = 20). La GPU NVIDIA A100 acelera considerablemente el rendimiento en un factor de 4x a 17x (mayor velocidad a medida que aumenta nprobe). Recordemos que el algoritmo IVF_PQ, a través de su técnica de cuantización, también reduce la huella de memoria y proporciona una solución de búsqueda de RNA computacionalmente viable combinada con la aceleración de la GPU.
Figura 6. Aceleración de la GPU con Milvus Aceleración de la GPU con el algoritmo IVF_PQ de Milvus ejecutado en la GPU NVIDIA A100 (búsqueda de similitudes entre elementos de usuario)
Al igual que en la Figura 5, en la Figura 7 se muestra la relación entre recuperación y rendimiento para todas las combinaciones de parámetros probadas con IVF_PQ. En este caso, todavía se puede ver cómo es posible que haya que renunciar ligeramente a cierta precisión en la búsqueda RNA en favor de un mayor rendimiento, aunque las diferencias son mucho menos notables, especialmente en el caso de las ejecuciones en la GPU. Esto sugiere que se pueden esperar niveles relativamente altos de rendimiento computacional con la GPU y, al mismo tiempo, conseguir una alta recuperación.
Figura 7. Equilibrio entre recuperación y rendimiento para todas las combinaciones de parámetros probadas en CPU y GPU con IVF_PQ (usuarios frente a elementos)
Conclusión
Si has llegado hasta aquí, nos gustaría compartir contigo algunas observaciones finales. Queremos recordarte que la complejidad y la naturaleza multietapa de Recsys requieren rendimiento y eficiencia en cada paso. Esperamos que este blog te haya dado razones de peso para considerar el uso de dos funciones críticas en tus pipelines RecSys:
La librería Merlin Systems de NVIDIA te permite conectar fácilmente Milvus, un eficiente motor de búsqueda vectorial acelerado en la GPU.
Utilice la GPU para acelerar los cálculos de indexación de bases de datos vectoriales y búsqueda de RNA con tecnologías como RAPIDS RAFT.
Estos resultados sugieren que la integración Merlin-Milvus presentada ofrece un alto rendimiento y es mucho menos compleja que otras opciones para el entrenamiento y la inferencia. Además, ambos marcos de trabajo se desarrollan activamente y en cada versión se añaden muchas funciones nuevas (por ejemplo, los nuevos índices de bases de datos vectoriales acelerados por GPU de Milvus). El hecho de que la búsqueda de similitudes vectoriales sea un componente crucial en diversos flujos de trabajo, como la visión por computador, el modelado de grandes lenguajes y los sistemas de recomendación, hace que este esfuerzo merezca aún más la pena.
Para terminar, nos gustaría dar las gracias a todos los miembros de los equipos de Zilliz/Milvus y Merlin y de RAFT que han contribuido a la elaboración de este trabajo y de esta entrada de blog. Esperamos tener noticias suyas si tiene la oportunidad de implantar Merlin y Milvus en sus recsys u otros flujos de trabajo.
- Introducción
- Los retos de los recomendadores
- Pilas tecnológicas para la solución
- Comprensión de las bases de datos vectoriales y Milvus
- Ejemplo de solución: integración de Milvus y Merlin
- Pruebas de rendimiento
- Conclusión
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word