百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

基于Pytorch的猫狗图片分类(pytorch 猫狗)

ztj100 2024-10-31 16:13 45 浏览 0 评论

转自:CSDN格兰芬多
译者 | 小圈 审校 | 方圆

猫狗分类来源于Kaggle上的一个入门竞赛—Dogs vs Cats 。为了加深对CNN的理解,基于 Pytorch 复现了LeNet,AlexNet,ResNet等经典CNN模型,项目大纲如下:

https://github.com/AuroraLHL/CatDog

文章目录

一、问题描述

二、数据集处理

1 损坏图片清洗

2 抽取图片形成数据集

三、图片预处理

(1)init 方法

(2)getitem方法

(3)len方法

(4)测试

四、模型

1 LeNet

2 AlexNet模型

五、训练

1 开始训练

2 tensorboard可视化

六、不同模型训练结果分析

1 LeNet模型

(1) 数据集数量=1000,无数据增强

(2) 数据集数量=4000,无数据增强

(3)数据集数量=4000,数据增强

(4)数据集=4000,数据增强

(5)使用dropout函数抑制过拟合

2 AlexNet模型

3 squeezeNet模型

4 resNet模型

总结

七、预测

一、问题描述

基于训练集数据,训练一个模型,利用训练好的模型预测未知图片中的动物是狗或者猫的概率。

训练集有25,000张图片,测试集12,500 张图片。

数据集下载地址:https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset

二、数据集处理

1 损坏图片清洗

在 01_clean.py 中,用多种方式来清洗损坏图片:

  • 判断开头是否有JFIF
  • 用imghdr库中的imghdr.what函数判断文件类型
  • 用Image.open(filename).verify()验证图片是否损坏

结果如下:

2 抽取图片形成数据集

由于一万多张图片比较多,并且需要将Cat类和Dog类的图片合在一起并重新命名,方便获得每张图片的labels,我们将从原数据集文件夹复制 任意给定数量图片train 的文件夹,并且重命名如下:

程序为:02_data_processing.py .

三、图片预处理

图片预处理部分需要完成:

  • 对图片的裁剪:将大小不一的图片裁剪成神经网络所需的,我选择的是裁剪为(224x224)
  • 转化为张量
  • 归一化:三个方向归一化
  • 图片数据增强
  • 形成加载器:返回图片数据和对应的标签,利用Pytorch的Dataset包

在 dataset.py 中定义Mydata的类,继承pytorch的Dataset,定义如下三个方法:

(1)init 方法

读取图片路径,并拆分为数据集和验证集,完成对图片的处理(以下代码 仅体现结构,具体见源码 ):

class Mydata(data.Dataset):
    """定义自己的数据集"""
    def __init__(self, root, Transforms=None, train=True):
        """进行数据集的划分"""
        if train:
            self.imgs = imgs[:int(0.8*imgs_num)]  #80%训练集
        else:
            self.imgs = imgs[int(0.8*imgs_num):]  #20%验证集
        """定义图片处理方式"""
        if Transforms is None:
            normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                                            std=[0.229, 0.224, 0.225])
            self.transforms = transforms.Compose(
                    [ transforms.CenterCrop(224), 
                    transforms.Resize([224,224]),
                    transforms.ToTensor(), normalize])

(2)getitem方法

对图片处理,返回数据和标签:

 def __getitem__(self, index):
     return data, label

(3)len方法

返回数据集大小:

    def __len__(self):
        """返回数据集中所有图片的个数"""  
        return len(self.imgs)

(4)测试

实例化数据加载器后,通过调用getitem方法,可以得到经过处理后的 3 × 244 × 244 3\times244\times244 3 × 244 × 244 的图片数据

if __name__ == "__main__":
    root = "./data/train"
    train = Mydata(root, train=True)  #实例化加载器
    img,label=train.__getitem__(5)    #获取index为5的图片
    print(img.dtype)
    print(img.size(),label)   
    print(len(train))    #数据集大小
#输出
torch.float32
torch.Size([3, 224, 224]) 0
3200

裁剪处理后图片如下所示,大小为 224X224 :

四、模型

模型都放在 models.py 中,主要用了一些经典的CNN模型 :

  • LeNet
  • ResNet
  • ResNet
  • SqueezeNet

下面给出重点关注的LeNet模型和AlexNet模型:

1 LeNet

LeNet模型是一个早期用来识别手写数字图像的卷积神经网络,这个名字来源于LeNet论文的第一作者Yann LeCun。LeNet展示了通过梯度下降训练卷积神经网络可以达到手写数字识别在当时最先进的结果,LeNet模型结构图示如下所示:

由上图知,LeNet分为 卷积层块全连接层块 两个部分,在本项目中我对LeNet模型做了 相应的调整 :

  • 采用三个卷积层
  • 三个全连接层
  • ReLu作为激活函数
  • 在卷积后正则化
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.relu = nn.ReLU()
        self.sigmoid = nn.Sigmoid()
        #三个卷积层
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=3,
                out_channels=16,
                kernel_size=3,
                stride=2,
            ),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(
                in_channels=16,
                out_channels=32,
                kernel_size=3,
                stride=2,
            ),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(
                in_channels=32,
                out_channels=64,
                kernel_size=3,
                stride=2,
            ),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        #三个全连接层
        self.fc1 = nn.Linear(3 * 3 * 64, 64)
        self.fc2 = nn.Linear(64, 10)
        self.out = nn.Linear(10, 2)   #分类类别为2,

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = x.view(x.shape[0], -1)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.out(x)
        return x

