图像分类与迁移学习--基于预训练VGG-16模型识别图像类别


前言

本文内容将讲述如何利用已经训练好的VGG-16模型(基于ImageNet数据集)来自动识别图像类别,其中模型测试将使用GPU主机而非GPU主机实现;并介绍如何下载利用PyTorch框架、什么是VGG-16以及实现对图像的尺寸与颜色的变换。


一、ImageNet与VGG-16

ImageNet是斯坦福大学从互联网上收集的大量图片后,对其分类整理后所形成的数据集。在PyTorch中可以轻松使用ImageNet数据集中的ILSVRC2012数据集,该数据集有1000种分类数,包含大多数日常所见到的物品(如玩具、零食与动物等),共120万张图片作为训练集,5万张作为验证集,10万张作为测试集;在PyTorch中还可以很方便使用各种已经训练好的或者是学习好的参数与神经网络模型。

VGG-16是2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG19最为著名。
VGG网络被广泛应用于图像分类、目标检测、语义分割等计算机视觉任务中,并且其网络结构的简单性和易实现性使得VGG成为了深度学习领域的经典模型之一。
在这里插入图片描述

二、预测分析

1.环境软件库安装配置

首先进入Pytorch官网,根据自己的电脑配置好对应的torch版本以及torchvision软件包,下图第一行红色底色为稳定版本(推荐),第二行为操作系统(一般为Windows系统),第三行为安装方式(Conda与Pip都行),第五行要根据自己的GPU以及NVIDIA下载对应的CUDA版本(torch官网会自动检测电脑所适应的版本),如果电脑没有GPU或者是A卡,则可以选择CPU下载方式,最后复制最后一行的代码在cmd命定窗(其他地方也行,如jupyter)运行即可。(这里建议读者去根据专门的教程下载torch)
在这里插入图片描述
首先导入对应的软件包,并确认Pytorch版本号

# 导入软件包
import numpy as np
import json
from PIL import Image
import matplotlib.pyplot as plt
import torch
import torchvision
from torchvision import models, transforms

%matplotlib inline
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
#主要解决jupyter notebook“内核似乎挂掉了,它很快将自动重启”的问题
print("PyTorch Version: ",torch.__version__)
print("Torchvision Version: ",torchvision.__version__)

在这里插入图片描述

2.加载已完成训练的VGG-16模型

第一次执行该代码将会耗费较长时间,需要下载对应的训练参数。

#VGG-16已完成训练模型的载入
# 第一次执行时,由于需要从网络下载学习好的参数数据,因此执行时间会稍微长一些
#生成VGG-16模型的实例
use_pretrained=True
# 使用已经训练好的参数
net=models.vgg16(pretrained=use_pretrained)
net.eval()  # 设置为推测模式,也就是测试模式,能够直接进行预测
#  输出模型的网络结构
print(net)

加载好后,打印输出网络模型,可以看到,VGG-16主要采用3*3的卷积结构,relu激活函数以及最大池化层,通道数由64个开始翻倍增长(网格输入的图像尺寸为颜色通道数为3的RGB格式,图像高宽均为224像素 [批次,3,224,224]),这样子使得模型”窄而深“的同时,参数量也不会过多,最后连接三层全连接网络层,由于有1000个类别,故输出神经元为1000。
在这里插入图片描述

2.加载待分类图片以及图片预处理

图片为在网络上随机寻找的金毛犬图片(1300,1100,3),为了方便输入到模型中,需要对图片进行一定的预处理操作,首先将尺寸转换为224*224大小,并对颜色信息进行标准化,对每个RGB值用平均值与标准偏差进行归一化处理(根据ILSVRC2012数据集计算得到的)。

# 对输入图片进行预处理的类
class BaseTransform():
    def __init__(self,resize,mean,std):
        self.base_transform=transforms.Compose([
            transforms.Resize(resize),#将较短边的长度作为resize的大小
            transforms.CenterCrop(resize),#从图片中央截取resize × resize大小的区域
            transforms.ToTensor(), #转换为Torch张量
            transforms.Normalize(mean,std)   #颜色标准化
        ])
    def __call__(self, img):    #如果没有指定调用方法时,该方法将被执行
        return self.base_transform(img)
