CLIP沟通文本和图像的桥梁。
SOTA的视觉任务模型需要固定的监督数据对,比如-大象,-兔子。这种方式在特定数据集上能够拥有很好的性能,但是在其他未知类别上的性能就会急剧下降。这种监督形式限制了模型的通用性,因为需要额外的数据来重新训练模型。一个识别和的模型并不能识别和。
传统的图像任务都是使用one-hot编码进行,每一类都有其独特的数字标签,比如背景为0,是1,是2,计算机只需要将像素分类成0,1,2。CLIP则是直接从图像的文本描述中进行学习,“a photo of rabbit”,“a photo of elephant”。只需要为每一幅图提供一些文本描述,即可进行CLIP的模型预训练。在一个数百万的大型数据集上进行预训练后,CLIP能取得十分惊艳的泛化性能,以适应任何下游任务,识别、分割、追踪等等。
在NLP中,text-to-text 的预训练方法已经十分成熟,使得大型的预训练模型能够 zero-shot 迁移到下游任务中,也就是现在最热门的 GPT 系列。GPT 的成功也引起了思考,是否可以通过 text-to-image 的方法来预训练大型视觉模型?早在 2016 年就有人尝试用 CNN 模型来预测图像的标题和短语,并证明这种训练方式可以提高模型的 zero-shot 的迁移能力。但这种方式的性能仍会低于标准视觉模型,其中原因之一是**数据集规模。(毕竟大力出奇迹,力大砖飞)。**ChatGPT 已经证明,超大数据集能提高性能和泛化能力。因此 CLIP 选择在一个大规模的自然语言监督的视觉数据集上进行训练。
A sufficiently large dataset
MS-COCO、YFCC100M 是目前常用于视觉训练的大型数据集。CLIP 在这些数据集中进行过滤,大致得到了 15million 的图像数据,与 ImageNet 相当。
此外,还爬取了互联网中的图像数据,包括 400 million 个图像对,并尽可能让类别平衡。
An efficient pre-training method
一个足够大型的数据集能让猪飞起来,那么一个足够好的方法就能让猪变成歼-20。
CLIP最开始使用类似于VirTex的方法,使用CNN来识别图像特征,使用Transformer来处理文本特征,并直接预测图像标题,结果可想而知,猪还是猪,只不过飞的高一点。直接预测标题存在一定困难,并且难以扩展和效率低下。
解决方法就是预测一个整体文本与哪一个图像配对,而不是确切的单词。也就是一句话是一个整体,而不是单词的排列组合。毕竟“一张狗的图像”、“一只狗一样的动物的图像”和“一只动物是狗的图像”在某些意义上是一样的,模型到底怎么理解这句话呢,这增加了复杂度。那么要是把这些文本作为整体,那Transformer模型从中提取特征,这几句话就变成整体的一类“狗”。想要实现这一功能就需要设计一个精妙的模型和损失函数。
给定一个批次的N个图像对(image,txet),那么CLIP就需要预测N×N个配对可能。CLIP从image encoder和text encoder中分别学习到图像表示(image embdding)和文本表示(text embedding),并计算两者的cosine similarity,以最小化cosine similarity损失。(这里称为对比学习)
# 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) # 有N个图像-文本对;每一张图像、文本都有1个label, 一共N张图像、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 # 将两者损失平衡。这一流程称为对比学习。
对于image encoder:CLIP考虑并使用了两个经典模型:ResNet50和Vit,并做了一些修改。
对于text encoder:则选择了Transformer。在文本编码器中使用了mask self-attention。
在模型规模的选择上,CLIP在image endcoder模型深度和宽度上进行同时扩展;在text encoder上则只缩放宽度。
提示工程同样重要,CLIP将文本规范化后,能够得到好几个点的提升。
比如“a photo of xxx, a type of xxx";