文章目录

  • 1. 导入需要的包,检查使用设备
  • 2. 导入数据集并修改数据集目录结构
  • 3. 数据处理
  • 4. 创建VGG Model
  • 5. 修改最后一层,冻结前面层的参数
  • 6. 训练并测试全连接层
  • 7.可视化模型预测结果(主观分析)
  • 8. 处理未分类过的待测试数据并提交到练习赛
  • 9. 总结

这个作业为 Kaggle 于2013年举办的猫狗大战比赛,判断一张输入图像是“猫”还是“狗”。
下面是使用在 ImageNet 上预训练 的 VGG 网络进行训练和测试的过程编码。

这里我们使用Google Colab来编写下面的代码。
关于Colab的使用之后有时间我再编写博客并贴上链接,下面先写深度学习代码。

1. 导入需要的包,检查使用设备

import numpy as np
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import torchvision
from torchvision import models,transforms,datasets
import time
import json# 判断是否存在GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print('Using gpu: %s ' % torch.cuda.is_available())

当使用的是GPU时,输出结果如下所示:

2. 导入数据集并修改数据集目录结构

数据集下载链接为:https://static.leiphone.com/cat_dog.rar
里面包含三个文件夹如下图所示:

test:比赛用的测试集(2000张图片,图片名为0 ~ 1999)
train:训练集(10000张猫,10000张狗,图片名分别为cat_0 ~ cat_9999,dog_0 ~ dog_9999)。
val:测试集(1000张猫,1000张狗,图片名分别为cat_0 ~ cat_999,dog_0 ~ dog_999)。

! wget -P ./drive/MyDrive/ https://static.leiphone.com/cat_dog.rar   #下载到指定目录
! unrar x cat_dog.rar ./drive/MyDrive/  #解压缩到指定目录

输出结果如下,图片被解压缩出来,并保持原有的目录结构不变:

下面这一步是为了第三步用datasets.ImageFolder()加载数据方便,所以改变了解压缩之后的目录结构。
/train/val中添加分别添加了文件夹/cats/dogs,并把猫和狗的照片分类分别放入两个文件夹中。这里如果不这样修改,datasets.ImageFolder()无法正常使用,需要使用其他方式加载数据。

%%shell
for filename in `ls ./drive/MyDrive/cat_dog/train`
doif [ ${filename: 0:3} == "cat" ] thenmkdir -p ./drive/MyDrive/cat_dog/train/catsmv -i ./drive/MyDrive/cat_dog/train/$filename ./drive/MyDrive/cat_dog/train/cats/$filenamefi
donefor filename in `ls ./drive/MyDrive/cat_dog/train`
doif [ ${filename: 0:3} == "dog" ] thenmkdir -p ./drive/MyDrive/cat_dog/train/dogsmv -i ./drive/MyDrive/cat_dog/train/$filename ./drive/MyDrive/cat_dog/train/dogs/$filenamefi
donefor filename in `ls ./drive/MyDrive/cat_dog/val`
doif [ ${filename: 0:3} == "cat" ] thenmkdir -p ./drive/MyDrive/cat_dog/val/catsmv -i ./drive/MyDrive/cat_dog/val/$filename ./drive/MyDrive/cat_dog/val/cats/$filenamefi
donefor filename in `ls ./drive/MyDrive/cat_dog/val`
doif [ ${filename: 0:3} == "dog" ] thenmkdir -p ./drive/MyDrive/cat_dog/val/dogsmv -i ./drive/MyDrive/cat_dog/val/$filename ./drive/MyDrive/cat_dog/val/dogs/$filenamefi
donefor filename in `ls ./drive/MyDrive/cat_dog/test`
domkdir -p ./drive/MyDrive/cat_dog/test/imgmv -i ./drive/MyDrive/cat_dog/test/$filename ./drive/MyDrive/cat_dog/test/img/$filename
done

此时的目录结构如下图所示:

3. 数据处理

#数据标准化
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) #图像预处理成224*224*3大小
vgg_format = transforms.Compose([transforms.CenterCrop(224),transforms.ToTensor(),normalize,])data_dir = './drive/MyDrive/cat_dog'
dsets = {x: datasets.ImageFolder(os.path.join(data_dir, x), vgg_format)for x in ['train', 'val']}dset_sizes = {x: len(dsets[x]) for x in ['train', 'val']}
dset_classes = dsets['train'].classes
# 通过下面代码可以查看 dsets 的一些属性
print(dsets['val'].classes)
print(dsets['val'].class_to_idx)
print(dsets['val'].imgs[:5])
print('dset_sizes: ', dset_sizes)