#确认图像预处理的结果
# 读取图片
image_file_path='./data/R-C.jpg'  #该图片保存在当前路径下data文件夹下,命名为R-C.jpg
img=Image.open(image_file_path)  # [高度][宽度][颜色RGB]
plt.imshow(img)
plt.show()
resize=224  #同时显示预处理前后的图片
mean=(0.485, 0.456, 0.406)   #均值
std=(0.229, 0.224, 0.225)   #标准差
transform=BaseTransform(resize,mean,std)
img_transformed=transform(img)  # torch.Size([3, 224, 224])   #转换
# 将 ( 颜色、高度、宽度 ) 转换为 ( 高度、宽度、颜色 ),并将取值范围限制在0~1
img_transformed=img_transformed.numpy().transpose((1, 2, 0))   #转换为[长,宽,通道]方便imshow
img_transformed=np.clip(img_transformed, 0, 1)
plt.imshow(img_transformed)
plt.show()

在这里插入图片描述

在这里插入图片描述

3.加载类别数据

首先需要下载模型所预测得到1000个结果类别的json文件imagenet_class_index.json

#·文件夹“data”不存在时制作
data_dir="./data/"   #保存路径,与预测图片地址一致
if not os.path.exists(data_dir):
    os.mkdir(data_dir)
#下载ImageNet的class_index
#是在Keras准备的。
# https://github.com/fchollet/deep-learning-models/blob/master/imagenet_utils.py
url = "https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json"
save_path=os.path.join(data_dir, "imagenet_class_index.json")  #分类标签
if not os.path.exists(save_path):
    urllib.request.urlretrieve(url, save_path)    

再载入分类标签信息,保存为字典形式

#根据ILSVRC数据,从模型的输出结果计算出分类标签
ILSVRC_class_index=json.load(open('./data/imagenet_class_index.json', 'r'))
ILSVRC_class_index

在这里插入图片描述
根据ILSVRC数据,从模型的输出结果计算出分类标签,具体首先细节可查看下方代码:

# 根据输出结果对标签进行预测的后处理类
class ILSVRCPredictor():
    """
    ----------
    class_index : dictionary
    将类的index与标签名关联起来的字典型变量
    """
    def __init__(self, class_index):
        self.class_index=class_index
    def predict_max(self, out):
        """
        获得概率最大的ILSVRC分类标签名
        Parameters
        ----------
        out : torch.Size([1, 1000])
            从Net中输出结果
        Returns
        -------
        predicted_label_name : str
        预测概率最高的分类标签的名称
        """
        maxid=np.argmax(out.detach().numpy())  #detach将结果从网格分离出来,并转为numpy数组
        predicted_label_name=self.class_index[str(maxid)][1]  #得到预测类别名
        return predicted_label_name

4.进行图片预测

将已经处理好的图片后,可以很方便的使用已训练VGG-16模型来对图片进行预测,模型预测的1000个类别经过前面定义的ILSVRCPredictor函数处理后,将返回预测概率最高的分类类别标签,具体代码如下,由于将图片传入到Pytorch网络中,需要采用批次处理([批次,通道,长,宽]类似这种格式),所以这里采用小批次对图片进行处理后,再输入到网络中。

# 载入ILSVRC的标签信息,并生成字典型变量
ILSVRC_class_index=json.load(open('./data/imagenet_class_index.json', 'r'))
predictor=ILSVRCPredictor(ILSVRC_class_index)# 生成ILSVRCPredictor的实例
# 读取输入的图像
image_file_path='./data/R-C.jpg'
img=Image.open(image_file_path)  # [ 高度 ][ 宽度 ][ 颜色RGB]
# 完成预处理后,添加批次尺寸的维度
transform=BaseTransform(resize, mean, std)  
#创建预处理类
img_transformed = transform(img)
inputs=img_transformed.unsqueeze_(0)  # torch.Size([3, 224, 224])(0)  # torch.Size([1, 3, 224, 224]) 小批次

