Calcule facilmente incorporações de clipes e crie um sistema clip retrieval com eles. Incorporações de 100 milhões de texto+imagem podem ser processadas em 20h usando um 3080.
De ponta a ponta, isso torna possível construir um sistema de busca semântica simples. Interessado em aprender sobre pesquisa semântica em geral? Você pode ler minha postagem média sobre o assunto.
Veja também laion5B e pesquisa semântica em escala de bilhões para ler mais sobre como fazer essa escala para bilhões de amostras.
Se você acredita em criar ferramentas reutilizáveis para facilitar o uso de dados para ML e gostaria de contribuir, entre no chat do DataToML.
pip install recuperação de clipe
Se for do seu interesse executar o índice laion5B, consulte este documento
ClipClient
permite consulta remota de um back-end de recuperação de clipe via python.
Consulte ClipClient
- Introdução ao Notebook para obter um exemplo de notebook Jupyter.
Durante a inicialização você pode especificar alguns parâmetros:
backend_url
: a URL do back-end. (obrigatório)indice_name
: especifique o nome do índice que deseja usar. (obrigatório)aesthetic_score
: a pontuação estética avaliada pelo preditor estético. O padrão é 9
.use_mclip
: se deve usar uma versão multilíngue do CLIP. O padrão é False
.aesthetic_weight
: o peso da pontuação estética. O padrão é 0.5
modality
: pesquise imagem ou texto no índice, seja Multimodal.IMAGE
ou Multimodal.TEXT
. O padrão é Multimodal.IMAGE
.num_images
: o número de imagens a serem retornadas da API. O padrão é 40
.deduplicate
: se deseja desduplicar o resultado por incorporação de imagem. O padrão é verdadeiro.use_safety_model
: se deseja remover imagens inseguras. O padrão é verdadeiro.use_violence_detector
: Se deseja remover imagens com violência. O padrão é verdadeiro.Por exemplo, para consultar o backend hospedado para Laion5B com os parâmetros padrão:
from clip_retrieval . clip_client import ClipClient , Modality
client = ClipClient ( url = "https://knn.laion.ai/knn-service" , indice_name = "laion5B-L-14" )
Você pode encontrar imagens legendadas semelhantes ao texto fornecido.
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 }
Você também pode encontrar imagens legendadas semelhantes à imagem fornecida. As imagens podem ser passadas via caminho local ou URL.
cat_results = client . query ( image = "cat.jpg" )
dog_results = client . query ( image = "https://example.com/dog.jpg" )
Você também pode encontrar imagens legendadas semelhantes a uma incorporação de clipe que você fornece.
cat_results = client . query ( embedding_input = cat_embedding )
Para aprimorar um conjunto de dados existente com pares de texto/imagem semelhantes, você pode consultar um diretório de imagens e combinar os 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 )
Você pode criar um conjunto de dados usando os resultados JSON salvos e a ferramenta img2dataset
.
img2dataset " search-results.json "
--input_format= " json "
--output_folder= " knn_search_dataset "
--caption_col= " caption "
Primeiro escolha um conjunto de dados de URLs e legendas de imagens (exemplos) e execute:
Você pode querer executar export CUDA_VISIBLE_DEVICES=
para evitar usar sua GPU se ela não tiver VRAM suficiente.
wget https://github.com/rom1504/img2dataset/raw/main/tests/test_files/test_1000.parquet
clip-retrieval end2end test_1000.parquet /tmp/my_output
Então vá para http://localhost:1234 e divirta-se pesquisando entre suas fotos
Use --run_back False
se não quiser executar o back-end
Obtenha algumas imagens em um example_folder
, por exemplo, fazendo:
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
Você também pode colocar arquivos de texto com os mesmos nomes das imagens nessa pasta, para obter incorporações de texto.
Em seguida, execute clip-retrieval inference --input_dataset image_folder --output_folder embeddings_folder
A pasta de saída conterá:
Isso chega a milhões de amostras. A 1.400 amostras/s de um 3080, 10 milhões de amostras podem ser processadas em 2 horas.
clip_inference transforma um conjunto de texto + imagem em embeddings de clipes
"open_clip:ViT-B-32/laion2b_s34b_b79k"
para usar o open_clip ou "hf_clip:patrickjohncyh/fashion-clip"
para usar o modelo de clipe de rosto abraçado. DeepSparse é um tempo de execução de inferência para inferência rápida de modelos esparsos em CPUs. Há um back-end disponível na recuperação de clipe instalando-o com pip install deepsparse-nightly[clip]
e especificando um clip_model
com um "nm:"
prefixado, como "nm:neuralmagic/CLIP-ViT-B-32-256x256-DataComp-s34B-b86K-quant-ds"
ou "nm:mgoin/CLIP-ViT-B-32-laion2b_s34b_b79k-ds"
.
Se desejar ter mais controle sobre como a inferência é executada, você pode criar e chamar trabalhadores diretamente usando clip-retrieval inference.worker
Exemplo de uso:
clip-retrieval inference.worker
--tasks= " [0] "
--input_dataset= " input/folder/{000000..000100}.tar "
--output_folder= " example/path "
--input_format= " webdataset "
--output_partition_count= " 1 "
Fazer isso invocará um único trabalhador que pode ser instruído a se concentrar em um subconjunto específico do input_dataset
. Esse trabalhador processará sequencialmente as tasks
passadas para ele. Aqui, tasks
é uma lista de partition_id
pelas quais este trabalhador será responsável.
Para calcular manualmente o número de tarefas, use a seguinte fórmula: number_samples / wds_number_file_per_input_file
.
A API é muito semelhante à clip-retrieval inference
com algumas pequenas alterações:
partition_id
que este trabalhador é responsável pela computação. ( obrigatório )"open_clip:ViT-B-32-quickgelu"
para usar o open_clip ou "hf_clip:patrickjohncyh/fashion-clip"
para usar o modelo de clipe de rosto abraçado.Nota : O trabalhador não aceita os seguintes argumentos
- write_batch_size Tamanho do lote de gravação (padrão 10**6 )
- Distribution_strategy escolha como distribuir o trabalho, consulte a seção de distribuição para obter detalhes ( sequencial padrão)
- estimativa de wds_number_file_per_input_file do número de amostras por tar se estiver usando wds e não especificando output_partition_count (padrão 10000 )
- qualquer um dos argumentos SLURM
Exemplo de consulta hdfs usando o 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 executar isso em vários nós (e vários gpus), consulte o tutorial em docs/distributed_clip_inference.md
O índice de clipe toma como entrada a saída da inferência de clipe e cria um índice usando autofaiss
clip-retrieval index --embeddings_folder embeddings_folder --index_folder index_folder
--max_index_memory_usage "16G"
permite configurar a quantidade de memória RAM que o índice consumirá. Mais memória RAM, melhor recall de knn (padrão 4G
).--current_memory_available 24G
permite controlar quanta memória RAM é usada durante o processo de criação (padrão 16G
).--image_subfolder "img_emb"
permite especificar uma subpasta para os embeddings de imagens que é concatenada à opção --embeddings_folder
(padrão img_emb
).--text_subfolder "text_emb"
permite especificar uma subpasta para os embeddings de texto que é concatenada à opção --embeddings_folder
( text_emb
padrão).--copy_metadata True
permite escolher se deseja copiar os metadados ou não ao final do processo (Default True
).--nb_cores 8
permite controlar o número de threads (Default None
, que usará todos os núcleos).A saída é uma pasta contendo:
Graças ao autofaiss e ao faiss, isso chega a centenas de milhões de amostras em poucas horas.
Você pode escolher cuidadosamente quanta memória usar para seu índice, a fim de maximizar a recuperação do knn. autofaiss index selection colab pode ajudar junto com o comando autofaiss score_index
para verificar o recall do seu índice. Em geral, os índices que usam mais memória obtêm uma recuperação melhor e, portanto, estão mais próximos de um knn ingênuo (lento).
Depois que os embeddings forem calculados, você poderá filtrar os dados por uma consulta específica. Para isso você pode executar clip-retrieval filter --query "cat" --output_folder "cat/" --indice_folder "indice_folder"
Ele copiará as 100 melhores imagens para esta consulta na pasta de saída. Usar --num_results
ou --threshold
pode ser útil para refinar o filtro
Graças ao índice knn rápido, isso pode ser executado em tempo real (<10ms) para valores K grandes (100.000) e em minutos para valores K muito grandes.
Esses scripts funcionam para pequenos conjuntos de dados. Para maiores, verifique [notebook/simple_filter.ipynb].
Clip back é um back-end de serviço knn simples. Se estiver usando o mapeamento de memória hdf5 e faiss, ele usará apenas a memória usada pelo clipe, que é de 4 GB.
Executar (output_folder é a saída do índice do clipe)
echo ' {"example_index": "output_folder"} ' > indices_paths.json
clip-retrieval back --port 1234 --indices-paths indices_paths.json
Opções:
--use_jit True
usa jit para o modelo de clipe--clip_model "ViT-B/32"
permite escolher o modelo de clipe a ser usado. Prefixe com "open_clip:"
para usar um modelo open_clip.--enable_mclip_option True
carrega o modelo mclip, possibilitando a busca em qualquer idioma.--columns_to_return='["url", "image_path", "caption", "NSFW"]
permite especificar quais colunas devem ser buscadas nos metadados e retornadas pelo back-end. É útil especificar less no caso de cache hdf5 para acelerar as consultas.--enable_faiss_memory_mapping=True
pode ser passada para usar um índice com mapeamento de memória. Isso diminui o uso de memória para zero.--enable_hdf5 True
pode ser passada para habilitar o cache hdf5 para os metadados. O cache HDF5 torna possível usar os metadados quase sem uso de memória.--use_arrow True
permite usar arrow em vez de hdf5. Deve ser usado junto com clip_back_prepro para conjuntos de dados muito grandes (bilhões)--reorder_metadata_by_ivf_index True
aproveita a propriedade de localidade de dados dos resultados de índices knn ivf: ela ordena a coleta de metadados na ordem dos clusters de fertilização in vitro. Isso torna possível uma recuperação de metadados muito mais rápida, pois as leituras acessam algumas partes principalmente sequenciais dos metadados, em vez de muitas partes não sequenciais. Na prática, isso significa ser capaz de recuperar 1 milhão de itens em 1s, enquanto apenas 1.000 itens podem ser recuperados em 1s sem esse método. Isso ordenará os metadados usando o primeiro índice de imagem.--provide_safety_model True
baixará e carregará automaticamente um modelo de segurança. Você precisa pip install autokeras
opcional dependência para que isso funcione.--provide_violence_detector True
carregará um detector de violência, papel--provide_aesthetic_embeddings True
carregará os embeddings estéticos e permitirá que os usuários façam a consulta se mover em direção a um ponto mais agradável do espaço do clipeEssas opções também podem ser fornecidas no arquivo de configuração para ter opções diferentes para cada índice. Exemplo:
{
"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 "
}
}
O cache hdf5 ou arrow é uma boa ideia para usar se:
Neste ponto você tem um servidor flask simples rodando na porta 1234 e que pode responder a estas perguntas:
/indices-list
-> retorna uma lista de índices/knn-service
que recebe 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
}
text, image e image_url são mutuamente exclusivos e retornam:
[
{
"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 também pode conter um campo de URL se os metadados o fornecerem.
O id é a posição do item no índice. Pode ser usado para consultar metadados com o endpoint /metadata:
{
"indice_name" : "example_index" ,
"ids" : [ 543 , 782 ]
}
que retorna:
{
"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
}
O argumento num_result_ids
de /knn-service
e /metadata
pode ser usado junto para fazer grandes consultas knn e, em seguida, buscar os metadados somente quando necessário. Faz sentido fazer isso, pois a pesquisa knn pode ser muito eficiente graças à forte localidade de referência do índice knn IVF, tornando rápido fazer knn com um K grande, enquanto a implementação atual de metadados em disco (hdf5) não tem isso propriedade e, portanto, não consegue recuperar rapidamente uma grande quantidade de itens aleatórios. Em particular, isso pode ser usado para implementar rolagem infinita em um front-end.
Por padrão, o back-end também exporá um front-end. Esse front-end, por padrão, atingirá esse back-end, no entanto, você pode precisar especificar se isso está acontecendo por http ou https; nesse caso, use a opção --default_backend
para especificar o URL do back-end. --url_column
permite especificar o nome do URL da coluna para a frente
Esses back-ends têm latência de 50 ms se usarem índices e metadados mapeados na memória. A taxa de transferência é de cerca de 20 consultas/s. Para alto rendimento, é necessário usar um servidor grpc, bem como uma GPU para inferência rápida de clipes. Desativar as opções de mapeamento de memória também pode acelerar as solicitações, ao custo do alto uso de memória RAM.
Esses back-ends também expõem um endpoint prometheus /metrics
bem como um resumo legível por humanos em /metrics-summary
. Isso pode (opcionalmente) ser usado para configurar um painel grafana para monitoramento:
Pode-se observar neste dashboard que a parte mais lenta de qualquer chamada é buscar a imagem pela sua url no caso de busca por url de imagem, levando até 300ms. Para consultas de texto ou imagens, a latência é de cerca de 50 ms. Aqui está um exemplo de saída no resumo 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 é uma interface de usuário simples que se conecta ao clip back e exibe os resultados. Você pode usá-lo na interface do usuário de recuperação de clipe
Ou você pode executá-lo sozinho com:
npm install -g clip-retrieval-front
clip-retrieval-front 3005
Você também pode executá-lo com clip-retrieval front
ou atrás do pacote python.
Para desenvolvê-lo, vá para frente e execute npm install
e depois npm start
.
Localmente ou no gitpod ( export PIP_USER=false
lá)
Configure um virtualenv:
python3 -m venv .env
source .env/bin/activate
pip install -e .
para executar testes:
pip install -r requirements-test.txt
então
make lint
make test
Você pode usar make black
para reformatar o código
python -m pytest -x -s -v tests -k "test_runner"
para executar um teste específico
Se você quiser usar o front por meio do backend ou frontend python, execute
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}}
}