输出结果为:

分别加载训练用的数据集和测试用的数据集。

loader_train = torch.utils.data.DataLoader(dsets['train'], batch_size=64, shuffle=True, num_workers=6)
loader_valid = torch.utils.data.DataLoader(dsets['val'], batch_size=5, shuffle=False, num_workers=6)

4. 创建VGG Model

model_vgg = models.vgg16(pretrained=True)
model_vgg = model_vgg.to(device)

5. 修改最后一层,冻结前面层的参数

print(model_vgg)model_vgg_new = model_vgg;for param in model_vgg_new.parameters():param.requires_grad = False
model_vgg_new.classifier._modules['6'] = nn.Linear(4096, 2)
model_vgg_new.classifier._modules['7'] = torch.nn.LogSoftmax(dim = 1)model_vgg_new = model_vgg_new.to(device)print(model_vgg_new.classifier)

6. 训练并测试全连接层

这里将训练的学习率定为0.0001,epochs=100。
尝试过将学习率定为更小的值,发现到损失值曲线收敛的很慢,故这里选取lr=0.0001。
epochs=1时其实准确率就能达到94%以上,有较好的效果了。这里设定为100,希望能训练出更好的模型。

'''
第一步:创建损失函数和优化器损失函数 NLLLoss() 的 输入 是一个对数概率向量和一个目标标签.
它不会为我们计算对数概率,适合最后一层是log_softmax()的网络.
'''
criterion = nn.NLLLoss()# 学习率
lr = 0.0001# 随机梯度下降
optimizer_vgg = torch.optim.SGD(model_vgg_new.classifier[6].parameters(),lr = lr)'''
第二步:训练模型
'''def train_model(model,dataloader,size,epochs=1,optimizer=None):model.train()for epoch in range(epochs):running_loss = 0.0running_corrects = 0count = 0for inputs,classes in dataloader:inputs = inputs.to(device)classes = classes.to(device)outputs = model(inputs)loss = criterion(outputs,classes)           optimizer = optimizeroptimizer.zero_grad()loss.backward()optimizer.step()_,preds = torch.max(outputs.data,1)# statisticsrunning_loss += loss.data.item()running_corrects += torch.sum(preds == classes.data)count += len(inputs)print('Training: No. ', count, ' process ... total: ', size)epoch_loss = running_loss / sizeepoch_acc = running_corrects.data.item() / sizeprint('epoch: ', epoch)print('Loss: {:.8f} Acc: {:.8f}'.format(epoch_loss, epoch_acc))# 测试准确率足够大时保存模型if epoch_acc > 0.97900000:torch.save(model, './drive/MyDrive/model/model_' + str(epoch_acc)[2:] + '_' + str(epoch) + '.pth')        # 模型训练
train_model(model_vgg_new,loader_train,size=dset_sizes['train'], epochs=100, optimizer=optimizer_vgg)

下面是训练过程截图:

保存的模型如 下图所示:

选取一个刚刚保存下来的模型,导入测试数据集进行测试:

model_vgg_new = torch.load('./drive/MyDrive/model/model_9804_60.pth');
model_vgg_new = model_vgg_new.to(device)def test_model(model,dataloader,size):model.eval()predictions = np.zeros(size)all_classes = np.zeros(size)all_proba = np.zeros((size,2))i = 0running_loss = 0.0running_corrects = 0for inputs,classes in dataloader:inputs = inputs.to(device)classes = classes.to(device)outputs = model(inputs)loss = criterion(outputs,classes)           _,preds = torch.max(outputs.data,1)# statisticsrunning_loss += loss.data.item()running_corrects += torch.sum(preds == classes.data)predictions[i:i+len(classes)] = preds.to('cpu').numpy()all_classes[i:i+len(classes)] = classes.to('cpu').numpy()all_proba[i:i+len(classes),:] = outputs.data.to('cpu').numpy()i += len(classes)print('Testing: No. ', i, ' process ... total: ', size)        epoch_loss = running_loss / sizeepoch_acc = running_corrects.data.item() / sizeprint('Loss: {:.4f} Acc: {:.4f}'.format(epoch_loss, epoch_acc))return predictions, all_proba, all_classespredictions, all_proba, all_classes = test_model(model_vgg_new,loader_valid,size=dset_sizes['val'])

测试结果如下图所示:

