使用预训练CNN生成图像嵌入(image embeddings)

文章介绍了如何利用Kaggle的狗品种图像数据集来生成图像嵌入。通过使用预训练的ResNet18模型,提取平均池化层的特征作为图像的低维表示,这些嵌入可用于后续的图像分类和搜索任务。文章详细阐述了数据准备、数据加载以及如何注册前向钩子来捕获嵌入的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是图像嵌入?

图像嵌入是图像的低维表示。换句话说,它是图像的密集向量表示,可用于分类等许多任务。

例如,这些深度学习表示有时用于创建搜索引擎,因为它依赖于图像相似性。事实上,要找到一类图像(例如狗),我们只需要找到最接近狗图像向量的嵌入向量。

找到这些的一个好方法是计算嵌入之间的余弦相似度。相似的图像在嵌入之间将具有较高的余弦相似度

来自 Kaggle 的狗品种图像数据集

对于这个例子,我们将使用我最喜欢的数据集之一:Kaggle Dog Breed Images 🐶

在这里插入图片描述
首先,我们需要下载这个数据集:

!export KAGGLE_USERNAME="xxxx" && export KAGGLE_KEY="xxxx" && mkdir -p data && cd data 
&& kaggle datasets download -d eward96/dog-breed-images 
&& unzip -n dog-breed-images.zip && rm dog-breed-images.zip

让我们看看这个数据文件夹中有什么:
在这里插入图片描述

这里我们有 10 种不同品种的狗:bernese_mountain_dog、chihuahua、dachshund、jack_russell、pug、border_collie、corgi、golden_retriever、labrador、siberian_husky。

import glob
data_dir = 'data'

list_imgs = glob.glob(data_dir + "/**/*.jpg")
print(f"There are {len(list_imgs)} images in the dataset {data_dir}")

=> 数据集中有918张图像。

以下示例展示了如何从狗品种文件夹创建 Deep Lake 数据集并将其存储在 Deep Lake 云中。

为了创建数据集,我们使用了 torchvision 模块:数据集和转换,以及 torch.utils.data.DataLoader:

from torchvision import datasets, transforms
import torch

# create dataloader with required transforms 
tc = transforms.Compose([
        transforms.Resize((256, 256)),
        transforms.ToTensor()              
    ])

image_datasets = datasets.ImageFolder(data_dir, transform=tc)
dloader = torch.utils.data.DataLoader(image_datasets, batch_size=10, shuffle=False)

print(len(image_datasets)) # returns 918

我们有一个调整大小和批处理的数据集加载器可供使用。

注意:Pytorch 默认的图像后端是 Pillow,当您使用 ToTensor() 类时,PyTorch 会自动将所有图像转换为 [0,1],因此无需在此处标准化图像。

如果我们想要可视化该数据集中的第一张图像:

for img, label in dloader:
      print(np.transpose(img[0], (1,2,0)).shape)
      print(img[i])
      plt.imshow((img[i].detach().numpy().transpose(1, 2, 0)*255).astype(np.uint8))
      plt.show()
      i = i + 1
      break

在这里插入图片描述

从狗品种图像数据集生成图像嵌入

为了生成图像嵌入,我们将使用预训练的模型直到分类前的最后一层,也称为倒数第二层。

CNN(卷积神经网络)的第一层提取输入图像的特征,然后全连接层处理分类并返回类别概率,然后将其传递给 softmax 损失,例如,它将确定哪个类别具有最高的概率概率得分:

在这里插入图片描述

# fetch pretrained model
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True)

现在我们需要选择要从中提取特征的层。如果我们再看一下 ResNet-18 的架构:

在这里插入图片描述
我们可以看到最后一层是 fc 层(全连接),其中对特征进行分类。我们想要CNN 分类部分之前的特征,因此,我们想要第一个全连接层,即 fc 之前的层:avgpool层。

我们可以使用模型对象选择该层:

# Select the desired layer
layer = model._modules.get('avgpool')

然后,我们使用register_forward_hook模块来获取嵌入:

def copy_embeddings(m, i, o):
    """Copy embeddings from the penultimate layer.
    """
    o = o[:, :, 0, 0].detach().numpy().tolist()
    outputs.append(o)

outputs = []
# attach hook to the penulimate layer
_ = layer.register_forward_hook(copy_embeddings)

注意:每次forward()计算出输出后都会调用函数copy_embeddings并将其保存在列表ouputs中。

然后,我们需要建模为推理模式:

model.eval() # Inference mode

让我们使用这个模型为我们的狗品种图像生成嵌入:

# Generate image's embeddings for all images in dloader and saves 
# them in the list outputs
for X, y in dloader:
    _ = model(X)
print(len(outputs)) #returns 92

由于dloader是批处理的,我们需要展平输出:

# flatten list of embeddings to remove batches
list_embeddings = [item for sublist in outputs for item in sublist]

print(len(list_embeddings)) # returns 918
print(np.array(list_embeddings[0]).shape)) #returns (512,)

正如预期的那样,新的展平列表 list_embeddings 的长度等于 918,这是我们在此狗品种数据集中拥有的图像数量。另外,列表 list_embeddings 中第一项的形状是 (512,),它对应于 avgpool 层输出的形状。

参考

https://www.activeloop.ai/resources/generate-image-embeddings-using-a-pre-trained-cnn-and-store-them-in-hub/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点PY

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

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

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

打赏作者

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

抵扣说明:

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

余额充值