本篇博文基于python3.7,Tensorflow2.1GPU版本,运行在Win10,pycharm作为IDE。相应的环境搭建,可以看博主之前的博文。
深度学习系列笔记——壹(深度学习环境的搭建及填坑之旅,基于windows)
kaggle猫狗大战官方链接
kaggle的注册和简单使用,本博客不再赘述,自行百度即可。
(1)下载数据集
(下载时建议使用科学上网)
训练所用到的Train Dataset
测试所用到的Test Dataset
提交所用到的submission.csv文件
下载完成后,分别解压到train和test目录,得到如下结构
其中test有12500张不带标签的猫狗图片,train中含有以名字为前缀标签的猫狗图片各12500张。
猫的图片
狗的图片
为了后续训练的方便,我将猫狗的图片分别放到train目录下的cats,dogs文件夹中。以便后续程序读取文件时能够直接对类别分类。
(2)整理数据集
由于官方没有给出验证集,因此博主直接将一部分训练集的数据分隔为验证集,博主这里设置猫和狗图片的验证集为猫狗各1100张。这样划分之后,猫狗的训练集将会剩下各11400张。
设置验证集,其实是在检测模型的泛化能力,检验模型对于未训练过的例子是否有很好的鲁棒性(健壮性),这样将有助于我们了解模型训练是否出现了过拟合现象。
另外,在本例中测试集是没有标签的,这里需要注意,且猫和狗的图片混合在一起。
(3)观察数据
这里的观察数据,其实是观察一下是否出现了很多脏数据,训练数据的质量很大程度会影响到模型最终的准确率。
另一方面,本例很显然可以利用CNN实现二分类,因此需要对数据的大小进行统一后送入模型,大小尺寸不一的图片对于训练好的模型是不能进行预测的,需要全部统一为模型设置的尺寸。
为方便起见以及考虑到过大的图片尺寸会导致模型训练变得极其缓慢(最终还是归结到硬件性能不足)。
官方给出的数据集,随便拿一张图,就有接近500x500的像素,这种尺度对于硬件性能不足的初学者来说简直是灾难。因为模型很可能在很长一段时间无法达到收敛且精度还很难达到要求。
因此博主这里将图片设置为200x200的尺寸。
由于部分图片的尺寸和1:1略有不同,因此调整后图片可能变扁或者变长,但是对于图中的猫狗识别其实影响没有很大。此处和经典的AlexNet使用的224x224,227x227以及VGG之类的模型略有不同,本篇作为初次尝试CNN的实际应用,从简考虑,后期可在此基础上进行一定的调整。另外读者若硬件性能较佳,可尝试更大尺寸的图片喂入CNN,构造出更高精度的模型
(1)数据增强
卷积神经网络有一个特点,在一定范围内(resnet便很好的诠释了为什么),增加网络的层数,往往能获得更好的效果,因为深层次的卷积层能够提取出更多表层网络无法提取出的特点,而网络层数的加深,也就意味着模型参数将会变得非常多,几千万甚至上亿的模型都是家常便饭,而随着网络层数的增加,待训练参数的增加,更意味着需要更加充足的数据去训练模型。
博主印象较为深刻的是吴恩达老师在深度学习课程中提到的,当训练数据不足时,太深的模型往往是在尝试 “记住” 数据,而不是学习数据。如何使得模型无法记住数据,而是强迫模型去学习数据内在的联系呢?这个时候,数据增强便派上了用场。这篇知乎的文章讲得不错,数据增强。
简言之,数据增强,就是在数据量不足的情况下,对已有的图片进行微小的改变。比如旋转(flips)、移位(translations)、旋转(rotations)等微小的改变。这些操作作用在像素层面,会使得我们的网络会认为这是不同的图片。从而迫使它去学习而不是生硬的记住图片。
(图片来源于网络,侵删)
(2)代码实现
keras为我们提供了很好的辅助,帮助我们在简单的数据上快速扩充出大量的数据,利用数据增强,我们能够让模型更好的学会如何去学习数据,而不是单纯的记住数据。
# 导入包
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
#ImageDataGenerator是用于实时数据增强的一个类,帮助我们快速实现数据的翻转,平移,旋转等操作
from tensorflow.keras import layers
#这里的layers是后面用到的,暂且不表
import os
import time
import matplotlib.pyplot as plt
start = time.time()
#用于后期模型训练总时间的计算,按下不表
# 设置目录路径,定位到前面设置的猫狗数据存放位置
PATH = os.path.join('D:/Desktop/catVSdog/data') # 图片数据集的根目录
# 将目录区分位猫狗训练集和验证集
train_dir = os.path.join(PATH, 'train') # train数据集 相对于根目录
validation_dir = os.path.join(PATH, 'validation') # validation数据集 相对于根目录
train_cats_dir = os.path.join(train_dir, 'cats') # train目录下的文件夹 每个会在之后分为一类
train_dogs_dir = os.path.join(train_dir, 'dogs')
validation_cats_dir = os.path.join(validation_dir, 'cats') # validation目录下的文件夹 每个会在之后分为一类
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
num_cats_tr = len(os.listdir(train_cats_dir))
num_dogs_tr = len(os.listdir(train_dogs_dir))
num_cats_val = len(os.listdir(validation_cats_dir))
num_dogs_val = len(os.listdir(validation_dogs_dir))
total_train = num_cats_tr + num_dogs_tr # 文件数量求和方便后续训练图片并设置步长时复用
total_val = num_cats_val + num_dogs_val
# 为方便起见,设置变量以在预处理数据集和训练网络时使用
batch_size = 32
epochs = 6
IMG_HEIGHT = 200 #图片的尺寸设置
IMG_WIDTH = 200
# 使用实时数据增强生成一批张量图像数据。 通过通道方式获取图片
#设置训练集
train_image_generator = ImageDataGenerator(rescale=1. / 255, rotation_range=5, horizontal_flip=True)
"""
rotation_range=5 指的是将图片在0-5°内随机旋转, horizontal_flip=True指的是将图片随机进行镜像翻转
ImageDataGenerator还有很多其他的操作,可以前往官网查询对应的API使用
[官网教程](https://tensorflow.google.cn/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator)
"""
#设置验证集
validation_image_generator = ImageDataGenerator(rescale=1. / 255)
#验证集这里不再进行数据增强,有需要也可以按照训练集的方式进行设置
"""
此处设置训练集的生成器,用于对训练数据的实时生成,由于训练集较大,直接加载至显存或者内存中不显示
因此采用一边读取数据至内存一边训练的方式,二者互不干扰
"""
#训练集数据生成器
train_data_gen = train_image_generator.flow_from_directory(
batch_size=batch_size, directory=train_dir, shuffle=True,
target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary')
#验证集数据生成器
val_data_gen = validation_image_generator.flow_from_directory(
batch_size=batch_size, directory=validation_dir,
target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary')
至此,我们已经完成了对于数据的处理操作,下一篇博文博主将继续介绍如何利用Keras搭建出猫狗大战的CNN模型。
深度学习系列笔记——贰 (基于Tensorflow Keras搭建的猫狗大战模型 二)
在三中,将总结整个项目的全部代码,并利用训练得到的模型,对测试图片进行相应的预测。
深度学习系列笔记——贰 (基于Tensorflow Keras搭建的猫狗大战模型 三)