Calcule fácilmente incrustaciones de clips y cree un sistema clip retrieval con ellas. Se pueden procesar 100 millones de incrustaciones de texto e imágenes en 20 horas utilizando un 3080.
De principio a fin, esto hace posible construir un sistema de búsqueda semántica simple. ¿Está interesado en aprender sobre la búsqueda semántica en general? Puedes leer mi publicación mediana sobre el tema.
Consulte también laion5B y la búsqueda semántica a escala de miles de millones para leer más sobre cómo hacer esta escala a miles de millones de muestras.
Si cree en la creación de herramientas reutilizables para que los datos sean fáciles de usar para ML y le gustaría contribuir, únase al chat de DataToML.
instalación de pip recuperación de clip
Si le interesa ejecutar el índice laion5B, consulte este documento
ClipClient
permite la consulta remota de un backend de recuperación de clips a través de Python.
Consulte ClipClient
: introducción a Notebook para ver un ejemplo de cuaderno Jupyter.
Durante la inicialización puede especificar algunos parámetros:
backend_url
: la URL del backend. (requerido)indice_name
: especifique el nombre del índice que desea utilizar. (requerido)aesthetic_score
: la puntuación estética según la clasificación del predictor estético. El valor predeterminado es 9
.use_mclip
: si se debe utilizar una versión multilingüe de CLIP. El valor predeterminado es False
.aesthetic_weight
: el peso de la puntuación estética. El valor predeterminado es 0.5
modality
: busca sobre imagen o texto en el índice, uno de Multimodal.IMAGE
o Multimodal.TEXT
. El valor predeterminado es Multimodal.IMAGE
.num_images
: la cantidad de imágenes que se devolverán desde la API. El valor predeterminado es 40
.deduplicate
: si se debe deduplicar el resultado mediante la incrustación de imágenes. El valor predeterminado es verdadero.use_safety_model
: si se deben eliminar imágenes no seguras. El valor predeterminado es verdadero.use_violence_detector
: si se deben eliminar imágenes con violencia. El valor predeterminado es verdadero.Por ejemplo, para consultar el backend alojado de Laion5B con los parámetros predeterminados:
from clip_retrieval . clip_client import ClipClient , Modality
client = ClipClient ( url = "https://knn.laion.ai/knn-service" , indice_name = "laion5B-L-14" )
Puede encontrar imágenes con subtítulos similares al texto que proporciona.
results = client . query ( text = "an image of a cat" )
results [ 0 ]
> { 'url' : 'https://example.com/kitten.jpg' , 'caption' : 'an image of a kitten' , 'id' : 14 , 'similarity' : 0.2367108941078186 }
También puede encontrar imágenes con subtítulos similares a la imagen que proporciona. Las imágenes se pueden pasar a través de una ruta local o una URL.
cat_results = client . query ( image = "cat.jpg" )
dog_results = client . query ( image = "https://example.com/dog.jpg" )
También puede encontrar imágenes con subtítulos similares a un clip incrustado que usted proporcione.
cat_results = client . query ( embedding_input = cat_embedding )
Para mejorar un conjunto de datos existente con pares de texto/imagen similares, puede consultar un directorio de imágenes y combinar los resultados.
all_results = [ result for result in [ client . query ( image = image ) for image in os . listdir ( "my-images" )]]
with open ( "search-results.json" , "w" ) as f :
json . dump ( all_results , f )
Puede crear un conjunto de datos utilizando los resultados json guardados y la herramienta img2dataset
.
img2dataset " search-results.json "
--input_format= " json "
--output_folder= " knn_search_dataset "
--caption_col= " caption "
Primero elija un conjunto de datos de URL de imágenes y títulos (ejemplos) y luego ejecute:
Es posible que desees ejecutar export CUDA_VISIBLE_DEVICES=
para evitar usar tu GPU si no tiene suficiente VRAM.
wget https://github.com/rom1504/img2dataset/raw/main/tests/test_files/test_1000.parquet
clip-retrieval end2end test_1000.parquet /tmp/my_output
Luego ve a http://localhost:1234 y disfruta buscando entre tus imágenes.
Utilice --run_back False
si no desea ejecutar el backend
Obtenga algunas imágenes en una example_folder
, por ejemplo haciendo:
pip install img2dataset
echo 'https://placekitten.com/200/305' >> myimglist.txt
echo 'https://placekitten.com/200/304' >> myimglist.txt
echo 'https://placekitten.com/200/303' >> myimglist.txt
img2dataset --url_list=myimglist.txt --output_folder=image_folder --thread_count=64 --image_size=256
También puedes colocar archivos de texto con los mismos nombres que las imágenes en esa carpeta, para obtener las incrustaciones de texto.
Luego ejecute clip-retrieval inference --input_dataset image_folder --output_folder embeddings_folder
La carpeta de salida contendrá:
Esto se escala a millones de muestras. A 1400 muestras/s de un 3080, se pueden procesar 10 millones de muestras en 2 h.
clip_inference convierte un conjunto de texto+imagen en incrustaciones de clips
"open_clip:ViT-B-32/laion2b_s34b_b79k"
para usar open_clip o "hf_clip:patrickjohncyh/fashion-clip"
para usar el modelo de clip de cara abrazada. DeepSparse es un tiempo de ejecución de inferencia para una inferencia rápida de modelos dispersos en CPU. Hay un backend disponible dentro de la recuperación de clips instalándolo con pip install deepsparse-nightly[clip]
y especificando un clip_model
con un "nm:"
antepuesto, como "nm:neuralmagic/CLIP-ViT-B-32-256x256-DataComp-s34B-b86K-quant-ds"
o "nm:mgoin/CLIP-ViT-B-32-laion2b_s34b_b79k-ds"
.
Si desea tener más control sobre cómo se ejecuta la inferencia, puede crear y llamar trabajadores directamente usando clip-retrieval inference.worker
Uso de ejemplo:
clip-retrieval inference.worker
--tasks= " [0] "
--input_dataset= " input/folder/{000000..000100}.tar "
--output_folder= " example/path "
--input_format= " webdataset "
--output_partition_count= " 1 "
Al hacerlo, se invocará a un único trabajador al que se le puede indicar que se centre en un subconjunto específico de input_dataset
. Ese trabajador procesará secuencialmente las tasks
que se le pasen. Aquí, tasks
es una lista de partition_id
de las que este trabajador será responsable.
Para calcular manualmente el número de tareas, utilice la siguiente fórmula: number_samples / wds_number_file_per_input_file
.
La API es muy similar a clip-retrieval inference
con algunos cambios menores:
partition_id
que este trabajador es responsable de calcular. ( requerido )"open_clip:ViT-B-32-quickgelu"
para usar open_clip o "hf_clip:patrickjohncyh/fashion-clip"
para usar el modelo de clip de cara abrazada.Nota : El trabajador no acepta los siguientes argumentos
- write_batch_size Escribir tamaño de lote (predeterminado 10**6 )
- Distribution_strategy elige cómo distribuir el trabajo, consulta la sección de distribución para obtener más detalles ( secuencial predeterminado)
- wds_number_file_per_input_file estimación del número de muestras por tar si se usa wds y no se especifica output_partition_count (predeterminado 10000 )
- cualquiera de los argumentos de SLURM
Ejemplo de consulta hdfs usando el formato webdataset: `clip_inference --input_dataset "pipe:hdfs dfs -cat /myfolder/webdataset/{00000..00010}.tar" --output_folder "hdfs://myfolder/embeddings" --input_format webdataset
`clip_inference --input_dataset "pipe:aws s3 cp --quiet s3://myfolder/webdataset/{00000..00010}.tar -" --output_folder "s3://myfolder/embeddings" --input_format webdataset
Para ejecutar esto en múltiples nodos (y múltiples GPU), consulte el tutorial en docs/distributed_clip_inference.md
El índice de clip toma como entrada la salida de la inferencia del clip y crea un índice a partir de ella usando autofaiss
clip-retrieval index --embeddings_folder embeddings_folder --index_folder index_folder
--max_index_memory_usage "16G"
permite configurar la cantidad de RAM que consumirá el índice. Más RAM, mejor recuperación de knn ( 4G
predeterminado).--current_memory_available 24G
permite controlar cuánta RAM se utiliza durante el proceso de creación (predeterminado 16G
).--image_subfolder "img_emb"
permite especificar una subcarpeta para las incrustaciones de imágenes que se concatena con la opción --embeddings_folder
( img_emb
predeterminada).--text_subfolder "text_emb"
permite especificar una subcarpeta para las incrustaciones de texto que se concatena con la opción --embeddings_folder
( text_emb
predeterminado).--copy_metadata True
permite elegir si copiar metadatos o no al final del proceso (Predeterminado True
).--nb_cores 8
permite controlar la cantidad de subprocesos (el valor predeterminado None
, que utilizará todos los núcleos).El resultado es una carpeta que contiene:
Gracias a autofaiss y faiss, esto escala a cientos de millones de muestras en unas pocas horas.
Es posible que desee elegir cuidadosamente cuánta memoria usar para su índice para maximizar la recuperación de knn. El colab de selección de índice autofaiss puede ayudar junto con el comando autofaiss score_index
para verificar la recuperación de su índice. En general, los índices que utilizan más memoria obtienen una mejor recuperación y, por lo tanto, están más cerca de un knn ingenuo (lento).
Una vez calculadas las incrustaciones, es posible que desee filtrar los datos mediante una consulta específica. Para eso, puede ejecutar clip-retrieval filter --query "cat" --output_folder "cat/" --indice_folder "indice_folder"
Copiará las 100 mejores imágenes para esta consulta en la carpeta de salida. Usar --num_results
o --threshold
puede ser útil para refinar el filtro
Gracias al rápido índice knn, esto puede ejecutarse en tiempo real (<10 ms) para valores K grandes (100000) y en minutos para valores K muy grandes.
Este script funciona para conjuntos de datos pequeños. Para los más grandes, consulte [notebook/simple_filter.ipynb].
Clip back es un backend de servicio knn simple. Si utiliza el mapeo de memoria hdf5 y faiss, solo usa la memoria utilizada por el clip, que es de 4 GB.
Ejecutar (output_folder es la salida del índice del clip)
echo ' {"example_index": "output_folder"} ' > indices_paths.json
clip-retrieval back --port 1234 --indices-paths indices_paths.json
Opciones:
--use_jit True
usa jit para el modelo de clip--clip_model "ViT-B/32"
permite elegir el modelo de clip a utilizar. Prefijo "open_clip:"
para usar un modelo open_clip.--enable_mclip_option True
carga el modelo mclip, lo que permite realizar búsquedas en cualquier idioma.--columns_to_return='["url", "image_path", "caption", "NSFW"]
le permite especificar qué columnas deben recuperarse de los metadatos y devolverse por el backend. Es útil especificar menos en el caso del almacenamiento en caché hdf5 para acelerar las consultas.--enable_faiss_memory_mapping=True
para usar un índice con mapeo de memoria. Eso reduce el uso de memoria a cero.--enable_hdf5 True
para habilitar el almacenamiento en caché hdf5 para los metadatos. El almacenamiento en caché HDF5 permite utilizar los metadatos casi sin uso de memoria.--use_arrow True
permite usar flecha en lugar de hdf5. Debe usarse junto con clip_back_prepro para conjuntos de datos muy grandes (miles de millones)--reorder_metadata_by_ivf_index True
aprovecha la propiedad de localidad de datos de los resultados de índices knn ivf: ordena la recopilación de metadatos en orden de los grupos de IVF. Eso hace posible tener una recuperación de metadatos mucho más rápida, ya que las lecturas acceden a algunas partes de los metadatos, en su mayoría secuenciales, en lugar de muchas partes no secuenciales. En la práctica, eso significa poder recuperar 1 millón de elementos en 1 segundo, mientras que solo se pueden recuperar 1000 elementos en 1 segundo sin este método. Esto ordenará los metadatos utilizando el primer índice de imagen.--provide_safety_model True
descargará y cargará automáticamente un modelo de seguridad. Necesita pip install autokeras
para que esto funcione.--provide_violence_detector True
cargará un detector de violencia, papel--provide_aesthetic_embeddings True
cargará las incrustaciones estéticas y permitirá a los usuarios hacer que la consulta se mueva hacia un punto más agradable del espacio del clip.Estas opciones también se pueden proporcionar en el archivo de configuración para tener diferentes opciones para cada índice. Ejemplo:
{
"laion5B" : {
"indice_folder" : " /mnt/laion5B/prepared_data " ,
"provide_safety_model" : true ,
"enable_faiss_memory_mapping" : true ,
"use_arrow" : true ,
"enable_hdf5" : false ,
"reorder_metadata_by_ivf_index" : false ,
"columns_to_return" : [ " url " , " caption " ],
"clip_model" : " ViT-L/14 " ,
"enable_mclip_option" : false
},
"laion_400m" : {
"indice_folder" : " /mnt/laion400M/index100 " ,
"provide_safety_model" : true ,
"enable_faiss_memory_mapping" : true ,
"enable_hdf5" : true ,
"use_arrow" : false ,
"reorder_metadata_by_ivf_index" : true ,
"enable_mclip_option" : true ,
"clip_model" : " ViT-B/32 "
}
}
hdf5 o el almacenamiento en caché de flechas es una buena idea si:
En este punto, tiene un servidor de matraz simple ejecutándose en el puerto 1234 y que puede responder estas consultas:
/indices-list
-> devolver una lista de índices/knn-service
que toma como entrada: {
"text" : "a text query" ,
"image" : "a base64 image" ,
"image_url" : "http://some-url.com/a.jpg" ,
"modality" : "image" , // image or text index to use
"num_images" : 4 , // number of output images
"indice_name" : "example_index" ,
"num_result_ids" : 4 // optional, if specified fetch this number of results in total but only num_images with metadata
}
texto, imagen e image_url son mutuamente excluyentes y devuelven:
[
{
"image" : "base 64 of an image" ,
"text" : "some result text" ,
"id" : 543
} ,
{
"image" : "base 64 of an image" ,
"text" : "some result text" ,
"id" : 782
}
]
Cada objeto también puede contener un campo de URL si los metadatos lo proporcionan.
La identificación es la posición del elemento en el índice. Puede usarse para consultar metadatos con el punto final /metadata:
{
"indice_name" : "example_index" ,
"ids" : [ 543 , 782 ]
}
que devuelve:
{
"image" : "base 64 of an image" ,
"text" : "some result text"
// any other key available in the metadata and specified in columns_to_return cli option
}
El argumento num_result_ids
de /knn-service
y /metadata
se puede usar juntos para realizar consultas knn grandes y luego recuperar los metadatos solo cuando sea necesario. Tiene sentido hacerlo ya que la búsqueda de knn puede ser muy eficiente gracias a la fuerte localidad de referencia del índice knn IVF, lo que hace que sea rápido hacer knn con una K grande, mientras que la implementación actual de metadatos en disco (hdf5) no tiene eso. propiedad y, por lo tanto, no puede manejar la recuperación rápida de una gran cantidad de elementos aleatorios. En particular, esto se puede utilizar para implementar el desplazamiento infinito en una interfaz.
De forma predeterminada, el backend también expondrá una interfaz. De forma predeterminada, esa interfaz llegará a este backend; sin embargo, es posible que deba especificar si esto sucede a través de http o https; en este caso, use la opción --default_backend
para especificar la URL del backend. --url_column
permite especificar el nombre de la URL de la columna para el frente
Este backend tiene una latencia de 50 ms si utiliza índices y metadatos asignados en memoria. El rendimiento es de aproximadamente 20 consultas/s. Para un alto rendimiento, se requiere el uso de un servidor grpc, así como una GPU para una inferencia rápida de clips; desactivar las opciones de mapeo de memoria también puede acelerar las solicitudes, a costa de un alto uso de RAM.
Este backend también expone un punto final prometheus /metrics
así como un resumen legible por humanos en /metrics-summary
. Esto se puede usar (opcionalmente) para configurar un panel de grafana para monitoreo:
Se puede ver en este panel que la parte más lenta de cualquier llamada es buscar la imagen por su URL en el caso de la búsqueda de la URL de la imagen, lo que demora hasta 300 ms. Para consultas de texto o de imágenes, la latencia es de aproximadamente 50 ms. A continuación se muestra un ejemplo de resultado en el resumen de métricas:
Among 20.0 calls to the knn end point with an average latency of 0.1889s per request, the step costs are (in order):
name description calls average proportion
0 download_time Time spent downloading an url 6 0.3215s 170.2%
1 metadata_get_time Time spent retrieving metadata 20 0.0415s 21.9%
2 knn_index_time Time spent doing a knn on the index 20 0.0267s 14.1%
3 image_clip_inference_time Time spent doing a image clip inference 6 0.0206s 10.9%
4 text_clip_inference_time Time spent doing a text clip inference 14 0.0186s 9.8%
5 image_prepro_time Time spent doing the image preprocessing 6 0.0097s 5.2%
6 text_prepro_time Time spent doing the text preprocessing 14 0.0020s 1.0%
Clip front es una interfaz de usuario simple que se conecta para recortar y mostrar los resultados. Puedes usarlo en la interfaz de usuario de recuperación de clips.
O puedes ejecutarlo tú mismo con:
npm install -g clip-retrieval-front
clip-retrieval-front 3005
También puede ejecutarlo con clip-retrieval front
o posterior desde el paquete Python.
Para desarrollarlo, vaya al frente y ejecute npm install
y luego npm start
.
Ya sea localmente o en gitpod ( export PIP_USER=false
allí)
Configurar un entorno virtual:
python3 -m venv .env
source .env/bin/activate
pip install -e .
para ejecutar pruebas:
pip install -r requirements-test.txt
entonces
make lint
make test
Puedes usar make black
para reformatear el código.
python -m pytest -x -s -v tests -k "test_runner"
para ejecutar una prueba específica
Si desea utilizar el frontend a través del backend o frontend de Python, ejecute
cd front
npm install
npm run build
cd ..
pip install -e .
@misc{beaumont-2022-clip-retrieval,
author = {Romain Beaumont},
title = { clip retrieval : Easily compute clip embeddings and build a clip retrieval system with them},
year = {2022},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {url{https://github.com/rom1504/clip-retrieval}}
}