7.可视化模型预测结果(主观分析)

随机选择一些正确的预测结果和相对应的图片输出出来,比对一下看看结果。

n_view = 8  # 单次可视化显示的图片个数
correct = np.where(predictions==all_classes)[0]
from numpy.random import random, permutation
idx = permutation(correct)[:n_view]
print('random correct idx: ', idx)
loader_correct = torch.utils.data.DataLoader([dsets['val'][x] for x in idx],batch_size = n_view,shuffle=True)
for data in loader_correct:inputs_cor,labels_cor = data
# Make a grid from batch
out = torchvision.utils.make_grid(inputs_cor)
imshow(out, title=[l.item() for l in labels_cor])

输出结果如下图所示。可以看到有些图片只有腿,计算机都能准确识别出来是猫还是狗,这种学习方法还是很强的。

8. 处理未分类过的待测试数据并提交到练习赛

/cat_dog/test/img中的图片是未分类过的,编码是从0~1999,共2000张图片,要从第6步训练并保存下来的model中选取准确率较高的model对待测试数据进行分类,并按规定将预测数据保存为下图所示格式。

代码如下图所示。
注意:文件读取顺序并不是按0.jpg,1.jpg一直顺延这样的顺序,实际上的顺序是0.jpg,10.jpg,11.jpg这样的顺序一直顺延。因此代码中我截取了文件名中的数字作为索引,这样就能无视读取顺序,将文件与预测值对应起来。

data_dir = './drive/MyDrive/cat_dog/test'
dsets = {'test': datasets.ImageFolder(data_dir, vgg_format)}
dset_sizes = len(dsets['test'])loader_test = torch.utils.data.DataLoader(dsets['test'], batch_size=1, num_workers=6)model_vgg_new = torch.load('./drive/MyDrive/model/model_9804_60.pth');
model_vgg_new = model_vgg_new.to(device)import csv
def test_model(model,dataloader,size):model.eval()predictions = np.zeros(size)i = 0for inputs,classes in dataloader:inputs = inputs.to(device)classes = classes.to(device)outputs = model(inputs)         _,preds = torch.max(outputs.data,1)# statisticspredictions[int(dsets['test'].imgs[i][0][33:-4])] = preds.to('cpu').numpy()i += 1print('Testing: No. ', i, ' process ... total: ', size)   csvFile = open("./drive/MyDrive/cat_dog_result/result.csv", "w")writer = csv.writer(csvFile)for i in range(dset_sizes):writer.writerow([i, predictions[i]])  print("Save successfully!!!")return predictionspredictions = test_model(model_vgg_new,loader_test,size=dset_sizes)

成功运行并保存成功后显示如下图所示。

将保存的文件下载下来并提交到AI研习社网站,网址如下:
https://god.yanxishe.com/41
可以得到预测结果的准确率和排名:

9. 总结

1.训练时增加epochs会训练出更好的结果,但是训练的更好的程度并不是随着epochs的增加无限增加的,故epochs选取适当的值即可,无需过大,当然也不能过小。
2.学习率不能定得过小,过小的话损失值曲线收敛的很慢,在有限的epochs中不能训练出很好地结果。学习率如果过大开始时loss下降得快,但后面会产生无法拟合的现象。因此学习率应该选取合适的值不应该过大或过小。
3.进一步改进需要采用更好的模型,如使用其他深度学习网络,增加网络深度,可能会产生更好的效果。

