100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 【Keras】 计算机视觉 CNN 实现猫狗图片分类

【Keras】 计算机视觉 CNN 实现猫狗图片分类

时间:2021-09-06 12:29:48

相关推荐

【Keras】 计算机视觉 CNN 实现猫狗图片分类

目录

综述图像预览数据预处理验证集模型训练训练结果

综述

本项目旨在通过一个公开数据集,训练一个可以将图片中的猫和狗进行分类的模型。

数据集包括25,000 张训练数据。其中猫和狗的照片各 12,500 张。测试集/验证集总共包括 12,500 张图片。

本项目将使用 Keras 作为工具包。使用 GPU 进行训练。

图像预览

这里我们首先预览两张训练集中的图片。比如这一张:

我们打印一下图片的名称和尺寸:

dog.10011.jpg(415, 449, 3)

换一张猫的图片试试

我们再来打印一下

cat.10011.jpg(198, 179, 3)

可以看到,图片都是以 jpg 格式存储,并且以 label.num 来进行命名。这张即表示,这是测试集中的第 10011 张猫的照片。

能够正确理解数据存储格式非常重要,因为这样,我们才能高效、正确的使用我们的数据。

至此,我们对于数据集的理解如下:

训练集一共25000张图片,猫和狗各一半。测试集一共12500张图片。图片均为 rgb 三维的 jpg 图片。图片命名即表示了该图片的分类。图片尺寸不一,没有进行统一处理。

因此,对于数据预处理部分,我们的思路就非常清晰了:

我们使用 rgb 图片进行训练,所以无需进行 grayscale所有图片都需要统一成 (224, 224, 3) 尺寸我们需要对图片数据进行 normalization。

数据预处理

由于图片的数量和尺寸较大,我们不可能将所有图片一次性带入到内存中训练。

因此,我们通过将设定批次将图片输送给神经网络训练的方式,来达到目的。而 Keras 很好的提供了相应的方法。

对于二分类问题,Keras 提供了一一种很好的解决思路。不同于通用的将 label 进行 one-hot encoding。我们可以通过将不同标签的图片放入不同文件夹的方式来达到同样的目的。实现此方法的代码如下:

import ostrain_file = './train/'cat_tartget_file = './keras_train/cat/'dog_target_file = './keras_train/dog/'train_cat_names = [i for i in os.listdir(train_file) if 'cat' in i]train_dog_names = [i for i in os.listdir(train_file) if 'dog' in i]import shutilfor name in train_cat_names:src = train_file + namedst = cat_tartget_file + nameshutil.copyfile(src, dst)for name in train_dog_names:src = train_file + namedst = dog_target_file + nameshutil.copyfile(src, dst)

运行代码之后,项目文件夹中出现了如下:

即代表分类完成。这时候,我们需要使用到 Keras 的方法器 ImageDataGenerator 来完成。

对于图片的预处理,我们按照顺序进行如下的操作:

将图片数据数据标准化。所有数值落在(0,1)的范围内。将图片尺寸调整为 (224, 224, 3)。随机的将图片进行横向翻转,提升神经网络的学习效果。

实现的代码如下:

from keras.preprocessing.image import ImageDataGeneratortrain_generator = ImageDataGenerator(rescale=1./255.0, horizontal_flip=True)train_dataset = train_generator.flow_from_directory(directory=r'./keras_train/', target_size=(224, 224), color_mode='rgb', class_mode='binary', batch_size=32)

运行代码之后可以看到

Using TensorFlow backend.Found 25000 images belonging to 2 classes.

训练集的 25000 图片都被迭代器成功读取,并且分为了两类。这里,如果我们没有声明 label 的顺序,那么将按照文件夹的顺序排列,即 0 代表 cat,1 代表 dog。

验证集

验证集的操作步骤和训练集是一致的。只不过,验证集元数据本身是没有分类的。于是采用了一种比较笨的办法…先用训练好的模型对验证集数据进行分类,然后再人工校验。(当了一把数据女工)。

但这其中也有一个有意思的发现,该模型对于黑色的狗和猫,出现错误的概率明显大于其他颜色。

在手动标注完成这时候,使用和上面一样的方法进行预加载。

模型训练

我在设计这个模型的时候,参考了 VGG-16 的结构。不同于 VGG-16,由于本身运算性能的限制,为了简化结构,提升运算效率,我删除了大部分卷积层。

在第一个和第二个全连接层中使用了 Dropout 层。旨在为了减少过拟合的情况。一开始我使用了四个全连接层,并在每个全连接层中使用了 Dropout 层,但是发现模型很难收敛。于是我使用了当前的选择。

batch_size 选择了 32 是因为再高会导致训练速度过低。

优化器我选择了比较通用的 Adam。learning rate 则选择了较小的 0.0001。我会在后面增大学习率,来看看有什么变化。

在创建模型的时候,使用Sequential和 Add 模式都是一样的,且都需要在第一层声明 input_shape。这里需要注意,模型传入的是一个四维的数据,(batch_size,dim,width,height)。然而,在声明 input_shape 的时候无需包含 batch_size。因为这个在之前创建迭代器的时候就已经生命好了。

实现代码如下:

import kerasfrom keras.models import Sequentialfrom keras.layers import Dense, Conv2D, MaxPool2D, Flatten, Dropoutfrom keras.optimizers import Adamdef vgg16_model():model = Sequential()model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(224, 224, 3)))model.add(MaxPool2D(pool_size=(2, 2), padding='same'))model.add(Dropout(rate=0.1))model.add(Conv2D(filters=128, kernel_size=(3, 3), padding='same', activation='relu'))model.add(MaxPool2D(pool_size=(2, 2), padding='same'))model.add(Dropout(rate=0.1))model.add(Conv2D(filters=256, kernel_size=(3, 3), padding='same', activation='relu'))model.add(MaxPool2D(pool_size=(2, 2), padding='same'))model.add(Dropout(rate=0.1))model.add(Conv2D(filters=512, kernel_size=(3, 3), padding='same', activation='relu'))model.add(MaxPool2D(pool_size=(2, 2), padding='same'))model.add(Dropout(rate=0.1))model.add(Conv2D(filters=512, kernel_size=(3, 3), padding='same', activation='relu'))model.add(MaxPool2D(pool_size=(2, 2), padding='same'))model.add(Flatten())model.add(Dense(units=4096, activation='relu'))model.add(Dropout(rate=0.5))model.add(Dense(units=1024, activation='relu'))model.add(Dropout(rate=0.5))model.add(Dense(units=512, activation='relu'))model.add(Dense(units=1, activation='sigmoid'))pile(loss='binary_crossentropy',optimizer=Adam(lr=0.0001),metrics=['accuracy'])return model

训练结果

我们将训练时候产生的数据:train_loss,train_acc,val_loss,val_acc 以 csv 的形式进行保存,方便我们之后进行模型分析。实现代码如下:

以下是使用此模型的训练结果:

可以看到,该模型在20个epoch训练之后,训练集的准确率达到了 99.33% , loss 下降到了 0.0187。但是,第 8 个epoch 之后,验证集的准确率没有明显的提升。

这里附上整个训练的数据变化记录:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。