Elasticsearch está introduciendo un nuevo tipo de vector en 8.6. Este vector tiene dimensiones enteras de 8 bits, donde cada dimensión tiene un rango de [-128, 127]. Es 4 veces más pequeño que el vector actual con dimensiones flotantes de 32 bits, lo que puede resultar en un ahorro sustancial de espacio.
Puede comenzar a indexar estos vectores más pequeños de 8 bits ahora mismo agregando el parámetro element_type con el valor de byte a sus asignaciones de vectores, similar al ejemplo a continuación.
{n "mappings": {n "properties": {n "my_vector": {n "type": "dense_vector",n "element_type": "byte",n "dims": 3,n "index": true,n "similarity": "dot_product"n }n }n }n}
Lee mas
Pero, ¿qué pasa si las dimensiones de sus vectores existentes no encajan en este tipo más pequeño? Entonces podemos usar el proceso de cuantización para hacer que encajen, ¡a menudo con solo una pequeña pérdida de precisión!
Cuantifiquemos
Comencemos definiendo la cuantización. La cuantificación es el proceso de tomar un conjunto más grande de valores y asignarlos a un conjunto más pequeño de valores. Más específicamente, en nuestro caso, esto sería tomar el rango de un flotante de 32 bits y asignarlo al rango de un entero de 8 bits para cada dimensión en un vector. (Esto no debe confundirse con la reducción dimensional, que es un tema diferente. Esto solo reduce el rango de valores para las dimensiones existentes).
Esto lleva a dos preguntas más. ¿Cuál es el rango real de nuestros vectores flotantes de 32 bits? ¿Y qué función debemos usar para hacer el mapeo? Las respuestas varían significativamente según el caso de uso.
Como ejemplo, una de las formas más simples de cuantificación es tomar las dimensiones de los vectores de 32 bits normalizados y asignarlos linealmente al rango completo de las dimensiones de los vectores de 8 bits. Usando Python, esto sería algo como lo siguiente:
import numpy as npnimport typing as tnndef quantize_embeddings(text_and_embeddings: t.List[t.Mapping[str, t.Any]]) -> t.List[t.Mapping[str, t.Any]]:n quantized_embeddings = np.array([x['embedding'] for x in nquery_and_embeddings])n quantized_embeddings = (quantized_embeddings * 128)n quantized_embeddings = quantized_embeddings.clip(-128, n127).astype(int).tolist()n return [dict(item, **{'embedding': embedding}) for (item, nembedding) in zip(text_and_embeddings, quantized_embeddings)]
Lee mas
Sin embargo, este es solo un ejemplo. Hay muchas otras funciones de cuantización útiles. Para su caso de uso específico, es importante evaluar qué método de cuantificación le dará los mejores resultados en relación con el equilibrio entre reducción de espacio, relevancia y recuperación.
Algunos números del mundo real
Los vectores de 8 bits y la cuantificación son geniales y todo, pero ¿realmente reducen el espacio en un caso de uso del mundo real? La respuesta es inequívocamente ¡SÍ! Y sustancialmente. Todo esto mientras continúan dando buenos resultados sin dañar la relevancia y el recuerdo. Elasticsearch incluso tiene todas las herramientas que necesita para hacer esa evaluación usted mismo con nuestra API de evaluación de clasificación .
Ahora, veamos algunos números generados a partir de un ejemplo del mundo real con la siguiente configuración:
Luego hacemos que suceda algo de magia y recolectamos resultados basados en esta configuración:
categoría | Tiempo de respuesta mediano de kNN | Tiempo de respuesta exacto medio | Recuperar@100 | NDCG@10 | Tamaño total del índice (1p, 1r) |
byte | 32ms | 1072ms | 0.79 | 0.38 | 5.8gb |
flotar | 36ms | 1530ms | 0.79 | 0.38 | 16,4 gb |
% Reducción | 11% | 30% | 0% | 0% | 64% |
Y nuestros resultados se ven fantásticos. Desglosemos cada uno.
Los vectores de bytes están listos para funcionar como parte de 8.6.