out=net(inputs)  #输出结果1000维
result =predictor.predict_max(out)# 输入数据到模型中,并将模型的输出转换为标签.predict_max# torch.Size([1, 1000])(out)(概率最大)
# 输出预测结果
print("输入图像的预测结果:", result)

在这里插入图片描述
可以看到,模型成功的将图片预测为金毛犬(金毛寻回犬)。接下来,我们再随机找一张图片,看看模型的预测结果是否正确:

image_file_path='./data/R-C2.jpg'  #甲壳虫图片
img=Image.open(image_file_path)  # [高度][宽度][颜色RGB]
plt.imshow(img)
plt.show()
resize=224# 3. 同时显示预处理前后的图片
mean=(0.485, 0.456, 0.406)
std=(0.229, 0.224, 0.225)
transform=BaseTransform(resize,mean,std)
img_transformed=transform(img)  # torch.Size([3, 224, 224])
# 将 ( 颜色、高度、宽度 ) 转换为 ( 高度、宽度、颜色 ),并将取值范围限制在0~1
img_transformed=img_transformed.numpy().transpose((1, 2, 0))
img_transformed=np.clip(img_transformed, 0, 1)
plt.imshow(img_transformed)
plt.show()

首先对图片进行同样的预处理后,得到的结果如下:
在这里插入图片描述
接着还是相同的步骤,对图片进行小批次处理后,将图片输入到VGG-16模型中,可以看到,模型同样正确的预测出图片的类别:叶甲虫

# 读取输入的图像
image_file_path='./data/R-C2.jpg'
img=Image.open(image_file_path)  # [ 高度 ][ 宽度 ][ 颜色RGB]
# 完成预处理后,添加批次尺寸的维度
transform=BaseTransform(resize, mean, std)  
#创建预处理类
img_transformed = transform(img)
inputs=img_transformed.unsqueeze_(0)  # torch.Size([3, 224, 224])(0)  # torch.Size([1, 3, 224, 224]) 小批次
out=net(inputs)
result =predictor.predict_max(out)
# 输出预测结果
print("输入图像的预测结果:", result)

总结

本章内容主要讲述如何利用已学习好的VGG-16模型进行图片的自动分类预测,可以发现利用迁移学习可以很方便的进行我们所需要的研究,而且结果也相当不错,对于VGG-16模型,还有VGG-19,读者如果感兴趣可以自己去练习实践。对于VGG网络模型的原理不是本文重点,如果对VGG模型感兴趣可以去找相关资料学习。

  • 33
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
卷积神经网络(CNN)是一种用于图像分类识别深度学习模型。基于CNN的图像分类可以通过使用MATLAB编程来实现。 首先,我们需要准备一组图像数据集,其中包含具有不同类别图像样本。可以使用MATLAB中的图像处理工具箱来加载和处理这些图像数据。然后,我们需要将数据集分为训练集和测试集两部分。 接下来,我们可以通过建立一个CNN模型来训练图像分类器。在MATLAB中,可以使用深度学习工具箱来创建和训练CNN模型。首先,我们可以选择一种已经训练好的预训练模型作为基础模型,例如ResNet或VGGNet。然后,我们可以利用迁移学习的思想将该模型调整为适合我们的图像分类任务。 在训练过程中,我们需要指定损失函数和优化算法来最小化模型的预测错误。常见的损失函数包括交叉熵损失和均方误差损失。优化算法可以选择使用随机梯度下降(SGD)或Adam等算法。 训练完模型后,我们可以使用测试集对其进行验证和评估。通过计算模型在测试集上的准确率、精确率、召回率等指标,我们可以评估模型的性能和效果。 最后,我们可以将训练好的模型应用于新的图像数据上进行分类和识别。通过将新的图像输入到模型中,模型会根据之前的训练经验判断图像所属的类别。 总的来说,基于CNN的图像分类识别是一种强大的深度学习方法,通过MATLAB的编程和深度学习工具箱的支持,我们可以很方便地实现这一任务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值