来源
Simple Implementation of OpenAI CLIP model: A Tutorial | Towards Data Science
【小白】一文读懂CLIP图文多模态模型_clip模型-CSDN博客
从 CLIP 聊聊多模态自监督学习新范式 - 知乎 (zhihu.com)
正文
clip出自Learning Transferable Visual Models From Natural Language Supervision(从自然语言监督中学习可迁移的视觉模型)
OpenAI宣布了两个新模型:DALL-E和CLIP,这两个模型都是以某种方式连接文本和图像的多模态模型。
用于对比语言-图像预训练 。简而言之,这个模型学习整个句子 和它描述的图像之间的关系;从某种意义上说,当模型被训练时,给定一个输入句子,它将能够检索与该句子对应的最相关的图像。这里重要的是,它是在完整的句子上训练的,而不是像汽车、狗等单个类。直觉是,当在整个句子上训练时,模型可以学习更多的东西,并在图像和文本之间找到一些模式。
使用 image encoder 可以是 resnet / Vit 编码图片, Text encoder 是 bert encoder,编码后的两个模态向量在大 batch 内做对比学习训练;训练集用了可怕的 400 million image text pair.
实现编码Simple Implementation of OpenAI CLIP model: A Tutorial | Towards Data Science
python
def forward(self, batch):
# 编码到固定大小的向量
image_features = self.image_encoder(batch["image"])
text_features = self.text_encoder(
input_ids=batch["input_ids"], attention_mask=batch["attention_mask"]
)
# 投影到共享空间
image_embeddings = self.image_projection(image_features)
text_embeddings = self.text_projection(text_features)
# Calculating the Loss
# 计算图像与文本间的相似度 Text @ Image.T
logits = (text_embeddings @ image_embeddings.T) / self.temperature
# 计算图像之间的相似性
images_similarity = image_embeddings @ image_embeddings.T
# 计算文本间的相似性
texts_similarity = text_embeddings @ text_embeddings.T
# targets包容了边界条件:即类似的图片or描述应该被考虑为同个嵌入
targets = F.softmax(
(images_similarity + texts_similarity) / 2 * self.temperature, dim=-1
)
#
texts_loss = cross_entropy(logits, targets, reduction='none')
#
images_loss = cross_entropy(logits.T, targets.T, reduction='none')
loss = (images_loss + texts_loss) / 2.0 # shape: (batch_size)
return loss.mean()
def cross_entropy(preds, targets, reduction='none'):
log_softmax = nn.LogSoftmax(dim=-1)
loss = (-targets * log_softmax(preds)).sum(1)
if reduction == "none":
return loss
elif reduction == "mean":
return loss.mean()
论文本身的伪代码:
关于loss:在线性代数中,衡量两个向量是否有相似特征,余弦相似度
逻辑上去解释这个公式:
如何理解应用于CLIP的对比损失函数的优化方式? - 思念殇千寻的回答 - 知乎
即CLIP是学习(image, text)图文对之间的正确匹配的。在我看来,这个正确匹配有两个对称的方面:
1)对于每一个caption,和它吻合的图片得到label 1,和它不吻合的图片得到label 0。(这个对应于caption_loss)这个方面可以使用CrossEntropy来监督。
2)对于每一个image,和它吻合的caption得到label 1,和它不吻合的caption得到label 0。(这个对应于image_loss)这个方面也可以使用CrossEntropy来监督。
而将两个loss相加除以2,得到的损失函数就同时考虑了两个方面了。如果一个模型在这两个方面都做得好,那么大概率(或者说一定?)是能够成功学习到correct pairings of a batch of (image, text) 的。text_embeds @ image_embeds,所以正着看就是为每个caption寻找吻合的image,转置后反着看就是为每个image寻找吻合的caption。
读论文记录:
下游应用、
引言
- CLIP 的突出贡献是利用 大数据(400 million image text pair 四亿)、 大模型(VIT large)和 大算力 (12 days on 256 v100 GPUs)达到了非常好的性能、泛化性和鲁棒性。
- 验证了10个图像编码器,从ResNet到Vit,得到结论即泛化性能和模型的规模大小成正比。
- 迁移学习(zero-shot),在30个未经训练的数据集上通过简单的分类头训练就能达到resnet的效果。
- 泛化性:不局限于分类任务,而是专注于文本相似度,可以预测到更为准确贴合的标签。
- 利用nlp的思想,把无监督与文本训练数据和图像结合起来。
模型、
训练目标设计与训练效率的关系:从生成式、到词袋预测(多分类)、再到对比学习(判断是否最匹配),模型训练效率稳步提升。
因为clip本身模型大+数据集大的特性,一些训练上的设置和普通的对比学习有差异。比如temperature它设置的是可学习的(调参成本太高),学习头使用的是线性的而不是非线性的(正常对比学习这里会差10个点,但是数据量太大、以及这里引入了文本模态并非单一图像模态这里基本没区别)
图像编码器选型:
实验
clip迁移到下游预训练任务:
prompt engineering and ensembling
动机:多义性与歧义性,加上上下文语义信息可以减弱;预训练的时候用的是句子。
结果分析-zeroshot
zero-shot在难数据集上表现不好(纹理分类、计算图片有几个物体),在简单数据集上表现出色
结果分析-fewshot
平均了20个数据集(有些每个class的label少于16个),★代表zero-shot,
结果分析-全参数
动机【为什么Linear Probe而不用微调】:为了验证预训练模型的好坏,所以尽量减少对模型主题/参数的调整。
模型局限性
- clip在zero-shot上达到了resnet的效果,但是并没有达到sota(ViT、MAE、Noisy Student),还差了十几个点。
- clip在难数据集上差很多
- clip在out of distribution上表现的不好(mnist)(27个数据集不能代表全部的zero-shot)
- 非生成式
- 很贵,用的数据很多(自监督、伪标签能更好的利用数据)
- 在某些few-shot场景上可能会降点
基础知识&扩展知识
resnet / Vit 编码
bert encoder
bert、gpt、t5
n-grams