论文链接:Learning Transferable Visual Models From Natural Language Supervision(通过自然语言处理的监督信号,学习可迁移的视觉模型).
代码链接:CLIP.
CLIP
- 摘要
- 1.引言
- 2.方法
- 3.实验
- 4.与人对比实验
- 5.数据集去重
- 6.Limitation
摘要
现在最先进的视觉系统都是预先定义好的一些物体类别标签的集合,模型学习预测这些预定义的类别从而完成模型的训练,但有限制性的监督信号也限制了模型本身的泛化性,尤其是需要识别新物体类别的时候,都要去收集新的数据训练新的模型。直接从自然语言文本里去得到一些监督信号是一个非常有前途的办法。本文爬取了一个4个亿的图片文本配对的数据集,选择一种自监督的训练方式,利用文本的监督信号训练一个迁移能力强的视觉模型(zero shot模型),证实了用一个非常简单的预训练的任务,就可以高效且可扩展的学习一些最好的图像的表征。本文在超过30个不同的视觉任务和数据集上去做测试,包括 OCR、视频动作检测、坐标定位等细分类任务,CLIP模型在不需要任何数据集的专门训练的情况下均取得不错的效果,尤其是ImageNet上的图像分类,在不使用128万张ImageNet数据集的任何一张图片训练集的情况下直接Zero-shot做推理,获得和之前监督训练res50同样的效果.
1.引言
在过去几年里,从原始的文本数据里去预训练一个模型在 nlp 领域取得了革命性的成功,比如bert, gpt这些模型。不论使用自回归预测的方式,还是使用这种掩码的方式,都是一种自监督的训练方式,它的目标函数与下游任务无关,只是通过预训练得到一个泛化性好的特征。随着计算资源增多,模型变大,数据变多,这个模型的能力也会稳健的提升。当直接用在下游任务上的时候,不需要针对那个任务的输出头,或者针对那个数据集做一些处理。这表明,利用自监督的信号去训练整个模型的框架下,大规模的没有标注的数据其实比手工标注的质量非常高的数据集更好,但在视觉领域,通常还是在ImageNet数据集上预训练一个模型,但预训练的模型总是有诸多限制。之前也有相关工作,比如VirTex,ICMLM 和 ConVIRT等尝试把图片和文字结合起来学到更好的特征。VirTex 用自回归的预测方式做模型的预训练,ICMLM 用这种掩码(类似完形填空)方式去做预训练,ConVIRT 与CLIP非常类似,但只在医疗图像上做了实验。这些方法只是在几十万张图片上训练,并且只训练了几天,与NLP那种亿级规模的数据集,训练了几年的规模比起来,效果肯定不佳(作者这里把所有的这些硬件都统称为是加速器,比如 vit 模型用了2,500个 TPU V3/天,如果用一个 TPUV3核训练这个模型需要训练2500天。大概就是7年)。因此,本文从数据规模和模型规模2方面提升,首先收集一个超级大的图像文本配对数据集,包括400Million(4亿)图片文本的配对,模型上测试ResNet,Efficient Net,Vision Transformer large等8个模型,最小的模型和最大的模型之间的计算量差了大概100倍(two orders of magnitude),迁移学习效果与模型大小正相关。
2.方法
第二章介绍clip如何训练,以及为什么使用对比学习训练。
2.1 自然语言监督clip的核心就是用自然语言信号训练一个比较好的视觉模型。这个方法并不新,但是之前的方法写的不同名字,容易产生混淆,而且用的数据集规模比较小,本文对之前的方法进行归纳总结,并且使用更大规模的数据集。之前这一领域进展不太顺利,第一个原因是,Nlp模型本身训练比较难,所以之前用的topic model或者n gram等复杂方式不太好做跨模态的训练,随着transformer和自监督学习的兴起,NLP革命性的实现具有上下文语义环境的学习方式。 在自监督学习的方式下,NLP可以利用无限的文本监督信号训练模型。用自然语言的文本监督信号训练视觉模型的好处有:
- 不需要再去标注数据,也不需要限定类别的数量。如果只在网上下载图片,文本配对,而不标注数据,那么,数据集的规模很容易扩大,而且现在的监督信号是文本,因此,模型输入输出的自由度就大很多, 不需要像之前一样受限于标注的类别数量。
- 现在的训练是文本和图像绑定在一起,学习到的不单是视觉特征,而是视觉文本的多模态特征,这样很容易做zero shot的迁移学习。如果是单模态的学习,不论是单模态自监督学习的Moco,还是半模态掩码学习的MAE,都只能学到视觉特征,而无法和自然语言联系在一起,也很难做zero shot的迁移。
2.2 构建大规模数据集
之前的数据集质量高的规模小,比如ms coco ,Visual Genome只有10万个训练样本,YFCC 100Million 有1个亿,规模大但质量差,清理之后缩小6倍,只有1,500万张图片,这个规模和ImageNet差不多。因此本文自己构建了一个大规模训练集WIT(web Image Text 数据集),有4亿图片文本对,与GPT2的WebText数据集差不多接近.
2.3 选择有效的训练方法
视觉模型都是非常大,训练也都非常贵,比如在 instagram 数据集上训练ResNeXt101-32x48d需要19个GPU年 ,Noisy Student EfficientNet-L2训练需要33个 TPUv3核/年,因此从自然语言直接学开放世界里所有的视觉概念耗费资源太大,训练的效率对于多模态预训练的成功至关重要,因此本文验证了几种方法。
-
virtex的方式:图像用卷积神经网提取特征,文本用Transformer提取特征, 然后从头开始训练,任务是给定一张图片,预测图片对应的文本,属于一个预测性任务
-
选择对比学习的方式:如果是预测一个图像所对应的文本,需要逐字逐句的去预测,非常复杂,效率较低,因为一张图像可能有多种文本描述,如果是使用对比学习的方法,预测一个图像和一个文本是否配对,那任务就简单很多。 将预测性目标函数换成对比性目标函数,训练效率提高了四倍。
图中蓝线是 OpenAI的 gpt 的模型方法,基于Transformer做预测型的任务,中间橘黄色的线指的是一种 bag of words 的方式,就是不需要逐字逐句的预测文本,文本已经全局化的抽成了一些特征,所以相应的约束被放宽了。约束放宽以后,训练效率立即提高了三倍,如果进一步放宽约束,不再去预测单词,只用对比学习的方式判断是不是图片文本对,如图中绿线,训练效率又进一步的提高了四倍。# image_encoder - ResNet or Vision Transformer # text_encoder - CBOW or Text Transformer # I[n, h, w, c] - minibatch of aligned images # T[n, l] - minibatch of aligned texts # W_i[d_i, d_e] - learned proj of image to embed # W_t[d_t, d_e] - learned proj of text to embed # t - learned temperature parameter # extract feature representations of each modality I_f = image_encoder(I) #[n, d_i] T_f = text_encoder(T) #[n, d_t] # joint multimodal embedding [n, d_e] I_e = l2_normalize(np.dot(I_f, W_i), axis=1) T_e = l2_normalize(np.dot(T_f, W_t), axis=1) # scaled pairwise cosine similarities [n, n] logits = np.dot(I_e, T_e.T) * np.exp(t) # symmetric loss function labels = np.arange(n) loss_i = cross_entropy_loss(logits, labels, axis=0) loss_t = cross_entropy_loss(logits, labels, axis=1) loss = (loss_i + loss_t)/2
上面是CLIP实现的核心代码,具体步骤如下:
- 图像的输入I[n,h,w,c] ,文本的输入T[n,l],其中n就是 batch size,l 是序列长度。
- 图像和文本的输入分别通过 Image Encoder 和 Text Encoder 得到图像和文本的特征I_f,T_f,其中 Image Encoder 可以是 ResNet 或 Vision Transformer,Text Encoder 可以是 CBOW 或 Text Transformer。
- 在得到I_f和T_f后,这里还有一个投射层W_i, W_t,投射层主要就是学习如何从单模态变到多模态所以作者这里说这是一个合并的多模态。
的一个特征用来学习如何从单模态变成多模态,然后再做 L2 归一化,就得到了用来对比学习的特征I_e,T_e。 - 有了n个图像的特征和n 个文本的特征之后,计算 cosine similarity,得到的相似度用来做分类的logits。
- logits 和 ground truth 的labels 计算交叉熵损失,loss_i,loss_t分别是 Image 和 Text 的 loss,最后求平均就得到了loss.最后把两个 loss加起来求平均这个操作在对比学习中比较常见,从最开始的 SimCLR 到 BYOL一直到最新的MOCOv3,DINO这些工作全都是用的这种对称式的目标函数,这里的ground truth用的是arrange function生成,值从1开始1234567一直到n,这个与MOCO创建ground truth方式不一样,因为对于 moco,正样本永远都在第一位,所以moco的ground truth全都是0,只有在0这个位置也就是第1号这个位置是正样本。但对于CLIP,它的正样本全在对角线上的,因此用这种方式创建ground truth。
CLIP实现中还有一些细节:1)由于数据集规模较大,因此不会有overfitting 的问题,2)最后并没有用这种非线性的投射层,而是用了一个线型的投射层。在SimCLR,MOCO 这一系列对比学习论文中,非线性的投射层会比用线性的投射层带来将近10个点的这个性能提升。但在多模态预训练过程,线性非线性没有太大关系,非线性的投射层应该只是用来适配纯图片的单模态学习,3)算法不需要做数据增强,只用了随机裁剪,4)temperature 这个超参数非常重要,本文将它设置成一个可学习标量,直接在模型训练过程中优化而不需要当成一个超参数,最后再去调参。
2.4 模型选择与缩放
本文验证了两种不同的图像编码器架构。第一种使用ResNet-50 作为图像编码器的基本架构,并且对原始版本进行了几个修改:1)使用ResNet-D改进,2)antialiased的rect-2模糊池化,3)用一个注意力池化机制替换了全局平均池化层。注意力池化使用一个“transformer-style”多头QKV注意力的单层,其中查询是根据图像的全局平均池化表示来条件化的。第二种使用Vision Transformer(ViT) ,只是在transformer之前的patch组合和位置embedding中添加了一个额外的layer normalization,并使用了稍微不同的初始化方案。
文本编码器是一个基于Radford等人的架构修改的Transformer。本文使用一个63M参数的12层512宽的模型作为基本大小,其中包含8个注意力头。transformer使用一个小写的字节对编码(BPE)表示文本,其词汇大小为49,152。为了提高计算效率,最大序列长度被限制在76。文本序列用[SOS]和[EOS]标记括起来,transformer的最高层在[EOS]处的激活函数被视为文本的特征表示,该表示被层归一化后,线性投影到多模态embedding空间中。在文本编码器中使用了掩码自注意力,以保留使用预训练语言模型初始化或将语言建模作为辅助目标的能力。
2.5 训练策略
作者训练了八个模型,分别是5个resnet,还有3个vit,ResNet有 res50和res101,还有三个残差网络根据EfficientNet 的方式把模型里Channel的宽度,模型的深度以及输入的大小都做了调整,从而得到了几个残差网络的变体,即ResNet 504,ResNet 5016和 ResNet 50*64分别对应原始的ResNet50 的4倍,16倍和64倍的的计算量。Vision Transformer使用ViTBase/32,ViTBase/16和 ViTLarge/14。这里的32 16 14分别指的是这个patches的大小。每个模型训练32个epoch,用 Adam优化器训练,最小的Batchsize是32768。数据增强方面,只用了随机裁剪,没有用其他的增强策略。训练的时候用到了混精度训练,混精度训练在transformer的训练中应用非常普遍,因为对于大部分任务来说,混经度训练一般不会掉点,甚至还有可能提点,占用的内存也减少一半,训练的速度大幅提高, 还有其他的节省内存的策略, 最大的resnet模型res 50×64,在592个v100 gpu上训练18天,最大的vit模型,在256个v100上花费12天,因此,训练vit比训练resnet高效。
3.实验
3.1 zero shot的迁移3.1.1 研究动机
之前的自监督或者无监督主要研究的是特征学习的能力,目标就是学习一种泛化性比较好的特征。比如moco,simclr,dino.但即使学到了很好的特征
如果想应用到下游任务,还是需要有标签的数据去做微调,这就牵扯各种这样的问题,也就是作者研究 zero shot迁移的研究动机。
3.1.2 CLIP的zero shot推理
在训练的过程中,模型的输入是一个图片和文字的配对,比如这里图片里画的是一只狗,配对的文字是Pepper the aussie pup。图片通过一个图片编码器得到了一些特征,这里的编码器呢既可以是ResNet,也可以是Vision Transformer;文字通过一个文本编码器,得到一些文本的特征。假如每Training Batch都有 n 个这样的图片文本对,即n 张图片,n个句子,那就会得到n个图片特征,n个文本的特征,CLIP在这些特征上去做对比学习。对比学习非常的灵活,只需要一个正样本和负样本的定义,这里配对的一组图片文本就是一个正样本。所以这个特征矩阵里沿着这个对角线方向上都是正样本,因为I1 T1 I2 T2 这些本身就都是配对的,剩下这个矩阵里所有不是对角线上的元素都是负样本,因此有n个这个正样本,有n^2-n个负样本,模型就可以通过对比学习的方式训练起来,完全不需要任何手工的标注。这种无监督的预训练方式需要大量的数据,OpenAI收集了一个数据集,里面有4亿个图片和文本的配对。
CLIP 的模型经过预训练之后,其实只能去得到一些视觉上和文本上的特征,并没有在任何分类的任务上继续训练或者微调,所以它没有分类头。作者这里利用自然语言的一种方法,也就是prompt template,以ImageNet为例,CLIP 呢就是先把ImageNet的1000个类变成一个句子。ImageNet有1000个类,因此生成1000个句子,这1000个句子通过之前预训练好的文本编码器,得到1000个这个文本的特征。这么做的原因是模型训练的时候用的都是句子,如果推理时候直接使用单词抽取的文本特征,那推理和训练使用的文本特征就不一样了,效果会稍有下降。生成句子的方式直接影响模型准确率,CLIP提出prompt engineering和 prompt ensemble 两种方式生成句子提高这个模型的准确率。当推理时,输入任意一张图片,图片经过编码器得到特征之后,和所有文本特征计算cosine similarity,最相似的文本对应的句子就是图片对应的类别,这样就完成了图片分类的任务。最大的优势在于,分类的类别数没有提前定好的标签列表限制,可以用任意类别单词构建句子实现图像分类。
3.1.3 与VISUAL N-GRAMS的对比结果
3.1.4 prompt engineering和 ensemble
最近prompt的学习方法不论是在 nlp 还是在 cv 领域都非常火,都非常的火,它是做做推理的时候用的方法,而不是在预训练阶段,所以不需要太多计算资源,但因为效果好,所以影响力非常大。prompt对应的中文含义是提示,也就是文本的引导作用。作者这里举了两个比较常见的例子,第一个是Polysemy多义性,也就是一个单词可以同时拥有很多的含义,如果做文本和图片的匹配的时候,每次只用标签对应的一个单词去做文本的特征抽取,就有可能面临到这种问题,算相似度有可能就是错的。作者这里使用一个提示的模板(prompt template),所有的标签都变成这是一个什么的图片这种句子,多义性的问题有时候就会解决,准确率提升了1.3%。prompt ensembling就是多用这种提示的模板做多次推理,然后把结果呢综合起来ensemble ,一般结果更好。作者这里用了80个提示模板Ensemble(CLIP代码库下notebook),比如说这是一张有很多东西的图片,这个模板就适用于里面有很多物体的图片,比如说这个模板 a photo of the hard to see有可能适合于那些特别特别小的物体,总之让提示模板尽量的描述到每一个物体可能所处的环境。
3.1.5 zero-shot CLIP 性能分析
linear probe就是把一个预训练好的模型冻住,只从里面去抽特征,只训练最后那一层那个 fc 分类头层去做有监督的分类任务。这里这个 res50是在ImageNet上用有监督的方式训练好一个模型,从中抽特征,然后在这些下游任务上去添加新的分类头,在新分类头上做linear probe微调。作者把这种方式当成基线,在图5中,如果CLIP 模型比他表现的好,就列在上面用绿色表示,加号代表CLIP 模型相比于这个基线提升了多少,对于下面蓝色的指CLIP 模型相对于基线要降低了多少的性能。下图可以看出,在大多数数据集上(16个),Zero Shot的CLIP 模型都超越有监督预训练好的 res50。对于普通的物体分类的数据集,CLIP能很好的做zero shot的迁移,但是对于更难的任务,更难的数据集。比如dtd这种对纹理进行分类的数据集,或者 CLEVRCounts这种给图片中的物体计数的任务,对CLIP 就非常难,CLIP 模型在这些数据上的表现不好。
对于上面那些更难的数据集,作者认为Few Shot 会比 zero shot的衡量更合理,所以在图6中,作者对比了zero shot CLIP、 Few Shot CLIP以及之前Few Shot 的那些方法。之前的这些方法首先预训练模型,然后把模型的参数冻住,只从里面去抽特征做linear probe,训练最后的分类头,这需要下游数据集有这种有标签的数据,这个算是 Few Shot。对于 CLIP 模型也一样,作者把CLIP里面的图片编码器拿出来冻住,然后做linear probe。图6的横坐标是数据集里每一个类别里用了多少个训练样本,0就是 zero shot 什么都不用,也就是 zero shot of the CLIP,别的这些方法因为没有和自然语言相结合没办法做Zero Shot,所以他们最低从 one shot 开始,从 one shot 到 two shot four shot,最后到 sixteen shot,图6的纵坐标是 average score,也就是平均的分类准确度。这里是20个数据集做平均,因为有7个数据集里的部分类别训练样本不足16个,不容易画曲线,所以去掉了,所以这里的每一条曲线是20个数据集结果的一个合并,而并不单单是一个数据集上的结果。
图6中可以看出一些结论
- 蓝色的曲线对应bit 模型,它也是 google 的一篇工作叫 big transfer,它主要就是做迁移学习,算是迁移学习或者说 Few Shot的迁移学习里表现最好的工作之一。这里的bit 的模型是在ImageNet21 k 上做预训练的,数据集比较大所以这条蓝色的曲线是一个很强的Base Line, zero shot CLIP不用任何训练样本直接就和bit打成平手,可见利用自然语言的威力。
- 紫色的曲线是对CLIP里的图片编码器做Few shot的 linear probe,可以发现当这个训练样本只有1、2、4的时候,用了训练样本的 Few Shot的方式不如直接做Zero Shot的 CLIP,再次证明了用文本去做这个引导的多模态的学习非常强大。
- 随着这个训练样本的增多,Few Shot学习的CLIP模型效果最好,不仅超越了之前的方法,验证了CLIP 模型的强大,同时还超越了Zero Shot CLIP,验证了作者上面的观点,对于较难的数据集,有一些训练样本对于性能提升非常有必要
3.2 表征学习
之前不论无监督还是自监督表征学习,都是先预训练一个模型,然后在下游任务用全部的数据做微调,所以如果用上全部数据,就可以和之前的特征学习的方式公平对比,有很多种方式衡量模型学到的这个特征,最常见的两种方式是 linear probe和fine tune。Linear Probe就是把预训练好的模型冻住,然后在上面训练一个分类头;Fine-tune微调就是把整个网络放开,直接做端到端的学习,一般更灵活,而且在下游数据集比较大的时候,微调往往是要比 linear probe 的效果要好很多。作者这里用 linear probe,原因是:
- CLIP为了研究跟数据集无关的预训练方式,如果下游数据集足够大,整个网络全都放开做微调,有可能预训练的模型并不好,但在微调的过程中不断优化,最后效果也很好,这样就无法分辨预训练的模型到底好不好,而 linear probe 用线性的分类头的方式不太灵活,整个网络大部分都是冻住的,只有最后这一层 fc 可以训练,可学习的空间比较小,如果预训练的模型没有训练好,即使在下游任务上训练再久,也很难优化到一个特别好的结果,因此能更准确的反映出预训练模型的好坏。
- linear probe 不太用调参,大大简化了方法的对比。因为CLIP涉及到大量数据集,若端到端的微调,有太多可以调的超参和设计方案,需要为每个数据集设计超参数工作量较大。
图10展示了对比结果,这里对比了很多的方法,包括CLIP,有监督的EfficientNet, 伪标签EfficientNet,弱监督的在 instagram 上训练的模型,对比学习自监督学习的模型以及一些经典的有监督学习基线模型,横坐标是一张图片做一遍前向过程需要用多少的计算量,纵坐标是在很多数据集上的平均准确率,准确度越高、用的时间越短,效果越好,因此越靠左上角点的模型在精度和速度上的trade-off就做的更好。右图把27个数据上的效果取平均,CLIP 对应的红色五角星和红色的空心的五角星效果都是最好的,证明 CLIP 模型的强大之处,不仅zero shot、Few shot,即使用全部数据训练,CLIP 同样能超越别的所有模型,左图是之前有个工作提出12个数据集的一个集合,CLIP用更大的模型Vision Transformer效果还是很好,但是用残差网络的 CLIP 就比别的有些方法要差,但这12个数据集与ImageNet关联性很高,所以那些模型在ImageNet数据集上做过有监督的预训练效果就会特别好。作者又用最大的EfficientNet,用 noise student也就是伪标签的方式去训练那个模型,再把 CLIP 模型和这个模型全都冻住,从里面抽特征,最后做logistic regression,结果在27个数据集里,CLIP 都超过EfficientNet。
3.5 分布偏移的鲁棒性
当数据分布改变的非常厉害的时候,普通模型可能掉点非常严重,但是CLIP训练的模型非常的稳健。
4.与人对比实验
对于 CLIP 模型难的类对于人也很难,对于 CLIP简单的类对于人也简单。
5.数据集去重
证明数据集之间没有重叠的问题,CLIP模型效果好是因为本身泛化性好。
6.Limitation
- CLIP在很多数据集上平均看可以和一个比较简单的基线模型效果相同,比如ImageNet上训练的 res 50的模型,但 res 50比 state of the art差很远,CLIP Zero Shot在ImageNet上76.2,最新最大的Vision Transformer或者MAE都是88 89 甚至90,还是有一定差距。如果扩大规模,也就是增加数据集,加大模型,CLIP的性能还能继续提高,但若想弥补十几个点的差距,还要在现在训练CLIP计算量的基础上乘以1000,即如果要和vit平手,需要4000亿数据,代价太大,需要有新的方法。
- CLIP 在有些数据集上 Zero Shot的结果并不好,比如在某些细分类的数据集,或者抽象的更难的任务比如计数效果不行
- CLIP 虽然泛化很好,对于很多自然图像的分布偏移相对稳健,但如果推理的时候,数据和训练的数据差的非常远,out of distribution,CLIP 模型泛化照样很差,比如MNIST这种生成数据集。
- 虽然CLIP可以做Zero Shot的分类任务,但还是从给定的类别里去做的选择,一种更灵活的方式就是直接生成图像的标题,这样一切都是模型自动化处理,生成新的输出,但受限于计算资源的问题,无法训练图像标题生成的基线网络,最好能将对比学习的目标函数和生成式的目标函数合在一起,这样既有对比学习训练模型的高效性,又有生成式模型的灵活性。
- 数据利用率低,训练需要4亿数据,最好能减少数据用量,比如数据增强,自监督,伪标签等
- CLIP用的27个数据集做测试,但这27个不一定就具有代表性,而且训练过程中反复用这些数据集测试,可能无形之中已经做了指导,最好是能够有新的zero shot的数据集供大家测试。
- 数据从网上爬取的,没有审查过滤清洗,可能带有偏见。
- CLIP模型的提出并不是为了 Few shot的这种情况,所以就导致一个非常奇怪的现象,当给 CLIP 提供了一些训练样本one shot two shot four shot 的时候,结果反而还不如直接用 zero shot。