调用torchsummary库,可以观察模型的结构、参数:

2 AlexNet模型

2012年,AlexNet横空出世,这个模型的名字来源于论文第一作者的姓名Alex Krizhevsky。AlexNet使用了 8层卷积神经网络 ,由5个卷积层和3个池化Pooling 层 ,其中还有3个全连接层构成。AlexNet 跟 LeNet 结构类似,但使?了更多的卷积层和更?的参数空间来拟合?规模数据集 ImageNet,它是浅层神经?络和深度神经?络的分界线。

特点:

  • 在每个卷积后面添加了Relu激活函数,解决了Sigmoid的梯度消失问题,使收敛更快。
  • 使用随机丢弃技术(dropout)选择性地忽略训练中的单个神经元,避免模型的过拟合(也使用数据增强防止过拟合)
  • 添加了归一化LRN(Local Response Normalization,局部响应归一化)层,使准确率更高。
  • 重叠最大池化(overlapping max pooling),即池化范围 z 与步长 s 存在关系 z>s 避免平均池化(average pooling)的平均效应

五、训练

训练在 main.py 中,主要是对获取数据、训练、评估、模型的保存等功能的整合,能够实现以下功能:

  • 指定训练模型、epoches等基本参数
  • 是否选用 预训练模型
  • 接着从上次的中断的地方 继续训练
  • 保存最好的模型 和最后一次训练的模型
  • 对模型的评估:Loss和Accuracy
  • 利用 TensorBoard可视化

1 开始训练

在 main.py 程序中,设置参数和模型( models.py 中可以查看有哪些模型):

在vscode中点击运行或在命令行中输入:python main.py

即可开始训练,开始训练后效果如下:

若程序中断,设置resume参数为True,可以接着上次的模型继续训练,可以非常方便的 任意训练多少次 。

2 tensorboard可视化

在vscode中打开tensorboard,或者在命令行中进入当前项目文件夹下输入

tensorboard --logdir runs

即可打开训练中的可视化界面,可以很方便的观察模型的效果:

如上图所示,可以非常方便的观察任意一个模型训练过程的效果!

六、不同模型训练结果分析

1 LeNet模型

在用LeNet模型训练的过程中,通过调整数据集数量、是否用数据增强等不同的方法,来训练模型,并观察模型的训练效果。

(1) 数据集数量=1000,无数据增强

通过Tensorboard可视化可以观察到:

  • 验证集准确率(Accuracy)在上升,训练 30epoch 左右,达到最终 63% 左右的最好效果
  • 但验证集误差(Loss)也在上升,训练集误差一直下降
  • 训练集误差 接近于0

说明模型在训练集上效果好,验证集上效果不好,泛化能力差,可以推测出模型 过拟合 了。而这个原因也是比较好推测的,数据集比较少。

(2) 数据集数量=4000,无数据增强

同样 过拟合了 ,但是最后的准确率能达到 68% 左右,说明数据集增加有效果,用全部数据进行训练效果应该更好。

(3)数据集数量=4000,数据增强

这次数据集数量同上一个一样为4000,但采用了如下的数据增强:

  • 水平翻转,概率为p=0.5
  • 上下翻转,概率为p=0.1

我们可以看到这次一开始验证集误差是 下降的 ,说明一开始没有过拟合,但到15个epoch之后验证集误差开始上升了,说明已经开始过拟合了,但最后的准确率在 71% 左右,说明数据增强对扩大数据集有明显的效果。

(4)数据集=4000,数据增强

这次数据集数量为4000,但采用了如下的数据增强:

  • 水平翻转,概率为p=0.5
  • 上下翻转,概率为p=0.5
  • 亮度变化

可以看到:

  • 35个epoch之前,验证集误差呈 下降 趋势,准确率也一直上升,最高能到 75%
  • 但在35个epoch之后,验证集误差开始上升,准确率也开始下降

说明使用了更强的数据增强之后,模型效果更好了。

(5)使用dropout函数抑制过拟合

本次数据集和数据增强方式同(4),但是在模型的第一个 全连接层 加入dropout函数。

dropout原理:

训练过程中随机丢弃掉一些参数。在前向传播的时候,让某个神经元的激活值以一定的概率p(伯努利分布)停止工作,这样可以使模型泛化性更强。

不使用dropout示意图 使用dropout示意图

这样相当于每次训练的是一个比较"瘦"的模型,更不容易过拟合

加入dropout函数后,训练85个epochs,可以观察到效果 十分显著 :

  • 验证集的误差总体呈现下降趋势,且最后 没有反弹 !
  • 训练集误差下降比较慢了!
  • 准确率一直上升,最后可以达到 76% !

