OpenCLIP 2.7 : 概要

OpenCLIP 2.7 : 概要 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 12/13/2022 (v2.7.0)

* 本ページは、mlfoundations/open_clip の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス

クラスキャット は人工知能・テレワークに関する各種サービスを提供しています。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

  • 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
  • sales-info@classcat.com  ;  Web: www.classcat.com  ;   ClassCatJP

 

 

OpenCLIP 2.7 : 概要

OpenAI の CLIP (対照的言語-画像事前訓練) のオープンソース実装にようこそ。

このレポジトリの目標は対照的画像-テキスト supervision によるモデルの訓練を可能にし、分布シフトへの堅牢性のようなそれらの特性を調査することです。私たちの出発点は、同じデータセットで訓練するときオリジナルの CLIP モデルの精度に一致する CLIP の実装です。具体的には、OpenAI の YFCC の 1500 万画像サブセット 上で私たちのコードベースで訓練された ResNet-50 モデルは ImageNet で 32.7% top-1 精度を獲得します。OpenAI の CLIP モデルは YFCC の同じサブセットで訓練されたとき 31.3% に到達します。実験の容易さのために、Conceptual Captions データセットの 300 万画像上の訓練のためのコードも提供します、そこでは私たちのコードベースで訓練された ResNet-50×4 は 22.2% top-1 ImageNet 精度に到達します。

更にこれを OpenAI の LAION-400M そしてより大きい LAION-2B スーパーセットに相当するサイズのデータセットで再現研究を行ないました。

私たちは以下を訓練しました :

  • ViT-B/32 on LAION-400M with a accuracy of 62.9%, comparable to OpenAI’s 63.2%, zero-shot top-1 on ImageNet1k
  • ViT-B/32 on LAION-2B with a accuracy of 66.6%.
  • ViT-B/16 on LAION-400M achieving an accuracy of 67.1%, lower than OpenAI’s 68.3% (as measured here, 68.6% in paper)
  • ViT-B/16+ 240×240 (~50% more FLOPS than B/16 224×224) on LAION-400M achieving an accuracy of 69.2%
  • ViT-L/14 on LAION-400M with an accuracy of 72.77%, vs OpenAI’s 75.5% (as measured here, 75.3% in paper)
  • ViT-L/14 on LAION-2B with an accuracy of 75.3%, vs OpenAI’s 75.5% (as measured here, 75.3% in paper)
  • ViT-H/14 on LAION-2B with an accuracy of 78.0. The best in1k zero-shot for released, open-source weights thus far.
  • ViT-g/14 on LAION-2B with an accuracy of 76.6. This was trained on reduced schedule, same samples seen as 400M models.

以下 で詳細に説明するように、中程度の精度の型 (regime) の CLIP モデルは、信頼できるスケーリング法則 に従っているので、より大きな CLIP モデルの堅牢性について結論を出すことを既に可能にしています。

このコードベースは進行中の作業で、それをよりアクセスしやすく役立つものにするためにすべての人に貢献することに勧めます。将来的には、TPU 訓練のサポートとより大きいモデルのリリースを追加する計画です。このコードベースが対照的画像-テキスト学習のさらなる研究を容易にして促進することを私たちは希望します。Please submit an issue or send an email if you have any other requests or suggestions.

src/open_clip/ のモデリングとトークナイザー・コードの一部は OpenAI の公式 レポジトリ の流用であることに注意してください。

 

アプローチ


Image Credit: https://github.com/openai/CLIP

 

使用方法

pip install open_clip_torch
import torch
from PIL import Image
import open_clip

model, _, preprocess = open_clip.create_model_and_transforms('ViT-B-32-quickgelu', pretrained='laion400m_e32')
tokenizer = open_clip.get_tokenizer('ViT-B-32-quickgelu')
preprocess
Compose(
    Resize(size=224, interpolation=bicubic, max_size=None, antialias=None)
    CenterCrop(size=(224, 224))
    <function _convert_to_rgb at 0x7f1ee28014c0>
    ToTensor()
    Normalize(mean=(0.48145466, 0.4578275, 0.40821073), std=(0.26862954, 0.26130258, 0.27577711))
)
image = preprocess(Image.open("CLIP.png")).unsqueeze(0)
text = tokenizer(["a diagram", "a dog", "a cat"])
image.shape, text.shape
(torch.Size([1, 3, 224, 224]), torch.Size([3, 77]))
text
tensor([[49406,   320, 22697, 49407,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0],
        [49406,   320,  1929, 49407,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0],
        [49406,   320,  2368, 49407,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0]])
