卷积神经网络实现猫狗分类

一、环境配置

创建虚拟环境:
命令终端输入conda create -n tf1 python=3.6
#tf1是自己为创建虚拟环境取的名字,后面python的版本可以根据自己需求进行选择

安装tensorflow和keras
pip install 包名
#直接这样安装可以由于网络的原因,安装失败或者安装很慢
#解决方式:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名
#此次安装命令如下:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow==1.14.0
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple keras==2.2.5

二、神经网络CNN

1、简介

卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一。
顾名思义,就是将卷积与前馈神经网络结合,所衍生出来的一种深度学习算法。

2、CNN结构

①输入层
用于数据的输入
②卷积层
使用卷积核进行特征提取和特征映射
③激励层
由于卷积也是一种线性运算,因此需要增加非线性映射
④池化层
进行下采样,对特征图稀疏处理,减少数据运算量。
⑤全连接层
通常在CNN的尾部进行重新拟合,减少特征信息的损失

在这里插入图片描述

3、层次说明

①卷积层
在这里插入图片描述
上面图中是33的卷积核(卷积核一般采用33和2*2 )与上一层的结果(输入层)进行卷积的过程
②池化层
在这里插入图片描述
最大池化,它只是输出在区域中观察到的最大输入值
均值池化,它只是输出在区域中观察到的平均输入值
两者最大区别在于卷积核的不同(池化是一种特殊的卷积过程)
③全连接层
在这里插入图片描述
全连接过程,跟神经网络一样,就是每个神经元与上一层的所有神经元相连

三、数据集准备

1、下载数据集

百度网盘:
https://pan.baidu.com/s/1f-MvZl7_J6DF7P9CGBY3SQ
提取码:
ruyn

2、数据集分类

按照命名进行分类
分类前
在这里插入图片描述
分类后
在这里插入图片描述
分类代码:

import tensorflow as tf
import keras
import os, shutil 
# 原始目录所在的路径
original_dataset_dir = 'G:\\Cat_And_Dog\\kaggle\\train\\'

# 数据集分类后的目录
base_dir = 'G:\\Cat_And_Dog\\kaggle\\cats_and_dogs_small'
os.mkdir(base_dir)

# # 训练、验证、测试数据集的目录
train_dir = os.path.join(base_dir, 'train')
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir, 'validation')
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir, 'test')
os.mkdir(test_dir)

# 猫训练图片所在目录
train_cats_dir = os.path.join(train_dir, 'cats')
os.mkdir(train_cats_dir)

# 狗训练图片所在目录
train_dogs_dir = os.path.join(train_dir, 'dogs')
os.mkdir(train_dogs_dir)

# 猫验证图片所在目录
validation_cats_dir = os.path.join(validation_dir, 'cats')
os.mkdir(validation_cats_dir)

# 狗验证数据集所在目录
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
os.mkdir(validation_dogs_dir)

# 猫测试数据集所在目录
test_cats_dir = os.path.join(test_dir, 'cats')
os.mkdir(test_cats_dir)

# 狗测试数据集所在目录
test_dogs_dir = os.path.join(test_dir, 'dogs')
os.mkdir(test_dogs_dir)

# 将前1000张猫图像复制到train_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_cats_dir, fname)
    shutil.copyfile(src, dst)

# 将下500张猫图像复制到validation_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_cats_dir, fname)
    shutil.copyfile(src, dst)
    
# 将下500张猫图像复制到test_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_cats_dir, fname)
    shutil.copyfile(src, dst)
    
# 将前1000张狗图像复制到train_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# 将下500张狗图像复制到validation_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# 将下500张狗图像复制到test_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_dogs_dir, fname)
    shutil.copyfile(src, dst)

查看分类后,对应目录下图片数量

#输出数据集对应目录下图片数量
print('total training cat images:', len(os.listdir(train_cats_dir)))
print('total training dog images:', len(os.listdir(train_dogs_dir)))
print('total validation cat images:', len(os.listdir(validation_cats_dir)))
print('total validation dog images:', len(os.listdir(validation_dogs_dir)))
print('total test cat images:', len(os.listdir(test_cats_dir)))
print('total test dog images:', len(os.listdir(test_dogs_dir)))

在这里插入图片描述

四、 猫狗分类的实例——基准模型

1、构建网络模型

#网络模型构建
from keras import layers
from keras import models
#keras的序贯模型
model = models.Sequential()
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#卷积层,卷积核2*2,激活函数relu
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#flatten层,用于将多维的输入一维化,用于卷积层和全连接层的过渡
model.add(layers.Flatten())
#全连接,激活函数relu
model.add(layers.Dense(512, activation='relu'))
#全连接,激活函数sigmoid
model.add(layers.Dense(1, activation='sigmoid'))
#查看模型各层的参数状况
#输出模型各层的参数状况
model.summary()

在这里插入图片描述

2、配置训练方法

model.compile(optimizer = 优化器,
              loss = 损失函数,
              metrics = ["准确率”])

优化器和损失函数可以是字符串形式的名字,也可以是函数形式。

from keras import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])

3、转换格式

将训练和验证的图片,调整为150*150

from keras.preprocessing.image import ImageDataGenerator

# 所有图像将按1/255重新缩放
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # 这是目标目录
        train_dir,
        # 所有图像将调整为150x150
        target_size=(150, 150),
        batch_size=20,
        # 因为我们使用二元交叉熵损失,我们需要二元标签
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

查看处理结果

