CLIP
Learning Transferable Visual Models From Natural Language Supervision
CLIP全称Constrastive Language-Image Pre-training,是OpenAI推出的采用对比学习的文本-图像预训练模型。CLIP惊艳之处在于架构非常简洁且效果好到难以置信,在zero-shot文本-图像检索,zero-shot图像分类,文本→图像生成任务guidance,open-domain 检测分割等任务上均有非常惊艳的表现
Zero-Shot Learning
介绍
零次学习(Zero-Shot Learning,简称ZSL)假设斑马是未见过的类别,但根据描述外形和马相似、有类似老虎的条纹、具有熊猫相似的颜色,通过这些描述推理出斑马的具体形态,从而能对斑马进行辨认。零次学习就是希望能够模仿人类的这个推理过程,使得计算机具有识别新事物的能力,如下图所示
有监督学习可以使得模型在已知数据集已知标签的情况, 得到让人惊讶的效果。但是, 我们对于人工智能的期望要更加的高, 我们期望模型具有推理的能力, 识别新类别的能力。ZSL就是希望我们的模型能够对其从没见过的类别进行分类,让机器具有推理能力,实现真正的智能。其中零次(Zero-shot)是指对于要分类的类别对象,一次也不学习。
问题
领域漂移问题(domain shift problem)
同一种属性,在不同的类别中,视觉特征的表现可能很大。如图3所示,斑马和猪都有尾巴,因此在它的类别语义表示中,“有尾巴”这一项都是非0值,但是两者尾巴的视觉特征却相差很远。如果斑马是训练集,而猪是测试集,那么利用斑马训练出来的模型,则很难正确地对猪进行分类。
枢纽点问题(Hubness problem)
在高维空间中,某些点会成为大多数点的最近邻点。由于ZSL在计算最终的正确率时,使用的是K-NN,所以会受到hubness problem的影响。
语义间隔(semantic gap)
样本的特征往往是视觉特征,比如用深度网络提取到的特征,而语义表示却是非视觉的,这直接反应到数据上其实就是:样本在特征空间中所构成的流型与语义空间中类别构成的流型是不一致的。这使得直接学习两者之间的映射变得困难。
模型详解
模型特点
- 多模态的, 结合CV和NLP
- zero-shot, 不受类别数量的影响
- Constastive learning, 两个encoder得到的向量表征映射到同一个空间, 消去不同模态之间的向量表示的gap, 便于后续的cosine相似度的计算
训练
对比式无监督训练
假设我们有 N 个图像与它们各自的描述集合,例如:<image1, text1>, <image2, text2>, <imageN, textN>。
对比式无监督预训练的目的是同时训练图像编码器和文本编码器,产生图像嵌入[I1, I2 ... IN]和文本嵌入[T1, T2 ... TN],其方式为:
正确的
以对比的方式,不相似的对<I1,T2>, <I1,T3>...<Ii,Tj>(其中 i≠j)的余弦相似性最小。
以clip_res50为例
该模型使用对称的交叉熵损失函数作为其优化目标。这种类型的损失函数既能优化图像到文本的方向,也能有优化文本到图像的方向(对比损失函数矩阵同时保持<I1,T2>和<I2,T1>的余弦相似度)
加速训练: 预测文本描述-图片 -> bag of words, 即将文本抽象为特征, 预测特征-图片 -> 预测文本-图片
- 首先接收 N 个
对。 - text encoder是一个标准的 Transformer 模型,进行了 GPT2 风格的修改。图像编码器可以是 ResNet 或 Vision Transformer。
- 对于每个图像,图像编码器都会计算一个图像向量。比如第一幅图像对应于 I1 向量,第二幅对应于 I2 向量,以此类推。每个向量的大小为 de(de 是潜在维度的大小)。因此,这一步的输出是 N * de 矩阵。clip_res50的de维度是512
- 同样地,文本描述被压缩成文本嵌入[T1, T2 ... TN],产生一个 N * de 矩阵。
- 最后,我们将这些矩阵相乘,计算每张图片和文本描述之间的成对余弦相似度。这将产生一个 N * N 矩阵,如上图所示。
- 目标是使对角线上的余弦相似度最大化,这些是正确的
对。以对比的方式,非对角线元素的相似度应该最小化(例如,I1 图像由 T1 描述,而不是由 T2、T2、T3 等描述)。
Zero-Shot 分类
提供一组文本描述,如一张狗或猫吃冰淇淋的照片(任何我们认为最能描述一张或多张图像的内容)。这些文本描述被编码为文本嵌入。然后,我们对图像做同样的事情——图像被编码成图像嵌入。最后,CLIP 计算图像嵌入和文本嵌入之间的成对余弦相似度。具有最高相似度的文本提示被选择为预测结果。当然,我们也可以输入一张以上的图像。CLIP 巧妙地缓存了输入的文本嵌入,所以它们不必为其余的输入图像重新进行计算。这就是 CLIP 端到端的工作方式。
数据
CLIP 使用多达 30 个公共数据集进行预训练。用大量的数据拟合一个大型语言模型是很重要的。对于如CIFAR只有一个单词作为标签的数据集, clip的作者会将标签加上“prompt”转成句子, 如dog -> A photo of a dog
code
一个例子, 预测图片对应的text
import torch
import clip
from PIL import Image
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-B/32", device=device)
image = preprocess(Image.open("CLIP.png")).unsqueeze(0).to(device)
text = clip.tokenize(["a diagram", "a dog", "a cat"]).to(device)
with torch.no_grad():
image_features = model.encode_image(image)
text_features = model.encode_text(text)
logits_per_image, logits_per_text = model(image, text)
probs = logits_per_image.softmax(dim=-1).cpu().numpy()
print("Label probs:", probs) # prints: [[0.9927937 0.00421068 0.00299572]]
将text 编码和image编码进行 norm、矩阵相乘, 如上图
def forward(self, image, text):
image_features = self.encode_image(image)
text_features = self.encode_text(text)
# normalized features
image_features = image_features / image_features.norm(dim=1, keepdim=True)
text_features = text_features / text_features.norm(dim=1, keepdim=True)
# cosine similarity as logits
logit_scale = self.logit_scale.exp()
logits_per_image = logit_scale * image_features @ text_features.t()
logits_per_text = logits_per_image.t()
# shape = [global_batch_size, global_batch_size]
return logits_per_image, logits_per_text
reference
https://blog.csdn.net/lsb2002/article/details/132275132
https://xie.infoq.cn/article/f7680d1fe54f4a0e2db7acbd3
标签:features,clip,text,image,图像,logits,文本,cnblog From: https://www.cnblogs.com/xle97/p/18215852