with torch.no_grad(), torch.cuda.amp.autocast():
    image_features = model.encode_image(image)
    text_features = model.encode_text(text)
    image_features /= image_features.norm(dim=-1, keepdim=True)
    text_features /= text_features.norm(dim=-1, keepdim=True)

    print(image_features.shape, text_features.shape)

    text_probs = (100.0 * image_features @ text_features.T).softmax(dim=-1)

print("Label probs:", text_probs)  # prints: [[1., 0., 0.]]
torch.Size([1, 512]) torch.Size([3, 512])
Label probs: tensor([[1.0000e+00, 2.9174e-06, 1.8152e-06]])

数十億の埋め込みを効率的に計算するためには、clip-retrieval を利用できます、これは openclip のサポートを持ちます。

 

分類タスク上の微調整

このレポジトリは CLIP モデルの訓練にフォーカスしています。ImageNet のような下流分類タスクで訓練されたゼロショットモデルを微調整するには、私たちの別のレポジトリ: WiSE-FT をご覧ください。WiSE-FT レポジトリは Robust Fine-tuning of Zero-shot Models という私たちの論文に対するコードを含み、そこでは分布シフト下の堅牢性を保全しながらゼロショットモデルを微調整するテクニックを紹介しています。

 

データ

データセットを webdataset としてダウンロードするには、img2dataset を推奨します。

 

Conceptual Captions

OpenCLIP は 2 つのカラム: 画像へのパスとテキストキャプションを含む CSV ファイルを読みます。カラム名は引数として main.py に渡されます。

スクリプト src/data/gather_cc.py は Conceptual Captions 画像を収集します。まず、Conceptual Captions URL をダウンロードして、そしてレポジトリからスクリプトを実行します :

python3 src/data/gather_cc.py path/to/Train_GCC-training.tsv path/to/Validation_GCC-1.1.0-Validation.tsv

訓練セットは 2.89M 画像を含み、そして検証セットは 13K 画像を含みます。

 

YFCC と他のデータセット

上述のように CSV ファイル経由で訓練データを指定することに加えて、私たちのコードベースは webdataset もサポートします、これは大規模なデータセットに対して勧められます。想定される形式は .tar ファイルの系列です。これらの .tar ファイルの各々は各訓練サンプルに対して 2 つのファイルを含む必要があります、1 つは画像のためで一つは対応するテキストのためです。両方のファイルは同じ名前を持ちますが、異なる拡張子である必要がります。例えば、shard_001.tar は abc.jpg と abc.txt のようなファイルを含むことができます。webdataset の詳細は https://github.com/webdataset/webdataset で学習できます。それぞれ 1,000 データポイントを含む .tar ファイルを使用します、これを tarp を使用して作成します。

YFCC データセットを Multimedia Commons からダウンロードできます。OpenAI と同様に、前述の精度値に到達するために YFCC のサブセットを使用しました。このサブセットの画像のインデックスは OpenAI の CLIP レポジトリ にあります。

 

CLIP の訓練

インストール

最初に以下で仮想環境を作成することを勧めます :

python3 -m venv .env
source .env/bin/activate
pip install -U pip

それから “pip install ‘open_clip_torch[training]'” で訓練のために openclip をインストールできます。

 

開発

contribute コードを変更したい場合、openclip をクローズしてから (virtualenv を作成後) openclip フォルダで “make install” を実行します。

https://pytorch.org/get-started/locally/ に従って pip PyTorch をインストールします。

訓練依存関係をインストールするために “make install-training” を実行できます。

 

テスト

テストは “make install-test” そして “make test” で実行できます。

特定のテストを実行するには “python -m pytest -x -s -v tests -k “training”” です。

特定の git revision や tag に対してリグレッションテストを実行するには :

  1. テストデータの生成
    python tests/util_test.py --model RN50 RN101 --save_model_list models.txt --git_revision 9d31b2ec4df6d8228f370ff20c8267ec6ba39383
    

    WARNING : This will invoke git and modify your working tree, but will reset it to the current state after data has been generated! Don’t modify your working tree while test data is being generated this way.

  2. リグレッションテストの実行
    OPEN_CLIP_TEST_REG_MODELS=models.txt python -m pytest -x -s -v -m regression_test
    

 

Sample シングルプロセス実行コード

python -m training.main \
    --save-frequency 1 \
    --zeroshot-frequency 1 \
    --report-to tensorboard \
    --train-data="/path/to/train_data.csv"  \
    --val-data="/path/to/validation_data.csv"  \
    --csv-img-key filepath \
    --csv-caption-key title \
    --imagenet-val=/path/to/imagenet/root/val/ \
    --warmup 10000 \
    --batch-size=128 \
    --lr=1e-3 \
    --wd=0.1 \
    --epochs=30 \
    --workers=8 \
    --model RN50