说明模型最后没有过拟合,并且效果还不错。

2 AlexNet模型

将AlexNet模型参数打印出来:

可以看到AlexNet相比LeNet,参数数目有数量级的上升,而在数据量比较小的情况下,很容易梯度消失,经过反复的调试:

  • 要在卷积层加入正则化
  • 优化器选择SGD
  • 学习率不能过大

才能避免验证集的准确率一直在 50%

经过调试,较好的一次结果如下所示,最终准确率能达到 78%

3 squeezeNet模型

在后面两个模型中,使用迁移学习的方法。

迁移学习(Transfer Learning) 是机器学习中的一个名词,是指一种学习对另一种学习> 的影响,或习得的经验对完成其它活动的影响。迁移广泛存在于各种知识、技能与社会规范> 的学习中,将某个领域或任务上学习到的知识或模式应用到不同但相关的领域或问题中。

使用squeezeNet预训练模型,在迭代16个epoch后,准确率可以达到 93%

4 resNet模型

使用resnet50的预训练模型,训练25个epoch后,准确率可以达到 98%!

总结

模型

测试集预测准确率

LeNet(无数据增强)

68%

LeNet(数据增强)

75%

LeNet(采用Dropout)

76%

Alexnet

78%

squeezeNet(迁移学习)

93%

resNet

98%

七、预测

模型训练好后,可以打开 predict.py 对新图片进行预测,给定用来预测的模型和预测的图片文件夹:

model = LeNet1() # 模型结构
modelpath = "./runs/LeNet1_1/LeNet1_best.pth" # 训练好的模型路径
checkpoint = torch.load(modelpath)  
model.load_state_dict(checkpoint)  # 加载模型参数
root = "test_pics"

运行 predict.py 会将预测的图片储存在 output 文件夹中,如下图所示

会给出预测的类别和概率。

相关推荐

其实TensorFlow真的很水无非就这30篇熬夜练

好的!以下是TensorFlow需要掌握的核心内容,用列表形式呈现,简洁清晰(含表情符号,<300字):1.基础概念与环境TensorFlow架构(计算图、会话->EagerE...

交叉验证和超参数调整:如何优化你的机器学习模型

准确预测Fitbit的睡眠得分在本文的前两部分中,我获取了Fitbit的睡眠数据并对其进行预处理,将这些数据分为训练集、验证集和测试集,除此之外,我还训练了三种不同的机器学习模型并比较了它们的性能。在...

机器学习交叉验证全指南:原理、类型与实战技巧

机器学习模型常常需要大量数据,但它们如何与实时新数据协同工作也同样关键。交叉验证是一种通过将数据集分成若干部分、在部分数据上训练模型、在其余数据上测试模型的方法,用来检验模型的表现。这有助于发现过拟合...

深度学习中的类别激活热图可视化

作者:ValentinaAlto编译:ronghuaiyang导读使用Keras实现图像分类中的激活热图的可视化,帮助更有针对性...

超强,必会的机器学习评估指标

大侠幸会,在下全网同名[算法金]0基础转AI上岸,多个算法赛Top[日更万日,让更多人享受智能乐趣]构建机器学习模型的关键步骤是检查其性能,这是通过使用验证指标来完成的。选择正确的验证指...

机器学习入门教程-第六课:监督学习与非监督学习

1.回顾与引入上节课我们谈到了机器学习的一些实战技巧,比如如何处理数据、选择模型以及调整参数。今天,我们将更深入地探讨机器学习的两大类:监督学习和非监督学习。2.监督学习监督学习就像是有老师的教学...

Python教程(三十八):机器学习基础

...

Python 模型部署不用愁!容器化实战,5 分钟搞定环境配置

你是不是也遇到过这种糟心事:花了好几天训练出的Python模型,在自己电脑上跑得顺顺当当,一放到服务器就各种报错。要么是Python版本不对,要么是依赖库冲突,折腾半天还是用不了。别再喊“我...

超全面讲透一个算法模型,高斯核!!

...

神经网络与传统统计方法的简单对比

传统的统计方法如...

AI 基础知识从0.1到0.2——用“房价预测”入门机器学习全流程

...

自回归滞后模型进行多变量时间序列预测

下图显示了关于不同类型葡萄酒销量的月度多元时间序列。每种葡萄酒类型都是时间序列中的一个变量。假设要预测其中一个变量。比如,sparklingwine。如何建立一个模型来进行预测呢?一种常见的方...

苹果AI策略:慢哲学——科技行业的“长期主义”试金石

苹果AI策略的深度原创分析,结合技术伦理、商业逻辑与行业博弈,揭示其“慢哲学”背后的战略智慧:一、反常之举:AI狂潮中的“逆行者”当科技巨头深陷AI军备竞赛,苹果的克制显得格格不入:功能延期:App...

时间序列预测全攻略,6大模型代码实操

如果你对数据分析感兴趣,希望学习更多的方法论,希望听听经验分享,欢迎移步宝藏公众号...

AI 基础知识从 0.4 到 0.5—— 计算机视觉之光 CNN

...

取消回复欢迎 发表评论: