【计算机视觉】如何利用 CLIP 做简单的图像分类任务?(含源代码)

要使用 CLIP 模型进行预测,您可以按照以下步骤进行操作:

一、安装

安装依赖:首先,您需要安装相应的依赖项。您可以使用 Python 包管理器(如 pip )安装 OpenAICLIP 库。

pip install git+https://github.com/openai/CLIP.git

在这里插入图片描述

二、代码解读

2.1 代码逐行构建过程

import clip
import torch
from PIL import Image

导入所需的库,包括 clip(用于加载和使用 CLIP 模型)、torchPyTorch 框架)和 PIL(用于图像处理)。

img_pah = '1.png'
classes = ['person', 'not_person']

设置输入图像的路径 img_path 和标签类别列表 classes。在这个示例中,类别列表包含了两个类别:‘person’‘not_person’

device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load('ViT-B/32', device)

根据是否可用 GPU,将设备设置为 “cuda”“cpu” 。然后,使用 CLIP 库中的 clip.load() 方法加载预训练的 ViT-B/32 模型,并返回加载的模型 model 和预处理函数 preprocess

image = Image.open(img_pah)
image_input = preprocess(image).unsqueeze(0).to(device)
text_inputs = torch.cat([clip.tokenize(f"a photo of a {c}") for c in classes]).to(device)

打开图像文件并使用预处理函数 preprocess 对图像进行预处理。然后,将预处理后的图像转换为模型所需的格式,并将其移动到设备上(GPUCPU)。对于文本输入,使用类别列表 classes 生成对应的文字描述,并使用 clip.tokenize() 函数对文字描述进行处理。

with torch.no_grad():
    image_features = model.encode_image(image_input)
    text_features = model.encode_text(text_inputs)

在不进行梯度计算的上下文中,使用 CLIP 模型的 encode_image() 方法对图像进行特征编码,得到图像特征 image_features 。同时,使用 encode_text() 方法对文本进行特征编码,得到文本特征 text_features

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)

对图像特征和文本特征进行归一化处理,以便计算它们之间的相似度。然后,使用矩阵乘法计算图像特征和文本特征之间的相似度矩阵。接下来,对相似度矩阵进行 softmax 归一化处理,得到相似度分数。最后,找到相似度分数中最高的值和对应的索引。

print("\nTop predictions:\n")
print('classes:{} score:{:.2f}'.format(classes[indices.item()], values.item()))

打印输出结果,显示预测的最高分数和对应的类别标签。

2.2 源代码 + 运行结果

import clip
import torch
from PIL import Image

img_pah = '1.png'
classes = ['person', 'not_person']

# 加载模型
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load('ViT-B/32', device)


# 准备输入集
image = Image.open(img_pah)
image_input = preprocess(image).unsqueeze(0).to(device)
text_inputs = torch.cat([clip.tokenize(f"a photo of a {c}") for c in classes]).to(device) #生成文字描述

# 特征编码
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()))

运行结果为:

Top predictions:

classes:person score:0.81

2.3 细节补充

2.3.1 clip.load()

clip.load() 方法中,可以调用多个预训练的 CLIP 模型。以下是一些常用的 CLIP 模型名称:

  • ViT-B/32: Vision Transformer 模型,基于 ImageNet 预训练的 ViT-B/32
  • RN50: ResNet-50 模型,基于 ImageNet 预训练的 ResNet-50
  • RN101: ResNet-101 模型,基于 ImageNet 预训练的 ResNet-101
  • RN50x4: ResNet-50 模型的扩展版本,使用更大的 batch size 进行训练。
  • RN50x16: ResNet-50 模型的更大版本,使用更大的 batch size 进行训练。

以上列出的是一些常用的预训练模型,但并不是全部可用的模型列表。CLIP 库还提供其他模型和变体,您可以在官方文档中查找完整的模型列表,并根据您的需要选择适合的预训练模型。

请注意,选择不同的预训练模型可能会影响性能和计算资源的要求。较大的模型通常具有更多的参数和更高的计算成本,但可能具有更好的性能。因此,根据您的具体应用场景和可用资源,选择适当的预训练模型进行调用。

2.3.2 preprocess()