Note : imagenet-val is the path to the validation set of ImageNet for zero-shot evaluation, not the training set! You can remove this argument if you do not want to perform zero-shot evaluation on ImageNet throughout training. Note that the val folder should contain subfolders. If it doest not, please use this script.

 

Multi-GPU and Beyond

このコードは 1024 A100 までバトルテストされ、分散訓練のために様々なソリューションを提供します。SLURM クラスタのネイティブサポートも含みます。

訓練するために使用されるデバイスの数が増えるにつれて、ロジット行列の空間的複雑さ (space complexity) も増します。素朴な all-gather スキームを使用すると、空間的複雑さは O(n^2) です。代わりに、フラグ –gather-with-grad と –local-loss が使用された場合、複雑さは実質的に線形になる可能性があります。This alteration results in one-to-one numerical results as the naïve method.

 

エポック

より大規模なデータセット (eg Laion2B) については、–train-num-samples を full エポックよりも低い値に設定することを勧めます、例えば replacement でサンプリングする –dataset-resampled と連動してエポックの 1/16 の –train-num-samples 135646078 にします。これは頻度高くチェックポイントを持ち、より頻繁に評価することを可能にします。

 

パッチ Dropout

最近の研究 は、visual トークンの半分から 3/4 を dropout できて、精度の損失なく 2-3x の訓練スピードアップにつながることを示しています。

キー patch_dropout により visual transformer config でこれを設定できます。

論文では、最後にパッチ dropout なしでも微調整しています。コマンドライン引数 –force-patch-dropout 0 でこれを行なうことができます。

 

シングルノード

分散ジョブを起動するために torchrun を利用します。以下は 4 GPU のノード上でジョブを起動します :

cd open_clip/src
torchrun --nproc_per_node 4 -m training.main \
    --train-data '/data/cc12m/cc12m-train-{0000..2175}.tar' \
    --train-num-samples 10968539 \
    --dataset-type webdataset \
    --batch-size 320 \
    --precision amp \
    --workers 4 \
    --imagenet-val /data/imagenet/validation/

 

マルチノード

ユーザがノードの数とホストノードについての情報を含める限りは、上の同じスクリプトが動作します。

cd open_clip/src
torchrun --nproc_per_node=4 \
    --rdzv_endpoint=$HOSTE_NODE_ADDR \
    -m training.main \
    --train-data '/data/cc12m/cc12m-train-{0000..2175}.tar' \
    --train-num-samples 10968539 \
    --dataset-type webdataset \
    --batch-size 320 \
    --precision amp \
    --workers 4 \
    --imagenet-val /data/imagenet/validation/

 

SLURM

これはたぶん利用するのに最も容易なソリューションです。次のスクリプトは最も大規模なモデルを訓練するために使用されました :

#!/bin/bash -x
#SBATCH --nodes=32
#SBATCH --gres=gpu:4
#SBATCH --ntasks-per-node=4
#SBATCH --cpus-per-task=6
#SBATCH --wait-all-nodes=1
#SBATCH --job-name=open_clip
#SBATCH --account=ACCOUNT_NAME
#SBATCH --partition PARTITION_NAME

eval "$(/path/to/conda/bin/conda shell.bash hook)" # init conda
conda activate open_clip
export CUDA_VISIBLE_DEVICES=0,1,2,3
export MASTER_PORT=12802

master_addr=$(scontrol show hostnames "$SLURM_JOB_NODELIST" | head -n 1)
export MASTER_ADDR=$master_addr

cd /shared/open_clip
export PYTHONPATH="$PYTHONPATH:$PWD/src"
srun --cpu_bind=v --accel-bind=gn python -u src/training/main.py \
    --save-frequency 1 \
    --report-to tensorboard \
    --train-data="/data/LAION-400M/{00000..41455}.tar" \
    --warmup 2000 \
    --batch-size=256 \
    --epochs=32 \
    --workers=8 \
    --model ViT-B-32 \
    --name "ViT-B-32-Vanilla" \
    --seed 0 \
    --local-loss \
    --gather-with-grad

 

Resuming from a checkpoint

python -m training.main \
    --train-data="/path/to/train_data.csv" \
    --val-data="/path/to/validation_data.csv"  \
    --resume /path/to/checkpoints/epoch_K.pt

 

テキストエンコーダとして事前訓練済み言語モデルを使用する訓練

