MLM之CLIP:CLIP(对比语言-图像预训练模型)的简介、安装和使用方法、案例应用之详细攻略
目录
《Learning Transferable Visual Models From Natural Language Supervision》翻译与解读
2、CLIP 架构:包括图像编码器和文本编码器,将图像和文本映射到共同的特征空间中
相关文章
《Learning Transferable Visual Models From Natural Language Supervision》翻译与解读
地址 | |
时间 | 2021 年 2 月 26 日 |
作者 | OpenAI |
总结 | 背景痛点: >> 传统计算机视觉系统通过对预定义对象类别进行监督式训练,这种监督形式限制了模型的通用性和可用性,因为任何其他视觉概念都需要额外的标注数据。 >> 现有的从自然语言中学习图像表示的方法在常见基准测试中的性能较低,难以与完全监督方法相竞争。 解决方案: >> 开发一种名为CLIP(Contrastive Language-Image Pre-training)的对比语言-图像预训练模型,该模型通过预测图像-文本对是否匹配的对比目标,从大规模(4亿对)互联网图文数据中直接学习视觉表示。 核心思路步骤: >> 构建包含4亿个(图像,文本)对的大规模WIT(WebImageText)数据集。 >> 在WIT数据集上联合训练图像编码器和文本编码器,优化目标是在每个批次内最大化真实图文对的相似性得分,最小化错误配对的相似性得分。 >> 在30多个现有计算机视觉数据集上评估零次传递性能,用于测试CLIP学习到的通用视觉表示能力。 >> 通过简化对比目标和架构设计(如注意力池化)提高训练效率。 >> 通过模型缩放(如增加宽度、深度、分辨率)来研究CLIP性能与计算量的关系。 优势: >> 无需任何数据集特定的监督或微调,CLIP就能在多个视觉任务上达到有竞争力的性能。 >> 相比于等准确度的监督ImageNet模型,零次传递CLIP模型表现出更强的鲁棒性。 >> 直接从自然语言中学习,可以有效利用互联网上丰富的文本数据,不受预定义类别集的限制。 >> 端到端的联合语义和视觉表示,可以实现灵活的零次传递能力。 >> 作为一种任务无关模型,CLIP展现出很强的潜在能力和可扩展性。 |
CLIP的简介
2021 年 1 月 5 日,OpenAI发布CLIP。CLIP(对比语言-图像预训练)是一种针对各种(图像,文本)对进行训练的神经网络。它可以用自然语言指示,根据给定的图像预测最相关的文本片段,而无需直接针对任务进行优化,类似于 GPT-2 和 3 的零样本能力。我们发现 CLIP 在 ImageNet“零样本”上的表现与原始 ResNet50 相当,而无需使用任何原始的 1.28M 标记示例,从而克服了计算机视觉领域的几大挑战。
CLIP 模型的主要意义:
>> 跨模态学习能力:同时处理和理解图像及其文本描述。
>> 零样本学习:使用自然语言描述进行图像识别,无需额外模型训练。
官网文章:https://openai.com/index/clip/
GitHub地址:https://github.com/openai/CLIP
1、方法
2、CLIP 架构:包括图像编码器和文本编码器,将图像和文本映射到共同的特征空间中
>> 图像编码器:使用卷积神经网络(CNN)或 Vision Transformer(ViT)架构。处理图像数据,提取视觉特征。
>> 文本编码器:基于 Transformer 架构。处理文本数据,提取文本特征。
>> 共同特征空间:图像和文本编码器输出嵌入向量,通过对比损失函数优化。
确保相关图像与文本描述在特征空间中接近,而不相关的距离较远。
>> 对比损失函数:对图像和文本的嵌入进行点积,确保正确配对具有高余弦相似度,错误配对则较低。通过反向传播更新权重,优化模型。
CLIP的安装和使用方法
1、安装
首先,安装 PyTorch 1.7.1(或更高版本)和 torchvision,以及其他一些小的依赖项,然后将此 repo 安装为 Python 包。在 CUDA GPU 机器上,以下操作即可完成:
$ conda install --yes -c pytorch pytorch=1.7.1 torchvision cudatoolkit=11.0
$ pip install ftfy regex tqdm
$ pip install git+https://github.com/openai/CLIP.git
将上面的内容替换为您机器上或在没有 GPU 的机器上安装时cudatoolkit=11.0适当的 CUDA 版本。
2、使用方法
代码实现
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]]
API实现
CLIP 模块clip提供以下方法:
clip.available_models()
返回可用 CLIP 模型的名称。
clip.load(name, device=..., jit=False)
返回模型和模型所需的 TorchVision 变换,由 返回的模型名称指定clip.available_models()。它会根据需要下载模型。name参数也可以是本地检查点的路径。
可以选择性地指定运行模型的设备,默认使用第一个 CUDA 设备(如果有),否则使用 CPU。当 时jit,False将加载模型的非 JIT 版本。
clip.tokenize(text: Union[str, List[str]], context_length=77)
返回包含给定文本输入的标记序列的 LongTensor。这可以用作模型的输入
返回的模型clip.load()支持以下方法:
model.encode_image(image: Tensor)
给定一批图像,返回由 CLIP 模型的视觉部分编码的图像特征。
model.encode_text(text: Tensor)
给定一批文本标记,返回由 CLIP 模型的语言部分编码的文本特征。
model(image: Tensor, text: Tensor)
给定一批图像和一批文本标记,返回两个张量,包含与每个图像和文本输入相对应的逻辑分数。这些值是相应图像和文本特征之间的余弦相似度乘以 100。
CLIP的案例应用:样本图像分类、图像搜索、多模态内容生成
样本图像分类:识别未训练特定类别的图像对象。
图像搜索:基于文本进行图像检索。
多模态内容生成:结合图像生成模型(如 DALL·E),根据文本描述生成图像。
1、零样本预测
以下代码使用 CLIP 执行零样本预测,如论文附录 B 所示。此示例从CIFAR-100 数据集中获取一张图片,并预测数据集中 100 个文本标签中最可能的标签。
import os
import clip
import torch
from torchvision.datasets import CIFAR100
# Load the model
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load('ViT-B/32', device)
# Download the dataset
cifar100 = CIFAR100(root=os.path.expanduser("~/.cache"), download=True, train=False)
# Prepare the inputs
image, class_id = cifar100[3637]
image_input = preprocess(image).unsqueeze(0).to(device)
text_inputs = torch.cat([clip.tokenize(f"a photo of a {c}") for c in cifar100.classes]).to(device)
# Calculate features
with torch.no_grad():
image_features = model.encode_image(image_input)
text_features = model.encode_text(text_inputs)
# Pick the top 5 most similar labels for the image
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(5)
# Print the result
print("\nTop predictions:\n")
for value, index in zip(values, indices):
print(f"{cifar100.classes[index]:>16s}: {100 * value.item():.2f}%")
输出将如下所示(具体数字可能因计算设备而略有不同):
Top predictions:
snake: 65.31%
turtle: 12.29%
sweet_pepper: 3.83%
lizard: 1.88%
crocodile: 1.75%
请注意,此示例使用encode_image()和encode_text()方法返回给定输入的编码特征。
2、线性探针评估
下面的示例使用scikit-learn对图像特征执行逻辑回归。
import os
import clip
import torch
import numpy as np
from sklearn.linear_model import LogisticRegression
from torch.utils.data import DataLoader
from torchvision.datasets import CIFAR100
from tqdm import tqdm
# Load the model
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load('ViT-B/32', device)
# Load the dataset
root = os.path.expanduser("~/.cache")
train = CIFAR100(root, download=True, train=True, transform=preprocess)
test = CIFAR100(root, download=True, train=False, transform=preprocess)
def get_features(dataset):
all_features = []
all_labels = []
with torch.no_grad():
for images, labels in tqdm(DataLoader(dataset, batch_size=100)):
features = model.encode_image(images.to(device))
all_features.append(features)
all_labels.append(labels)
return torch.cat(all_features).cpu().numpy(), torch.cat(all_labels).cpu().numpy()
# Calculate the image features
train_features, train_labels = get_features(train)
test_features, test_labels = get_features(test)
# Perform logistic regression
classifier = LogisticRegression(random_state=0, C=0.316, max_iter=1000, verbose=1)
classifier.fit(train_features, train_labels)
# Evaluate using the logistic regression classifier
predictions = classifier.predict(test_features)
accuracy = np.mean((test_labels == predictions).astype(float)) * 100.
print(f"Accuracy = {accuracy:.3f}")
请注意,该C值应通过使用验证分割的超参数扫描来确定。