preprocessCLIP 库中提供的预处理函数之一,用于对图像进行预处理以符合 CLIP 模型的输入要求。下面是 preprocess 函数的一般步骤和说明:

  • 图像的缩放:首先,图像会被缩放到指定的大小。通常情况下,CLIP 模型要求输入图像的尺寸是正方形的,例如 224x224 像素。所以,在预处理过程中,图像会被调整为适当的尺寸。
  • 像素值归一化:接下来,图像的像素值会被归一化到特定的范围。CLIP 模型通常要求输入图像的像素值在 0 到 1 之间,因此预处理过程中会将像素值归一化到这个范围。
  • 通道的标准化:CLIP 模型对图像通道的顺序和均值标准差要求是固定的。因此,预处理过程中会对图像的通道进行重新排列,并进行标准化。具体来说,通常是将图像的通道顺序从 RGB(红绿蓝)调整为 BGR(蓝绿红),并对每个通道进行均值标准化。
  • 转换为张量:最后,经过预处理的图像会被转换为张量形式,以便于传递给 CLIP 模型进行计算。这通常涉及将图像的维度进行调整,例如从形状为 (H, W, C) 的图像转换为形状为 (C, H, W) 的张量。

总之,preprocess 函数负责将输入的图像进行缩放、归一化和格式转换,以使其符合 CLIP 模型的输入要求。具体的预处理操作可能因 CLIP 模型的不同版本而有所差异,建议参考 CLIP 库的官方文档或源代码以获得更详细的预处理细节。

2.3.3 unsqueeze

PyTorch 中,unsqueeze() 是一个张量的方法,用于在指定的维度上扩展维度。

具体而言,unsqueeze(dim) 的作用是在给定的 dim 维度上增加一个维度。这个操作会使得原始张量的形状发生变化。

以下是 unsqueeze(dim) 的详细解释:

  • 参数 dim:表示要在哪个维度上进行扩展。可以是一个整数或一个元组来指定多个维度。通常, dim 的取值范围是从 0 到 tensor.dim()(即张量的维度数)。
  • 返回值:返回一个新的张量,与原始张量共享数据内存,但形状发生了变化。

示例:

import torch

# 原始张量形状为 (2, 3)
x = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 在维度0上扩展维度,结果形状为 (1, 2, 3)
y = x.unsqueeze(0)

# 在维度1上扩展维度,结果形状为 (2, 1, 3)
z = x.unsqueeze(1)

在上述示例中,原始张量 x 的形状为 (2, 3)。通过调用 unsqueeze() 方法并传递不同的维度参数,我们可以在指定的维度上扩展维度。结果张量 y 在维度0上扩展维度,形状变为 (1, 2, 3);结果张量 z 在维度1上扩展维度,形状变为 (2, 1, 3)。

通过使用 unsqueeze() 方法,我们可以改变张量的形状,以适应不同的计算需求和操作要求。

### CLIP 模型在图像分类中的应用 CLIP(Contrastive Language–Image Pre-training)作为一种多模态基础模型,不仅能够处理图像和文本之间的关系,还在图像分类任务中展现出强大的能力[^1]。通过预先训练于大规模的图文配对数据集,CLIP 学习到了如何将不同形式的信息映射到同一语义空间。 #### 特征提取与表示学习 当应用于图像分类时,CLIP 可以利用其预训练权重来抽取输入图片的有效特征向量。这些特征被证明对于区分真假图像特别有效,因为它们能够在特征域空间里清晰地区分这两类样本。具体来说: - **跨模态嵌入**:CLIP 同时编码来自视觉和自然语言的数据点至共享表征空间; - **零样本迁移**:即使未见过特定类别标签,也能依据描述性提示完成新类型的识别工作; ```python import torch from clip import load as load_clip device = "cuda" if torch.cuda.is_available() else "cpu" model, preprocess = load_clip("ViT-B/32", device=device) image_input = preprocess(image).unsqueeze(0).to(device) text_inputs = torch.cat([torch.tensor(tokenizer.encode(f"a photo of a {label}")) for label in labels]).to(device) with torch.no_grad(): image_features = model.encode_image(image_input) text_features = model.encode_text(text_inputs) similarity = (100.0 * image_features @ text_features.T).softmax(dim=-1) values, indices = similarity[0].topk(5) ``` 此代码片段展示了如何加载预训练好的 CLIP 模型并计算给定测试集中每张照片相对于一系列候选名称的概率分布情况。最终得到的结果 `indices` 就代表了最有可能匹配该幅画作所描绘对象的文字标签索引列表。 #### 实现细节 为了使 CLIP 更好地适应具体的图像分类场景,通常还需要考虑以下几个方面: - 数据增强策略的选择会影响泛化性能; - 针对目标领域调整超参数设置可以提升效果; - 结合其他技术如集成方法或者微调部分网络层也可能带来增益。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旅途中的宽~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值