1 模型说明

含义:CLIP(Contrastive Language-Image Pre-training)
git地址:https://github.com/openai/CLIP
paper:https://arxiv.org/abs/2103.00020
安装:pip install git+https://github.com/openai/CLIP.git
或者使用另一个开源复现:pip install open_clip_torch
CLIP模型用4亿对来自网络的图文数据对,将文本作为图像标签,使用NLP监督预训练图像分类器,使用256个GPU训练两周。模型为350M,通过蒸馏转为48M,后续又转为24M。

1.1 训练过程

  1. 2个encoder分别处理文本和图片数据,text encoder使用Transformer,image encoder用了2种模型,ResNet和Vision Transformer(ViT);
  2. encoder representation直接线性投影到multi-modal embedding space;这里包含了所有需要学习的参数
  3. 计算2模态之间的cosine similarity,让N个匹配的图文对相似度最大,不匹配的图文对相似度最小;具体来说,是横着计算一遍交叉熵,再竖着计算一遍交叉熵,然后取平均值。

伪代码如下:T_f和I_f是编码结果,W_i和W_t是embedding参数,T_e和I_e就是多模态结果,两者相乘得到的logits就是上图的矩阵,然后和对角矩阵计算交叉熵损失。

1.2 api调用

模型的使用方法如下:首先将需要分类的图像经过编码器得到特征,然后对于目标任务数据集的每一个标签,或者你自己定义的标签,都构造一段对应的文本,如上图中的 dog 会改造成 “A photo of a dog”,以此类推。然后经过编码器得到文本和图像特征,接着将文本特征与图像特征做内积,内积最大对应的标签就是图像的分类结果。

clip函数支持的方法:
clip.available_models()
clip.load(name, device=…, jit=False)
clip.tokenize(text: Union[str, List[str]], context_length=77)
加载进来的模型支持的方法:
model.encode_image(image: Tensor)
model.encode_text(text: Tensor)
model(image: Tensor, text: Tensor):计算余弦相似度

2. 使用样例

一般的流程是:

  1. 通过调用clip.load(模型名称),获取model, preprocess
  2. 调用clip.tokenize向量化文字,然后调用model.encode_text转为text_feature
  3. 调用preprocess处理图片,然后调用model.encode_image转为image_feature
  4. 将两个feature标准化后,计算余弦相似度

2.1 skimage自带图像与描述文字的相似度

import numpy as np
import torch
from pkg_resources import packaging
import clip# 导入数据
model, preprocess = clip.load("ViT-B/32") # 加载模型
model.cuda().eval()
input_resolution = model.visual.input_resolution
context_length = model.context_length
vocab_size = model.vocab_size
# Model parameters: 151,277,313
# Input resolution: 224
# Context length: 77
# Vocab size: 49408import os
import skimage
import IPython.display
import matplotlib.pyplot as plt
from PIL import Image
import numpy as npfrom collections import OrderedDict
import torch# 描述文字
descriptions = {"page": "a page of text about segmentation","chelsea": "a facial photo of a tabby cat","astronaut": "a portrait of an astronaut with the American flag","rocket": "a rocket standing on a launchpad","motorcycle_right": "a red motorcycle standing in a garage","camera": "a person looking at a camera on a tripod","horse": "a black-and-white silhouette of a horse", "coffee": "a cup of coffee on a saucer"
}
original_images = []
images = []
texts = []for filename in [filename for filename in os.listdir(skimage.data_dir) if filename.endswith(".png") or filename.endswith(".jpg")]:name = os.path.splitext(filename)[0]if name not in descriptions:continueimage = Image.open(os.path.join(skimage.data_dir, filename)).convert("RGB")original_images.append(image)images.append(preprocess(image))texts.append(descriptions[name])image_input = torch.tensor(np.stack(images)).cuda()
text_tokens = clip.tokenize(["This is " + desc for desc in texts]).cuda() # shape: 8*77# 512 dimension
with torch.no_grad():image_features = model.encode_image(image_input).float()text_features = model.encode_text(text_tokens).float()image_features /= image_features.norm(dim=-1, keepdim=True)
text_features /= text_features.norm(dim=-1, keepdim=True)
similarity = text_features.cpu().numpy() @ image_features.cpu().numpy().T

输出如下图:

2.2 上述图片使用cifer100的标签分类

# 加载数据
from torchvision.datasets import CIFAR100
cifar100 = CIFAR100(os.path.expanduser("~/.cache"), transform=preprocess, download=True)# 描述文字
text_descriptions = [f"This is a photo of a {label}" for label in cifar100.classes]
text_tokens = clip.tokenize(text_descriptions).cuda()
with torch.no_grad():text_features = model.encode_text(text_tokens).float()text_features /= text_features.norm(dim=-1, keepdim=True)# 展示概率最高的top5分类
text_probs = (100.0 * image_features @ text_features.T).softmax(dim=-1)
top_probs, top_labels = text_probs.cpu().topk(5, dim=-1)

