クリップの埋め込みを簡単に計算し、それを使用してclip retrievalシステムを構築します。 3080 を使用すると、1 億のテキスト + 画像の埋め込みを 20 時間で処理できます。
これにより、エンドツーエンドでシンプルなセマンティック検索システムを構築できます。セマンティック検索全般について知りたいですか?このトピックに関する私の投稿を読むことができます。
この規模を 10 億サンプルまで拡張する方法の詳細については、laion5B と 10 億規模でのセマンティック検索も参照してください。
データを ML で使いやすくするための再利用可能なツールを作成することを信じており、貢献したい場合は、DataToML チャットに参加してください。
pip インストール クリップ取得
laion5B インデックスの実行に興味がある場合は、このドキュメントを参照してください。
ClipClient
使用すると、Python 経由でクリップ取得バックエンドのリモート クエリを実行できます。
jupyter ノートブックの例については、 ClipClient
- Getting Started Notebook」を参照してください。
初期化中に、いくつかのパラメータを指定できます。
backend_url
: バックエンドの URL。 (必須)indice_name
: 使用するインデックスの名前を指定します。 (必須)aesthetic_score
:etics-predictor によって評価された美的スコア。デフォルトは9
です。use_mclip
: CLIP の多言語バージョンを使用するかどうか。デフォルトはFalse
です。aesthetic_weight
: 美的スコアの重み。デフォルトは0.5
ですmodality
: インデックス内の画像またはテキスト ( Multimodal.IMAGE
またはMultimodal.TEXT
のいずれか) を検索します。デフォルトはMultimodal.IMAGE
です。num_images
: API から返される画像の数。デフォルトは40
です。deduplicate
: 画像埋め込みによって結果を重複排除するかどうか。デフォルトは true です。use_safety_model
: 安全でない画像を削除するかどうか。デフォルトは true です。use_violence_detector
: 暴力的な画像を削除するかどうか。デフォルトは true です。たとえば、デフォルトのパラメータを使用して Laion5B のホストされたバックエンドをクエリするには、次のようにします。
from clip_retrieval . clip_client import ClipClient , Modality
client = ClipClient ( url = "https://knn.laion.ai/knn-service" , indice_name = "laion5B-L-14" )
提供したテキストに似たキャプション付きの画像が見つかります。
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 }
提供した画像に似たキャプション付き画像も検索できます。画像はローカル パスまたは URL 経由で渡すことができます。
cat_results = client . query ( image = "cat.jpg" )
dog_results = client . query ( image = "https://example.com/dog.jpg" )
提供したクリップ埋め込みに似たキャプション付き画像を見つけることもできます。
cat_results = client . query ( embedding_input = cat_embedding )
類似のテキストと画像のペアを使用して既存のデータセットを強化するには、画像のディレクトリをクエリし、結果を結合します。
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 )
保存された json 結果とツールimg2dataset
使用してデータセットを作成できます。
img2dataset " search-results.json "
--input_format= " json "
--output_folder= " knn_search_dataset "
--caption_col= " caption "
まず画像の URL とキャプション (例) のデータセットを選択してから、次を実行します。
十分な VRAM がない場合は、GPU の使用を避けるために、 export CUDA_VISIBLE_DEVICES=
を実行することをお勧めします。
wget https://github.com/rom1504/img2dataset/raw/main/tests/test_files/test_1000.parquet
clip-retrieval end2end test_1000.parquet /tmp/my_output
次に、http://localhost:1234 にアクセスして、写真の検索をお楽しみください。
バックエンドを実行したくない場合は、 --run_back False
使用します。
たとえば次のようにして、 example_folder
内のいくつかの画像を取得します。
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
画像と同じ名前のテキスト ファイルをそのフォルダーに配置して、テキストの埋め込みを取得することもできます。
次に、 clip-retrieval inference --input_dataset image_folder --output_folder embeddings_folder
出力フォルダーには次のものが含まれます。
これは数百万のサンプルまで拡張できます。 3080 の 1400 サンプル/秒では、10M サンプルを 2 時間で処理できます。
Clip_inference テキスト + 画像のセットをクリップ埋め込みに変換します
"open_clip:ViT-B-32/laion2b_s34b_b79k"
、ハグ顔クリップモデルを使用する場合は"hf_clip:patrickjohncyh/fashion-clip"
と指定します。DeepSparse は、CPU 上で高速にスパース モデルを推論するための推論ランタイムです。 pip install deepsparse-nightly[clip]
でインストールし、「nm:neuralmagic/CLIP-ViT-B-32-256x256」のように"nm:"
を先頭に付けてclip_model
指定することで、クリップ検索内でバックエンド"nm:neuralmagic/CLIP-ViT-B-32-256x256-DataComp-s34B-b86K-quant-ds"
または"nm:mgoin/CLIP-ViT-B-32-laion2b_s34b_b79k-ds"
。
推論の実行方法をさらに制御したい場合は、 clip-retrieval inference.worker
を使用してワーカーを直接作成し、呼び出すことができます。
使用例:
clip-retrieval inference.worker
--tasks= " [0] "
--input_dataset= " input/folder/{000000..000100}.tar "
--output_folder= " example/path "
--input_format= " webdataset "
--output_partition_count= " 1 "
これにより、 input_dataset
の特定のサブセットに焦点を当てるように指示できる単一のワーカーが呼び出されます。そのワーカーは、渡されたtasks
を順番に処理します。ここで、 tasks
、このワーカーが担当するpartition_id
のリストです。
タスクの数を手動で計算するには、 number_samples / wds_number_file_per_input_file
という式を使用します。
API はclip-retrieval inference
とよく似ていますが、いくつかの小さな変更があります。
partition_id
を表す整数のリスト。 (必須)"open_clip:ViT-B-32-quickgelu"
、ハグ顔クリップモデルを使用する場合は"hf_clip:patrickjohncyh/fashion-clip"
と指定します。注: ワーカーは次の引数を受け入れません。
- write_batch_size書き込みバッチサイズ (デフォルトは10**6 )
- distribution_strategyジョブの分散方法を選択します。詳細については、分散セクションを参照してください (デフォルトは順次)
- wds_number_file_per_input_file wds を使用し、output_partition_count を指定しない場合の tar あたりのサンプル数の推定 (デフォルトは10000 )
- SLURM 引数のいずれか
Webdataset 形式を使用した HDF クエリの例: `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
これを複数のノード (および複数の GPU) で実行するには、docs/distributed_clip_inference.md のチュートリアルを参照してください。
クリップ インデックスはクリップ推論の出力を入力として受け取り、autofaiss を使用してそこからインデックスを作成します。
clip-retrieval index --embeddings_folder embeddings_folder --index_folder index_folder
--max_index_memory_usage "16G"
オプションを使用すると、インデックスが消費する RAM の量を構成できます。 RAM が増えると、knn リコールが向上します (デフォルト4G
)。--current_memory_available 24G
作成プロセス中に使用される RAM の量を制御できます (デフォルトは16G
)。--image_subfolder "img_emb"
--embeddings_folder
オプション (デフォルトimg_emb
) に連結される画像埋め込みのサブフォルダーを指定できます。--text_subfolder "text_emb"
、 --embeddings_folder
オプション (デフォルトのtext_emb
) に連結されるテキスト埋め込みのサブフォルダーを指定できます。--copy_metadata True
指定すると、プロセスの最後にメタデータをコピーするかどうかを選択できます (デフォルトはTrue
)。--nb_cores 8
スレッドの数を制御できます (デフォルトはNone
、すべてのコアが使用されます)。出力は以下を含むフォルダーです。
autofaiss と faiss のおかげで、これは数時間で数億のサンプルにまで拡張できます。
knn 再現率を最大化するために、インデックスに使用するメモリの量を慎重に選択することをお勧めします。 autofaiss インデックスの選択 colab は、 autofaiss score_index
コマンドと併用してインデックスのリコールをチェックするのに役立ちます。一般に、より多くのメモリを使用するインデックスはより良い再現率を取得するため、単純な (遅い) knn に近くなります。
埋め込みが計算されたら、特定のクエリによってデータをフィルターで除外することができます。そのためにはclip-retrieval filter --query "cat" --output_folder "cat/" --indice_folder "indice_folder"
実行できます。これにより、このクエリに最適な 100 個の画像が出力フォルダーにコピーされます。 --num_results
または--threshold
を使用すると、フィルターを絞り込むのに役立つ場合があります
高速 knn インデックスのおかげで、これは、大きな K 値 (100000) の場合はリアルタイム (<10ms) で、非常に大きな K 値の場合は数分で実行できます。
このスクリプトは小規模なデータセットに対して機能します。より大きなものについては、[notebook/simple_filter.ipynb] を確認してください。
Clip back は、単純な knn サービス バックエンドです。 hdf5 と faiss メモリ マッピングの両方を使用する場合、クリップで使用されるメモリ (4GB) のみが使用されます。
実行 (output_folder はクリップ インデックスの出力です)
echo ' {"example_index": "output_folder"} ' > indices_paths.json
clip-retrieval back --port 1234 --indices-paths indices_paths.json
オプション:
--use_jit True
クリップ モデルに jit を使用します--clip_model "ViT-B/32"
使用するクリップ モデルを選択できます。 open_clip モデルを使用するには、 "open_clip:"
という接頭辞を付けます。--enable_mclip_option True
mclip モデルがロードされ、任意の言語で検索できるようになります。--columns_to_return='["url", "image_path", "caption", "NSFW"]
どの列をメタデータからフェッチしてバックエンドによって返すかを指定できます。 hdf5 キャッシュの場合、クエリを高速化するために、less を指定すると便利です。--enable_faiss_memory_mapping=True
オプションを渡すと、メモリ マッピングのあるインデックスを使用できます。これにより、メモリ使用量がゼロになります。--enable_hdf5 True
オプションを渡すと、メタデータの hdf5 キャッシュを有効にすることができます。 HDF5 キャッシュにより、メモリをほとんど使用せずにメタデータを使用できるようになります。--use_arrow True
設定すると、hdf5 の代わりに arrow を使用できます。非常に大規模なデータセット (数十億) の場合は、clip_back_prepro と一緒に使用する必要があります。--reorder_metadata_by_ivf_index True
オプションは、knn ivf インデックスの結果のデータ局所性プロパティを利用します。つまり、IVF クラスターの順序でメタデータ コレクションを順序付けします。これにより、読み取りではメタデータの多くの非連続部分ではなく、ほとんど連続したいくつかの部分にアクセスするため、メタデータの取得が大幅に高速化されます。実際には、これは 1 秒で 100 万個のアイテムを取得できることを意味しますが、この方法を使用しない場合は 1 秒で 1,000 個のアイテムしか取得できません。これにより、最初の画像インデックスを使用してメタデータが順序付けされます。--provide_safety_model True
指定すると、安全モデルが自動的にダウンロードされ、ロードされます。これを機能させるには、 pip install autokeras
必要があります。--provide_violence_detector True
暴力検出器、紙をロードします--provide_aesthetic_embeddings True
すると、美的埋め込みがロードされ、ユーザーがクリップ空間のより適切な点に向かってクエリを移動できるようになります。これらのオプションを構成ファイルで指定して、インデックスごとに異なるオプションを指定することもできます。例:
{
"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 または arrow キャッシュは、次の場合に使用することをお勧めします。
この時点で、ポート 1234 で実行されている単純な flask サーバーがあり、これらのクエリに応答できます。
/indices-list
-> インデックスのリストを返します/knn-service
入力として受け取ります: {
"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、image_url は相互に排他的であり、次の値を返します。
[
{
"image" : "base 64 of an image" ,
"text" : "some result text" ,
"id" : 543
} ,
{
"image" : "base 64 of an image" ,
"text" : "some result text" ,
"id" : 782
}
]
メタデータが提供する場合、各オブジェクトには URL フィールドが含まれる場合もあります。
ID はインデックス内の項目の位置です。 /metadata エンドポイントを使用してメタデータをクエリするために使用できます。
{
"indice_name" : "example_index" ,
"ids" : [ 543 , 782 ]
}
これは以下を返します:
{
"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
}
/knn-service
と/metadata
のnum_result_ids
引数を一緒に使用すると、大規模な knn クエリを実行し、必要な場合にのみメタデータをフェッチできます。 knn IVF インデックスの参照の強力な局所性のおかげで、knn 検索は非常に効率的になり、大きな K を使用して knn を高速に実行できるため、これを行うのは理にかなっていますが、現在のディスク上のメタデータ実装 (hdf5) にはそのような機能がありません。プロパティのため、大量のランダムなアイテムを高速に取得することはできません。特にこれは、フロントエンドで無限スクロールを実装するために使用できます。
デフォルトでは、バックエンドはフロントエンドも公開します。そのフロントエンドはデフォルトでこのバックエンドにアクセスしますが、これが http 経由で行われるか https 経由で行われるかを指定する必要がある場合があります。この場合、オプション--default_backend
使用してバックエンド URL を指定します。 --url_column
フロントの列 URL の名前を指定できます。
メモリ マップされたインデックスとメタデータを使用する場合、このバックエンドのレイテンシーは 50 ミリ秒です。スループットは約 20 クエリ/秒です。高スループットを実現するには、高速クリップ推論のための GPU だけでなく grpc サーバーの使用も必要です。メモリ マッピング オプションをオフにすると、RAM の使用量が多くなりますが、リクエストを高速化することもできます。
このバックエンドは、 prometheus /metrics
エンドポイントと、 /metrics-summary
で人間が判読できる概要も公開します。これは (オプションで) 監視用の grafana ダッシュボードをセットアップするために使用できます。
このダッシュボードでは、画像 URL 検索の場合、呼び出しの中で最も遅い部分は URL による画像の取得であり、最大 300 ミリ秒かかることがわかります。テキスト クエリまたは画像クエリの場合、遅延は約 50 ミリ秒です。メトリクスの概要の出力例を次に示します。
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%
クリップフロントは、クリップバックに接続して結果を表示するシンプルな UI です。クリップ検索UIで使用できます
または、次のようにして自分で実行することもできます。
npm install -g clip-retrieval-front
clip-retrieval-front 3005
Python パッケージの前後でclip-retrieval front
を使用して実行することもできます。
開発するには、フロントに移動してnpm install
実行し、次にnpm start
実行します。
ローカルまたは gitpod のいずれか (そこでexport PIP_USER=false
ます)
virtualenv をセットアップします。
python3 -m venv .env
source .env/bin/activate
pip install -e .
テストを実行するには:
pip install -r requirements-test.txt
それから
make lint
make test
make black
使用してコードを再フォーマットできます
python -m pytest -x -s -v tests -k "test_runner"
特定のテストを実行します
Python バックエンドまたはフロントエンド経由でフロントを使用したい場合は、次を実行します。
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}}
}