#查看上面对于图片预处理的处理结果
for data_batch, labels_batch in train_generator:
    print('data batch shape:', data_batch.shape)
    print('labels batch shape:', labels_batch.shape)
    break

4、模型训练并保存生成的模型

#模型训练过程
history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=50)
#保存训练得到的的模型
model.save('G:\\Cat_And_Dog\\kaggle\\cats_and_dogs_small_1.h5')

在这里插入图片描述

5、结果可视化

#对于模型进行评估,查看预测的准确性
import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

在这里插入图片描述
在这里插入图片描述

训练的loss是成上升趋势
过拟合是为了得到一致假设而使假设变得过度严格,实际训练得到的模型的分类效果不佳。

五、调整基准模型

1、图像增强

利用图像生成器定义一些常见的图像变换,图像增强就是通过对于图像进行变换,从而,增强图像中的有用信息。

#该部分代码及以后的代码,用于替代基准模型中分类后面的代码(执行代码前,需要先将之前分类的目录删掉,重写生成分类,否则,会发生错误)
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
      rotation_range=40,
      width_shift_range=0.2,
      height_shift_range=0.2,
      shear_range=0.2,
      zoom_range=0.2,
      horizontal_flip=True,
      fill_mode='nearest')

①rotation_range
一个角度值(0-180),在这个范围内可以随机旋转图片
②width_shift和height_shift
范围(作为总宽度或高度的一部分),在其中可以随机地垂直或水平地转换图片
③shear_range
用于随机应用剪切转换
④zoom_range
用于在图片内部随机缩放
⑤horizontal_flip
用于水平随机翻转一半的图像——当没有假设水平不对称时(例如真实世界的图片)
⑥fill_mode
用于填充新创建像素的策略,它可以在旋转或宽度/高度移动之后出现

2、增强后的图像

import matplotlib.pyplot as plt
# This is module with image preprocessing utilities
from keras.preprocessing import image
fnames = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)]
# We pick one image to "augment"
img_path = fnames[3]
# Read the image and resize it
img = image.load_img(img_path, target_size=(150, 150))
# Convert it to a Numpy array with shape (150, 150, 3)
x = image.img_to_array(img)
# Reshape it to (1, 150, 150, 3)
x = x.reshape((1,) + x.shape)
# The .flow() command below generates batches of randomly transformed images.
# It will loop indefinitely, so we need to `break` the loop at some point!
i = 0
for batch in datagen.flow(x, batch_size=1):
    plt.figure(i)
    imgplot = plt.imshow(image.array_to_img(batch[0]))
    i += 1
    if i % 4 == 0:
        break
plt.show()

在这里插入图片描述

3、网络模型增加一层dropout

#网络模型构建
from keras import layers
from keras import models
#keras的序贯模型
model = models.Sequential()
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#卷积层,卷积核2*2,激活函数relu
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2, 2)))
#flatten层,用于将多维的输入一维化,用于卷积层和全连接层的过渡
model.add(layers.Flatten())
#退出层
model.add(layers.Dropout(0.5))
#全连接,激活函数relu
model.add(layers.Dense(512, activation='relu'))
#全连接,激活函数sigmoid
model.add(layers.Dense(1, activation='sigmoid'))
#输出模型各层的参数状况
model.summary()
from keras import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])

不添加dropout的网络结构:
在这里插入图片描述
添加dropout后的网络结构:
在这里插入图片描述

4、训练模型

train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,)
# Note that the validation data should not be augmented!
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=32,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=100,
      validation_data=validation_generator,
      validation_steps=50)
model.save('G:\\Cat_And_Dog\\kaggle\\cats_and_dogs_small_2.h5')

只进行数据增强的训练结果:
在这里插入图片描述

数据增强和dropout层增加的训练结果:
在这里插入图片描述

5、结果可视化

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()

只进行数据增强的可视化结果:
在这里插入图片描述
在这里插入图片描述
数据增强和dropout层增加的可视化结果:
在这里插入图片描述
在这里插入图片描述

loss的整体趋势是变小的
前者在训练过程中波动会更大,后者在准确上小于前者。两者虽然在准确率有所变小,但是都避免了过拟合。

六、参考

https://blog.csdn.net/qq_43279579/article/details/117298169

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Python是一种广泛应用于人工智能领域的编程语言,而卷积神经网络(Convolutional Neural Network,CNN)则是一种深度学习模型,常用于图像识别和分类任务。在Python中,我们可以使用各种深度学习框架如TensorFlow、PyTorch等来实现卷积神经网络分类任务。 首先,我们需要加载用于训练和测试的图像数据集,通常我们会使用像Keras这样的库来方便地处理数据。然后,我们可以定义卷积神经网络的结构,这包括卷积层、池化层和全连接层等。在Python中,我们可以利用TensorFlow或PyTorch等框架来构建这些层,并将它们组合成一个完整的卷积神经网络模型。 接着,我们需要对模型进行训练。在Python中,我们可以使用深度学习框架提供的优化器和损失函数来编译模型,并用训练集上的数据来训练模型。训练过程中,我们可以监控模型在验证集上的表现,并根据表现来调整模型的超参数以及结构。 最后,我们可以使用训练好的模型来对新的图像进行分类。在Python中,我们可以使用训练好的模型来进行预测,并输出图像的分类结果。 总而言之,Python提供了丰富的深度学习库和工具,使得实现卷积神经网络分类任务变得简单而高效。通过Python,我们可以轻松地加载数据、构建模型、训练模型和进行预测,从而实现各种卷积神经网络分类任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值