结果如下:

2.3 判断性别

classes = ['man', 'woman']
image_input = preprocess(Image.open('man.jpg')).unsqueeze(0)
text_inputs = torch.cat([clip.tokenize(f"a photo of a {c}") for c in classes])#特征编码
with torch.no_grad():image_features = model.encode_image(image_input)text_features = model.encode_text(text_inputs)#选取参数最高的标签
image_features /= image_features.norm(dim=-1, keepdim=True)
text_features /= text_features.norm(dim=-1, keepdim=True)
similarity = (100.0 * image_features @ text_features.T).softmax(dim=-1)
values, indices = similarity[0].topk(1)#输出结果
print("\nTop predictions:\n")
print('classes:{} score:{:.2f}'.format(classes[indices.item()], values.item()))

3. 迁移训练

参考如下代码。
其中image_caption_dataset用来加载图像文字对,load_data调用image_caption_dataset来包装训练数据对。
load_pretrian_model用于加载训练用的模型,jit需要设置为False。
通过logits_per_image, logits_per_text = model(images, texts)可以得到预测结果,与torch.arange(N)计算交叉熵进行优化

from PIL import Image
import osdevice = 'cuda' if torch.cuda.is_available() else 'cpu'class image_caption_dataset(Dataset):def __init__(self, df, preprocess):self.images = df["image"]self.caption = df["caption"]self.preprocess = preprocessdef __len__(self):return len(self.caption)def __getitem__(self, idx):images = self.preprocess(Image.open(self.images[idx]))caption = self.caption[idx]return images, captiondef load_data(cup_path, cupnot_path, batch_size, preprocess):df = {'image': [], 'caption':[]}cup_list = os.listdir(cup_path)cupnot_list = os.listdir(cupnot_path)caption = cup_path.split('/')[-1]for img in cup_list:img_path = os.path.join(cup_path, img)df['image'].append(img_path)df['caption'].append(caption)caption = cupnot_path.split('/')[-1]for img in cupnot_list:img_path = os.path.join(cupnot_path, img)df['image'].append(img_path)df['caption'].append(caption)dataset = image_caption_dataset(df, preprocess)train_dataloader = DataLoader(dataset, batch_size=batch_size)return train_dataloaderdef convert_models_to_fp32(model):for p in model.parameters():p.data = p.data.float()p.grad.data = p.grad.data.float()def load_pretrian_model(model_path):model, preprocess = clip.load(model_path, device=device, jit=False)  # 训练时 jit必须设置为falseif device == "cpu":model.float()else:clip.model.convert_weights(model)return model, preprocessdef train(epoch, batch_size, learning_rate, cup_path, cupnot_path):# 加载模型model, preprocess = load_pretrian_model('ViT-B/32')#加载数据集train_dataloader = load_data(cup_path, cupnot_path, batch_size, preprocess)#设置参数loss_img = nn.CrossEntropyLoss().to(device)loss_txt = nn.CrossEntropyLoss().to(device)optimizer = optim.Adam(model.parameters(), lr=learning_rate, betas=(0.9, 0.98), eps=1e-6, weight_decay=0.2)for i in range(epoch):for batch in train_dataloader:list_image, list_txt = batch texts = clip.tokenize(list_txt).to(device)images = list_image.to(device)logits_per_image, logits_per_text = model(images, texts)if device == "cpu":ground_truth = torch.arange(batch_size).long().to(device)else:ground_truth = torch.arange(batch_size, dtype=torch.long, device=device)#反向传播total_loss = (loss_img(logits_per_image, ground_truth) + loss_txt(logits_per_text, ground_truth)) / 2optimizer.zero_grad()total_loss.backward()if device == "cpu":optimizer.step()else:convert_models_to_fp32(model)optimizer.step()clip.model.convert_weights(model)print('[%d] loss: %.3f' %(i + 1, total_loss))torch.save(model, './model/model1.pkl')def main():epoch = 100batch_size = 6learning_rate = 5e-5cup_path = './data/It is photo with cup'cupnot_path = './data/It is photo without cup'train(epoch, batch_size, learning_rate, cup_path, cupnot_path)if __name__ == '__main__':main()

深度学习系列37:CLIP模型相关推荐

  1. 【深度学习系列】CNN模型的可视化

    前面几篇文章讲到了卷积神经网络CNN,但是对于它在每一层提取到的特征以及训练的过程可能还是不太明白,所以这节主要通过模型的可视化来神经网络在每一层中是如何训练的.我们知道,神经网络本身包含了一系列特征 ...

  2. 深度学习系列笔记——贰 (基于Tensorflow2 Keras搭建的猫狗大战模型 三)

    深度学习系列笔记--贰 (基于Tensorflow Keras搭建的猫狗大战模型 一) 深度学习系列笔记--贰 (基于Tensorflow Keras搭建的猫狗大战模型 二) 前面两篇博文已经介绍了如 ...

  3. 吴恩达.深度学习系列-C4卷积神经网络-W2深度卷积模型案例

    吴恩达.深度学习系列-C4卷积神经网络-W2深度卷积模型案例 (本笔记部分内容直接引用redstone的笔记http://redstonewill.com/1240/.原文整理的非常好,引入并添加我自 ...

  4. 深度学习系列笔记——贰 (基于Tensorflow Keras搭建的猫狗大战模型 一)

    猫狗大战是著名的竞赛网站kaggle几年前的一个比赛,参赛者得到猫狗各12500张图片,作为训练集,另外还会得到12500张猫和狗的图片,作为验证.最后提交结果至kaggle平台,获得评测分数. 本篇 ...

  5. 【深度学习系列】——神经网络的可视化解释

    这是深度学习系列的第三篇文章,欢迎关注原创公众号 [计算机视觉联盟],第一时间阅读我的原创!回复 [西瓜书手推笔记] 还可获取我的机器学习纯手推笔记! 深度学习系列 [深度学习系列]--深度学习简介 ...

  6. 【深度学习系列】卷积神经网络CNN原理详解(一)——基本原理(1)

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

  7. 腾讯深度学习系列——深度学习及并行化实现概述

    深度学习及并行化实现概述 摘要: 深度学习可以完成需要高度抽象特征的人工智能任务,如语音识别.图像识别和检索.自然语言理解等.深层模型是包含多个隐藏层的人工神经网络,多层非线性结构使其具备强大的特征表 ...

  8. 深度学习系列:深度学习在腾讯的平台化和应用实践

    深度学习系列:深度学习在腾讯的平台化和应用实践(一) 莫扎特 2015-01-04 6:05:13 大数据技术 评论(0) 深度学习是近年机器学习领域的重大突破,有着广泛的应用前景.随着Google公 ...

  9. 【深度学习系列】——深度学习简介

    这是深度学习系列的第一篇文章,欢迎关注原创公众号 [计算机视觉联盟],第一时间阅读我的原创!回复 [西瓜书手推笔记] 还可获取我的机器学习纯手推笔记! 直达笔记地址:机器学习手推笔记(GitHub地址 ...

最新文章

  1. Android listview viewholder
  2. 2-4 zookeeper配置文件介绍,运行zk
  3. 制作计算器窗口java_Java实现的窗口计算器
  4. SAP云平台部署HTML5应用时的错误消息Failed to report quota consumption
  5. nginx和apache限制IP地址访问的设置方法
  6. [Leedcode][JAVA][第876题][快慢指针]
  7. 计组之中央处理器:8、五段式指令流水线
  8. 重建Windows 7的图标缓存
  9. slam 无人车 融合imu 后手动调整小车位姿,不受里程计影响
  10. 电脑连接移动设备android驱动程序,手机连接电脑驱动程序下载汇总
  11. DroidCam连接教程+资源
  12. 计算机换色带技巧,安装与更换针式打印机的色带的详细方法(图文教程)
  13. html按钮圆弧样式,几款不错的按钮样式汇总
  14. java基础—java由来
  15. class path resource [springMVC-servlet.xml] cannot be opened because it does not exist
  16. electron-vue 添加右下角通知图标
  17. 华为新人培养计划曝光!(新员工培训就该这么做)
  18. 2006年中国互联网天使投资大会文字实录
  19. 对于迪杰斯特拉算法的学习
  20. GeoJSON详解(带图)

热门文章

  1. 软链接、硬链接与复制的区别
  2. 风控策略的开发与场景应用
  3. No subdirectories found for mandatory directory location ‘file: /config/*/‘
  4. mysql索引长度超过767bytes问题解决。Specified key was too long; max key length is 767 bytes
  5. flex---布局神器,无往不利
  6. 个人博客作业三:英语学习APP的案例分析
  7. javascript 中搜索数组的四种方法
  8. 服务器计费系统,《仙境传说》两服务器计费系统升级
  9. 电信计费模拟系统c语言,电信计费模拟实现(C语言).doc
  10. 原来写在BlogBus(博客大巴)上的文章搬运到这里!~