开放式剪辑
项目描述
开放式剪辑
欢迎来到 OpenAI 的CLIP(对比语言-图像预训练)的开源实现。
该存储库的目标是启用具有对比图像文本监督的训练模型,并研究它们的属性,例如对分布变化的鲁棒性。我们的出发点是 CLIP 的实现,它在相同数据集上训练时与原始 CLIP 模型的准确性相匹配。具体来说,使用我们的代码库在 OpenAI 的1500 万张 YFCC 图像子集上训练的 ResNet-50 模型在 ImageNet 上实现了32.7%的 top-1 准确率。OpenAI 的 CLIP 模型在 YFCC 的同一子集上训练时达到31.3% 。为了便于实验,我们还提供了用于训练概念字幕数据集中 300 万张图像的代码,其中使用我们的代码库训练的 ResNet-50x4 达到了 22.2% 的 top-1 ImageNet 准确率。
我们通过对与 OpenAI 的LAION-400M以及更大的LAION-2B超集相当大小的数据集进行复制研究来进一步实现这一点。
我们训练过:
- LAION-400M 上的 ViT-B/32 准确率为62.9%,与 OpenAI 的63.2%相当,ImageNet1k 上的零镜头 top-1
- LAION-2B 上的 ViT-B/32 准确率为66.6%。
- LAION-400M 上的 ViT-B/16 实现了67.1%的准确度,低于 OpenAI 的68.3%(此处测量,纸上的 68.6%)
- LAION-400M 上的 ViT-B/16+ 240x240(FLOPS 比 B/16 224x224 高约 50%)达到69.2%的准确度
- LAION-400M 上的 ViT-L/14 的准确率为72.77%,而 OpenAI 的准确率为75.5%(此处测得,纸上为 75.3%)
- LAION-2B 上的 ViT-L/14 准确率为75.3%,而 OpenAI 的准确率为75.5%(此处测量,纸上为 75.3%)
- LAION-2B 上的 ViT-H/14 精度为78.0。迄今为止发布的开源权重的最佳 in1k 零样本。
- LAION-2B 上的 ViT-g/14 精度为76.6。这是按减少的时间表训练的,相同的样本被视为 400M 模型。
正如我们在下面更详细地描述的那样,中等精度的 CLIP 模型已经使我们能够得出关于较大 CLIP 模型的稳健性的结论,因为这些模型遵循可靠的缩放定律。
该代码库正在进行中,我们邀请所有人为使其更易于访问和有用而做出贡献。未来,我们计划增加对 TPU 训练的支持并发布更大的模型。我们希望这个代码库能够促进和促进对比图文学习的进一步研究。如果您有任何其他要求或建议,请提交问题或发送电子邮件。
请注意,部分src/open_clip/
建模和标记器代码是对 OpenAI 官方存储库的改编。
方法
图片来源: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')
image = preprocess(Image.open("CLIP.png")).unsqueeze(0)
text = open_clip.tokenize(["a diagram", "a dog", "a cat"])
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)
text_probs = (100.0 * image_features @ text_features.T).softmax(dim=-1)
print("Label probs:", text_probs) # prints: [[1., 0., 0.]]
为了有效地计算数十亿个嵌入,您可以使用具有 openclip 支持的剪辑检索。
分类任务的微调
该存储库专注于训练 CLIP 模型。要在 ImageNet 等下游分类任务上微调经过训练的零样本模型,请参阅我们的其他存储库:WiSE-FT。WiSE -FT 存储库包含我们关于零样本模型的鲁棒微调的论文的代码,其中我们介绍了一种微调零样本模型的技术,同时在分布偏移下保持稳健性。
数据
概念性字幕
OpenCLIP 读取包含两列的 CSV 文件:图像路径和文本标题。列的名称作为参数传递给main.py
.
该脚本src/data/gather_cc.py
将收集概念字幕图像。首先,下载概念字幕 URL,然后从我们的存储库运行脚本:
python3 src/data/gather_cc.py path/to/Train_GCC-training.tsv path/to/Validation_GCC-1.1.0-Validation.tsv
我们的训练集包含 289 万张图像,我们的验证集包含 13K 幅图像。
YFCC 和其他数据集
除了如上所述通过 CSV 文件指定训练数据外,我们的代码库还支持webdataset,推荐用于更大规模的数据集。预期的格式是一系列.tar
文件。这些.tar
文件中的每一个都应包含每个训练示例的两个文件,一个用于图像,一个用于相应的文本。两个文件应该具有相同的名称但不同的扩展名。例如,shard_001.tar
可能包含诸如abc.jpg
和之类的文件abc.txt
。webdataset
您可以在https://github.com/webdataset/webdataset了解更多信息。我们使用.tar
每个包含 1,000 个数据点的文件,这些文件是使用tarp创建的。
您可以从Multimedia Commons下载 YFCC 数据集。与 OpenAI 类似,我们使用 YFCC 的一个子集来达到上述准确度数字。该子集中的图像索引位于OpenAI 的 CLIP 存储库中。
培训剪辑
设置环境和安装依赖项
康达
# Create a conda environment (heavily recommended)
conda create -n open_clip python=3.10
conda activate open_clip
按照https://pytorch.org/get-started/locally/安装 conda PyTorch
虚拟环境
openclip 也可以通过以下几行与 virtualenv 一起使用:
python3 -m venv .env
source .env/bin/activate
pip install -U pip
make install
按照https://pytorch.org/get-started/locally/安装 pip PyTorch
make install-dev
然后可以运行测试make test
其他依赖
安装 open_clip 包和其余依赖项:
cd open_clip
python setup.py install
如果你想训练模型,你还需要从requirements-training.txt
.
示例单进程运行代码:
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
注意:imagenet-val
是零样本评估的ImageNet验证集的路径,而不是训练集!如果您不想在整个训练过程中对 ImageNet 执行零样本评估,则可以删除此参数。请注意,该val
文件夹应包含子文件夹。如果没有,请使用此脚本。
多 GPU 及以上
该代码已经过多达 1024 个 A100 的实战测试,并为分布式训练提供了多种解决方案。我们包括对 SLURM 集群的本机支持。
随着用于训练的设备数量的增加,logit 矩阵的空间复杂度也会增加。使用朴素的全聚集方案,空间复杂度将为
O(n^2)
. 相反,如果使用标志
--gather-with-grad
和,复杂性可能会变得有效线性--local-loss
。这种改变导致一对一的数值结果作为幼稚的方法。
单节点
我们利用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/
咕噜咕噜
这可能是最容易使用的解决方案。以下脚本用于训练我们最大的模型:
#!/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
从检查点恢复:
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
损失曲线
在具有 8 个 GPU 的机器上运行时,该命令应为概念字幕生成以下训练曲线:
/docs/clip_conceptual_captions.md中给出了概念字幕的更详细曲线。
在 YFCC 上训练 RN50 时,使用与上述相同的超参数,除了lr=5e-4
和epochs=32
。
请注意,要使用其他模型,如ViT-B/32
orRN50x4
或RN50x16
or ViT-B/16
,请使用 指定--model RN50x4
。
启动张量板:
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 - https://laion.ai/laion-400-open-dataset
我们正在努力使用相当大小(和开放)的 LAION-400M 数据集重现 OpenAI 的 ViT 结果。训练后的权重可以在v0.2版本中找到。
LAION400M 权重已在 JUWELS 超级计算机上进行了训练(请参阅下面的致谢部分)。
ViT-B/32 224x224
我们在 ViT-B/32 上复制了 OpenAI 的结果,达到了 62.96% 的 top-1 ImageNet-1k 零镜头精度。
零样本比较(由 Andreas Fürst 提供)
ViT-B/32 使用 128 个 A100 (40 GB) GPU 训练了约 36 小时,4600 GPU 小时。对于 32768 的全局批量大小,每个 GPU 的批量大小为 256。由于在移动到“本地”对比损失之前最初的大小,256 比它本来可以的 (~320-384) 低得多。
ViT-B/16 224x224
B/16 LAION400M 训练达到了 67.07 的 top-1 ImageNet-1k 零样本验证分数。
这是使用更新的 webdataset 0.2.x 代码的第一次主要培训课程。发现了一个错误,该错误会阻止分片在每个时期的节点/工作人员之间正确洗牌。这在训练(第 26 阶段)的一部分中得到了修复,但可能会产生影响。
ViT-B/16 使用 176 个 A100 (40 GB) GPU 训练了约 61 小时,10700 个 GPU 小时。每个 GPU 的批量大小为 192,全局批量大小为 33792。
ViT-B/16+ 240x240
B/16+ 240x240 LAION400M 训练达到了 69.21 的 top-1 ImageNet-1k 零样本验证分数。
该型号与 B/16 的深度相同,但增加了
- 视野宽度从 768 -> 896
- 文本宽度从 512 -> 640
- 分辨率 224x224 -> 240x240(196 -> 225 个令牌)
与上面的 B/16 运行不同,该模型运行干净,没有数据集洗牌问题。
ViT-B/16+ 使用 224 个 A100 (40 GB) GPU 训练了约 61 小时,13620 GPU 小时。每个 GPU 的批量大小为 160,全局批量大小为 35840。
ViT-L/14 224x224
L/14 LAION-400M 训练达到了 72.77 的 top-1 ImageNet-1k 零样本验证分数。
ViT-L/14 使用 400 个 A100 (40 GB) GPU 训练了约 127 小时,50800 GPU 小时。每个 GPU 的批处理大小为 96,全局批处理大小为 38400。已启用 Grad 检查点。
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 224x224
在 LAION-2B 上训练的 ViT-B/32,达到了 65.62% 的 top-1 ImageNet-1k 零镜头准确率。
ViT-B/32 使用 112 个 A100 (40 GB) GPU 进行训练。每个 GPU 的批量大小为 416,全局批量大小为 46592。由 stable.ai 慷慨提供计算。
B/32 的第二次迭代在具有更大全局批量大小和学习率的稳定性.ai 集群上进行训练,达到 66.6% 的 top-1。见https://huggingface.co/laion/CLIP-ViT-B-32-laion2B-s34B-b79K
ViT-L/14 224x224
在 JUWELS Booster 上训练了具有 75.3% top-1 ImageNet-1k zero-shot 的 ViT-L/14。在此处查看模型详细信息https://huggingface.co/laion/CLIP-ViT-L-14-laion2B-s32B-b82K
这些权重使用与其他权重不同的数据集均值和标准差。不使用 OpenAI 的均值和标准,而是[-1, 1]
通过[0.5, 0.5, 0.5]
. 如果使用open_clip.create_model_and_transforms
预训练的权重,则会自动处理。
ViT-H/14 224x224
在 JUWELS Booster 上训练了一个具有 78.0% top-1 ImageNet-1k zero-shot 的 ViT-H/14。在此处查看模型详细信息https://huggingface.co/laion/CLIP-ViT-H-14-laion2B-s32B-b79K
ViT-g/14 224x224
在 JUWELS Booster 上训练了一个具有 76.6% top-1 ImageNet-1k zero-shot 的 ViT-H/14。在此处查看模型详细信息https://huggingface.co/laion/CLIP-ViT-g-14-laion2B-s12B-b42K
与其他 LAION-2B 模型相比,该模型的训练时间更短,只看到 12B 个样本而不是 32+B。它与所见样本中的 LAION-400M 训练相匹配。结果,许多零样本结果较低,但尽管如此,它在一些 OOD 零样本和检索任务中表现得非常好。
YFCC-15M
以下是在 YFCC-15M 上训练的模型的检查点,以及它们在 ImageNet 和 ImageNetV2 上的零样本 top-1 精度。这些模型使用 8 个 GPU 和“示例运行代码”部分中描述的相同超参数进行训练,除了lr=5e-4
和epochs=32
.
- ResNet-50 (32.7% / 27.9%)
- ResNet-101 (34.8% / 30.0%)
CC12M - https://github.com/google-research-datasets/conceptual-12m
- ResNet-50 (36.45%)
预训练模型接口
我们提供了一个简单的模型接口来实例化预训练和未经训练的模型。
注意:许多现有检查点使用来自原始 OpenAI 模型的 QuickGELU 激活。在最新版本的 PyTorch 中,这种激活实际上不如原生的 torch.nn.GELU 有效。模型默认值现在是 nn.GELU,因此应该使用带有-quickgelu
后缀的模型定义来进行 OpenCLIP 预训练权重。所有 OpenAI 预训练的权重将始终默认为 QuickGELU。也可以使用-quickgelu
QuickGELU 将非模型定义与预训练权重一起使用,但会出现精度下降,因为微调可能会在更长的运行中消失。
未来训练的模型将使用 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')]
>>> model, train_transform, eval_transform = open_clip.create_model_and_transforms('ViT-B-32', pretrained='laion2b_s34b_b79k')
扩展趋势
下图显示了当我们缩放用于训练的样本数量时,CLIP 模型的零样本性能如何变化。ImageNet 和ImageNetV2的零样本性能稳步提高,并且在约 15M 样本时远未达到饱和。
为什么低精度 CLIP 模型很有趣?
TL;DR: CLIP 模型具有很高的有效鲁棒性,即使在小规模下也是如此。
CLIP 模型特别有趣,因为它们对自然分布变化更加稳健(参见CLIP 论文中的第 3.3 节)。下图说明了这种现象,x 轴上的 ImageNet 精度和 y 轴上的ImageNetV2(具有分布偏移的 ImageNet 验证集的复制)精度。标准训练表示在 ImageNet 训练集上进行训练,CLIP 零样本模型显示为星号。
正如Taori 等人,2020和Miller 等人,2021所观察到的,在 ImageNet 上训练的模型的分布内和分布外精度遵循可预测的线性趋势(上图中的红线)。有效稳健性将稳健性 量化为超出此基线的准确度,即模型位于红线上方的距离。理想情况下,模型不会受到分布偏移的影响并落在 y = x 线上(训练有素的人工标注者在 y = x 线的一个百分点内)。
尽管使用此代码库训练的 CLIP 模型的准确度远低于 OpenAI 训练的模型,但我们的模型仍然处于提高有效鲁棒性的相同趋势(紫色线)。因此,我们可以研究是什么让 CLIP 稳健而不需要工业规模的计算。
有关有效稳健性的更多信息,请参阅:
要了解有关有助于 CLIP 稳健性的因素的更多信息,请参阅Fang 等人,2022 年。
致谢
我们非常感谢高斯超级计算 eV 中心 ( www.gauss-centre.eu ) 通过约翰·冯·诺依曼计算研究所 (NIC) 在 Jülich 超级计算中心的 GCS 超级计算机 JUWELS Booster 上提供计算时间来资助这部分工作(股份公司)。
团队
该存储库的当前开发由Ross Wightman、Cade Gordon和Vaishaal Shankar 领导。
该存储库的原始版本来自威斯康星大学、谷歌、斯坦福、亚马逊、哥伦比亚和伯克利的一组研究人员。
Gabriel Ilharco*、Mitchell Wortsman*、Nicholas Carlini、Rohan Taori 、Achal Dave、Vaishaal Shankar、John Miller、Hongseok Namkoong、Hannaneh Hajishirzi、Ali Farhadi、Ludwig Schmidt
特别感谢Jong Wook Kim和Alec Radford帮助复制 CLIP!
引用
如果您发现此存储库有用,请考虑引用:
@software{ilharco_gabriel_2021_5143773,
author = {Ilharco, Gabriel and
Wortsman, Mitchell and
Wightman, Ross and
Gordon, Cade and
Carlini, Nicholas and
Taori, Rohan and
Dave, Achal and
Shankar, Vaishaal and
Namkoong, Hongseok and
Miller, John and
Hajishirzi, Hannaneh and
Farhadi, Ali and
Schmidt, Ludwig},
title = {OpenCLIP},
month = jul,
year = 2021,
note = {If you use this software, please cite it as below.},
publisher = {Zenodo},
version = {0.1},
doi = {10.5281/zenodo.5143773},
url = {https://doi.org/10.5281/zenodo.5143773}
}
@inproceedings{Radford2021LearningTV,
title={Learning Transferable Visual Models From Natural Language Supervision},
author={Alec Radford and Jong Wook Kim and Chris Hallacy and A. Ramesh and Gabriel Goh and Sandhini Agarwal and Girish Sastry and Amanda Askell and Pamela Mishkin and Jack Clark and Gretchen Krueger and Ilya Sutskever},
booktitle={ICML},
year={2021}
}