目录
- 1 模型结构
- 2 伪代码
- 3 Loss计算方法
官方网站:https://openai.com/index/clip/
论文:Learning Transferable Visual Models From Natural Language Supervision
GitHub:https://github.com/openai/CLIP
Colab:https://colab.research.google.com/github/openai/clip/blob/master/notebooks/Interacting_with_CLIP.ipynb
CLIP的英文全称是Contrastive Language-Image Pre-training,即一种基于对比文本-图像对的预训练方法或者模型。CLIP是一种基于对比学习的多模态模型,与CV中的一些对比学习方法如moco和simclr不同的是,CLIP的训练数据是文本-图像对:一张图像和它对应的文本描述,这里希望通过对比学习,模型能够学习到文本-图像对的匹配关系。
1 模型结构
模型总览图如下图所示,具体的流程如下:
- 模型的输入是一个图像文本对,例如下图的输入图片是一条狗,对应的文本是pepper也是一条狗。
- 图片通过图片编码器得到一些特征,这里的编码器既可以是ResNet,也可以是Vision Transformer。
- 句子通过文本编码器也得到一些文本特征。
- 每个train batch里都有N个这样的图片文本对,就会得到N个图片的特征(IN)和N个文本的特征(TN),CLIP就是在这些特征上去做对比学习。对比学习非常灵活,只需要正样本和负样本的定义,其他都是正常套路。在这里,配对的图片文本对是一个正样本,因为它们描述的是同一个东西,所以特征矩阵里沿着对角线方向上的都是正样本,不是对角线上的元素都是负样本。这里我们有N个正样本和N2-N个负样本。有了正负样本,模型可以通过对比学习的方式去训练起来了,完全不需要任何收工的标注。
对于这种无监督的训练方式,例如对比学习,需要大量的数据,所以OpenAI专门去收集了这样的数据集,里面有4亿个图片和文本对,而且这些数据清理得非常好,质量非常高,这也是CLIP能这么强大的主要原因之一。
CLIP没有分类头,如何做Zero-shot推理呢?作者想出了一个巧妙的利用自然语言的方法,叫prompt template。
这里拿ImageNet做例子:CLIP先把ImageNet里1000类变成一个句子:A photo of a {object}.,用1000类里的物体名去替代句子里的object,从而把一个单词变成了一个句子。这1000个句子通过预训练好的文本编码器,就会得到1000个文本的特征。
这里为什么要做prompt template呢?直接用1000个单词去抽取文本特征也是可以的,但是模型在训练的时候每次看到的都是一个句子,如果在推理的时候把所有的文本都变成一个单词,这样就跟在训练时看到的文本不太一样了,所以效果会稍有下降。而且怎么变成句子也是很有讲究的,所以CLIP论文最后还提出了prompt engineering 和 prompt ensemble这两种方式进一步提升模型的准确率,而不需要重新训练模型。
在推理的时候,不论这时候来了任何一张图片,只要把这张扔给图片的编码器,得到图片特征之后,去跟所有的文本特征计算相似度(cosine similarity)。图像特征跟哪个文本特征最相似,就把对应的句子挑出来,从而完成了分类任务。
2 伪代码
3 Loss计算方法
CLIP采用对称损失函数,简单来说,就是对相似度矩阵分别从行方向和列方向计算Loss,最后取两者的平均。