第四次作业:猫狗大战挑战赛相关推荐

  1. 软件工程08组-第四次作业-猫狗大战挑战赛

    第四次作业:猫狗大战挑战赛 一.代码学习 判断GPU 该段代码等同于: if torch.cuda.is_available(): device = torch.device("cuda&q ...

  2. 【AI】第四次作业:猫狗大战挑战赛

    文章目录 前言 作业要求 实验前,先明确一些概念 一.在谷歌 Colab 上完成猫狗大战VGG分类 实验目的: 实验思路: 0.代码环境Colab 1.数据下载 2.数据预处理 3.创建VGG 4.修 ...

  3. 2021年人工神经网络第四次作业:基于MATLAB的求解

    简 介: 本文选取了2021年人工神经网络第四次作业学生提交的作业.供交流使用. 关键词: 人工神经网络 #mermaid-svg-ATqdYQemfmABj2Hj {font-family:&quo ...

  4. 2021年人工神经网络第四次作业要求:第七题

    简 介: 对于MATLAB中的SimpleClass数据集合,对比了BP,RBF,SVM,SOFM,DHNN 等方法分类结果,可以看到BP,RBF,SVM,SOFM都具有非常好的分类效果.DHNN对于 ...

  5. 2021年人工神经网络第四次作业 - 第三题Cifar10

    简 介: 在Paddle下使用最基本的BP网络以及LeNet网络结构,测试了Cifar10数据集合.但实际运行在测试集合上的效果始终没有突破0.3,具体原因还需要进行查找. 后来经过测试,发现问题出现 ...

  6. 2021年人工神经网络第四次作业 - 第二题MNIST手写体识别

    简 介: ※MNIST数据集合是深度学习基础训练数据集合.改数据集合可以使用稠密前馈神经网络训练,也可以使用CNN.本文采用了单隐层BP网络和LeNet网络对于MNIST数据集合进行测试.实验结果标明 ...

  7. 2021年人工神经网络第四次作业-第四题:旋转的数字

    简 介: 本文对于作业中给定的机械数字字符识别问题进行了实验研究.通过对于采样1000样本的数据集合进行训练,经过增加DropOut的可以增加网络的泛化性能.对于网络规模的增加对训练精度没有明显的改进 ...

  8. 2021年人工神经网络第四次作业-第五题:危险品识别

    简 介: 通过对于物品X射线数据集合的整理,挑选出15类体积比较大的物品,训练LeNet网络进行识别. 关键词: X射线,危险品识别,LeNet,Paddle #mermaid-svg-wZUMACG ...

  9. 2021年人工神经网络第四次作业-第一题:LeNet对于水果与动物进行分类

    简 介: 对于有五种动物和五中水果组成的FAMNIST数据集合的图像分类问题进行了测试.本文主要是集中在前期的数据库的准备和网络的构建方面.对于网络的详细测试参见在 对于FAMNIST中的十种动物和水 ...

  10. 2021年春季学期-信号与系统-第十四次作业参考答案-第九小题参考答案

    本文是 2021年春季学期-信号与系统-第十四次作业参考答案 中各小题的参考答案. §09 第九小题 9.证明DFT的对称性质: 若:DFT{x[n]}=X[k]DFT\left\{ {x\left[ ...

最新文章

  1. 计算机二叉树讲解ppt,数据结构二叉树.ppt
  2. 如何去除C#Strings中的空格?
  3. 源码阅读分析 View的Touch事件分发
  4. 浏览器打开域名变成localhost_史上最全微信域名防封API原理及实现方案
  5. 从Nacos客户端视角来分析一下配置中心实现原理
  6. asp 退出登录修改cookie能进入后台_某logCMS的代码审计:越权到后台getshell
  7. 导出Excel,身份证号码默认为成科学计数形式,解决方法.
  8. 让SQL2000的查询分析器能够直接编辑SQL2005的视图或存储过程
  9. Mysql数据库的tinyint类型
  10. tfidf关键词提取php,TFIDF介绍
  11. 在linux平台上如何修改hostid
  12. 科学素养题(2022年2月-2022年10月)
  13. 初识等级保护,要点整理
  14. html实现短信验证的功能,怎样实现短信验证功能
  15. excel怎么一次性删除所有的批注
  16. [转贴]当杀毒软件无能为力时,手动杀毒也许是我的最后救命稻草!
  17. 超乎想象!关于5G无人机的最强科普!
  18. 2020华数杯全国大学生数学建模竞赛C题-脱贫帮扶绩效评价体系的构建与探究(二)(附MATLAB和Python代码)
  19. 苹果、李子、橙python_苹果 石榴 核桃 李子永清村念“水果经”
  20. 朗诵素材-《少年正是读书时》(两角色主持朗诵)

热门文章

  1. 图 矩阵 两点间有m的路径 矩阵乘法_代数图论I: 基本理论和无向图的同调
  2. 计算机网络自顶向下-链路层
  3. 计算机网络自顶向下-应用层
  4. Android按back后执行过程,安卓app测试获取接口返回数据,然后处理数据,放在一个button点击事件里面 执行顺序有问题?无法获取数据?...
  5. java接口参数类型为枚举_Spring MVC处理参数中的枚举类型通用实现方法
  6. Linux自动化运维第十八课
  7. linux下安装apache与php;Apache+PHP+MySQL配置攻略
  8. 《Effective C#》Item 14:使用构造函数初始化语句
  9. git由于网络原因导致 please make sure you have the correct access rights and the repository exists
  10. Swiper插件的基本使用方法和案例