別の言語モデルを CLIP のテキストエンコーダとして使用したい場合、src/open_clip/model_configs 内の Hugging Face モデル configs の一つを使用して、それぞれ –model と –hf-tokenizer-name パラメータとしてそのトークナイザーを渡すことによりそれを行なうことができます。現在 RoBERTa (“test-roberta” config) だけをサポートしていますが、新しいモデルの追加は自明なはずです。最後から幾つの層を非凍結のままにするかを –lock-text-unlocked-layers パラメータで決定することもできます。ここに CLIP を (最後の 10 層が非凍結である) RoBERTa LM で訓練するサンプルコマンドがあります :

python -m training.main \
         --train-data="pipe:aws s3 cp s3://s-mas/cc3m/{00000..00329}.tar -" \
         --train-num-samples 3000000 \
         --val-data="pipe:aws s3 cp s3://s-mas/cc3m/{00330..00331}.tar -" \
         --val-num-samples 10000 \
         --dataset-type webdataset \
         --batch-size 256 \
         --warmup 2000 \
         --epochs 10 \
         --lr 5e-4 \
         --precision amp \
         --workers 6 \
         --model "roberta-ViT-B-32" \
         --lock-text \
         --lock-text-unlocked-layers 10 \
         --name "10_unfrozen" \
         --report-to "tensorboard" \

 

損失曲線

8 GPU を装備するマシン上で実行するとき、コマンドは Conceptual Captions に対して以下の訓練曲線を生成するはずです :

Conceptual Captions に対する詳細な曲線は /docs/clip_conceptual_captions.md で与えられます。

YFCC 上で RN50 を訓練するとき、lr=5e-4 と epochs=32 以外は上記と同じハイパーパラメータが使用されます。

ViT-B/32 or RN50x4 or RN50x16 or ViT-B/16 のような別のモデルを使用するには、–model RN50x4 で指定することに注意してください。

 

tensorboard の起動

tensorboard --logdir=logs/tensorboard/ --port=7777

 

評価 / ゼロショット

ローカルチェックポイントの評価

python -m training.main \
    --val-data="/path/to/validation_data.csv"  \
    --model RN101 \
    --pretrained /path/to/checkpoints/epoch_K.pt

 

ホストされた事前訓練済みチェックポイントを ImageNet ゼロショット予測で評価する

python -m training.main \
    --imagenet-val /path/to/imagenet/validation \
    --model ViT-B-32-quickgelu \
    --pretrained laion400m_e32

 

事前訓練済みモデル詳細

(訳注: 事前訓練済みモデル詳細の LAION-400M 及び LAION-2B (en) については原文を参照してください。)

 

LAION-400M – https://laion.ai/laion-400-open-dataset

私たちは OpenAI の ViT の結果を比較可能なサイズの (そしてオープンな) LAION-400M データセットによる再現に取り組んでいます。訓練済み重みはリリース v0.2 で見つかります。

LAION400M の重みは JUWELS スーパーコンピュータで訓練されました (下記の acknowledgements セクション参照)。

 

ViT-B/32 224×224

 

ViT-B/16 224×224

 

ViT-B/16+ 240×240

 

ViT-L/14 224×224

 

LAION-2B (en) – https://laion.ai/laion-5b-a-new-era-of-open-large-scale-multi-modal-datasets/

英語キャプションを持つ LAION-5B の ~2B サンプルサブセット (https://huggingface.co/datasets/laion/laion2B-en)

 

ViT-B/32 224×224

 

ViT-L/14 224×224

 

ViT-H/14 224×224

 

ViT-g/14 224×224

 

ViT-B/32 roberta base

 

ViT-B/32 xlm roberta base

 

ViT-H/14 xlm roberta large

 

YFCC-15M

 

CC12M

 

事前訓練済みモデルインターフェイス

事前訓練済みモデルと未訓練モデルの両方をインスタンス化する単純なモデルインターフェイスを提供しています。

NOTE : 多くの既存のチェックポイントはオリジナルの OpenAI モデルから QuickGELU 活性を使用しています。この活性は実際には PyTorch の最近のバージョンのネイティブ torch.nn.GELU よりも非効率です。今はモデルのデフォルトは nn.GELU ですので、OpenCLIP の事前訓練済み重みのためには -quickgelu ポストフィックスによるモデル定義を使用するべきです。すべての OpenAI 事前訓練済み重みは常に QuickGELU がデフォルトです。QuickGELU を使用して事前訓練済み重みで非 -quickgelu モデル定義を使用することもできますが、精度が落ち、再調整は長い実行に対してゼロになる (vanish) 傾向があります。

将来的な訓練済みモデルは nn.GELU を使用します。

>>> import open_clip
>>> open_clip.list_pretrained()
[('RN50', 'openai'),
 ('RN50', 'yfcc15m'),
 ('RN50', 'cc12m'),
 ('RN50-quickgelu', 'openai'),
 ('RN50-quickgelu', 'yfcc15m'),
 ('RN50-quickgelu', 'cc12m'),
 ('RN101', 'openai'),
 ('RN101', 'yfcc15m'),
 ('RN101-quickgelu', 'openai'),
 ('RN101-quickgelu', 'yfcc15m'),
 ('RN50x4', 'openai'),
 ('RN50x16', 'openai'),
 ('RN50x64', 'openai'),
 ('ViT-B-32', 'openai'),
 ('ViT-B-32', 'laion400m_e31'),
 ('ViT-B-32', 'laion400m_e32'),
 ('ViT-B-32', 'laion2b_e16'),
 ('ViT-B-32', 'laion2b_s34b_b79k'),
 ('ViT-B-32-quickgelu', 'openai'),
 ('ViT-B-32-quickgelu', 'laion400m_e31'),
 ('ViT-B-32-quickgelu', 'laion400m_e32'),
 ('ViT-B-16', 'openai'),
 ('ViT-B-16', 'laion400m_e31'),
 ('ViT-B-16', 'laion400m_e32'),
 ('ViT-B-16-plus-240', 'laion400m_e31'),
 ('ViT-B-16-plus-240', 'laion400m_e32'),
 ('ViT-L-14', 'openai'),
 ('ViT-L-14', 'laion400m_e31'),
 ('ViT-L-14', 'laion400m_e32'),
 ('ViT-L-14', 'laion2b_s32b_b82k'),
 ('ViT-L-14-336', 'openai'),
 ('ViT-H-14', 'laion2b_s32b_b79k'),
 ('ViT-g-14', 'laion2b_s12b_b42k'),
 ('roberta-ViT-B-32', 'laion2b_s12b_b32k'),
 ('xlm-roberta-base-ViT-B-32', 'laion5b_s13b_b90k'),
 ('xlm-roberta-large-ViT-H-14', 'frozen_laion5b_s13b_b90k'),]

>>> model, train_transform, eval_transform = open_clip.create_model_and_transforms('ViT-B-32', pretrained='laion2b_s34b_b79k')

 

勾配累積

より大きいバッチをシミュレートするには –accum-freq k を使用します。gpu 毎のバッチサイズ, –batch-size が m の場合、実効バッチサイズは k * m* num_gpus です。

–accum-freq をでデフォルトの 1 から増やすとき、samples/s はほぼ一定です (バッチサイズが 2 倍になり、バッチ毎時間も同様です)。バッチサイズを減らすために –grad-checkpointing –local-loss –gather-with-grad のような他の機能を –accum-freq を増やす前に使用することを勧めます。–accum-freq はこれらの機能に加えて使用できます。

サンプル毎に 1 つの forward パスの代わりに、今ではサンプル毎に 2 つの forward パスがあります。但し、最初は torch.no_grad で実行されます。

某かの追加 GPU が必要です — すべての m バッチからの特徴とデータはメモリにストアされます。

通常 1 回のかわりに m 回の損失計算があります。

詳細は Cui et al. (https://arxiv.org/abs/2112.09331) or Pham et al. (https://arxiv.org/abs/2111.10050) をご覧ください。

 

スケーリング・トレンド

下のプロットは、訓練のためのサンプル数をスケールするとき CLIP モデルのゼロショット性能がどのように変化するかを示しています。ゼロショット性能は ImageNet と ImageNetV2 の両方について確実に向上し、~15M サンプルでは飽和 (saturated) には程遠いです。

 

低精度 CLIP モデルは何故面白いか?

TL;DR: CLIP モデルは、小さいスケールでも、高い実効性のある堅牢性を持ちます。

CLIP モデルは自然な分布シフトに対してより堅牢であるために特に興味をそそられます (CLIP 論文 の Section 3.3 参照)。この現象は、x-軸上に ImageNet 精度そして y 軸上に ImageNetV2 (ImageNet 検証セットを分布シフトで再生) 精度を持つ下の図で示されます。”Standard training” は ImageNet 訓練セット上の訓練を表し、そして CLIP ゼロショットモデルは ★ として示されています。

実効性のある堅牢性の詳細は、以下をご覧ください :

To know more about the factors that contribute to CLIP’s robustness refer to Fang et al., 2022.

 

Acknowledgments

(訳注: 原文 参照)

 

The Team

(訳注: 原文 参照)

 

Citing

(訳注: 原文 参照)

 

以上