0


使用卷积神经网络实现猫狗分类任务

  使用卷积神经网络在猫狗分类数据集上实现分类任务。

一、数据集下载链接

  猫狗分类数据集链接 → 提取码:1uwy。

二、基础环境配置

  1. Windows10 + Anaconda3 + PyCharm 2019.3.3
  2. 安装CPU版本的TensorFlow
  3. 在PyCharm中配置好TensorFlow环境

三、训练及测试过程

  1. 在PyCharm中新建猫狗分类项目Classification-cats-and-dogs。第一步依次点击FileNew Project...后,第二步点击Pure Python后选择好新建项目的位置,然后点击Create在这里插入图片描述
  2. 给新建的项目配置好TensorFlow环境。第一步依次点击FileSettings...后,第二步点击Project Interpreter后,再点击Show All...选择tensorflow环境,然后再依次点击OKOK在这里插入图片描述
  3. 在猫狗分类项目Classification-cats-and-dogs中新建分类模型文件classification.py。第一步右击项目Classification-cats-and-dogs后依次选择NewPython File,第二步给新建的文件命名classification后回车。在这里插入图片描述
  4. classification.py文件的代码如下所示。
  1. import os
  2. import tensorflow as tf
  3. from tensorflow.keras.optimizers import RMSprop
  4. from tensorflow.keras.preprocessing.image import ImageDataGenerator
  5. import matplotlib.pyplot as plt
  6. base_dir ='E:/Remote Sensing/Data Set/cats_and_dogs'# 指定每一种数据的位置
  7. train_dir = os.path.join(base_dir,'train')
  8. validation_dir = os.path.join(base_dir,'validation')# Directory with our training cat/dog pictures
  9. train_cats_dir = os.path.join(train_dir,'cats')
  10. train_dogs_dir = os.path.join(train_dir,'dogs')# Directory with our validation cat/dog pictures
  11. validation_cats_dir = os.path.join(validation_dir,'cats')
  12. validation_dogs_dir = os.path.join(validation_dir,'dogs')# 设计模型
  13. model = tf.keras.models.Sequential([# 我们的数据是150x150而且是三通道的,所以我们的输入应该设置为这样的格式。
  14. tf.keras.layers.Conv2D(16,(3,3), activation='relu', input_shape=(256,256,3)),
  15. tf.keras.layers.MaxPooling2D(2,2),
  16. tf.keras.layers.Conv2D(32,(3,3), activation='relu'),
  17. tf.keras.layers.MaxPooling2D(2,2),
  18. tf.keras.layers.Conv2D(64,(3,3), activation='relu'),
  19. tf.keras.layers.MaxPooling2D(2,2),# Flatten the results to feed into a DNN
  20. tf.keras.layers.Flatten(),# 512 neuron hidden layer
  21. tf.keras.layers.Dense(512, activation='relu'),# 二分类只需要一个输出
  22. tf.keras.layers.Dense(1, activation='sigmoid')])
  23. model.summary()# 打印模型相关信息# 进行优化方法选择和一些超参数设置# 因为只有两个分类。所以用2分类的交叉熵,使用RMSprop,学习率为0.001.优化指标为accuracy
  24. model.compile(optimizer=RMSprop(lr=0.001),
  25. loss='binary_crossentropy',
  26. metrics=['acc'])# 数据处理# 把每个数据都放缩到01范围内
  27. train_datagen = ImageDataGenerator(rescale=1.0/255.)
  28. test_datagen = ImageDataGenerator(rescale=1.0/255.)# 生成训练集的带标签的数据
  29. train_generator = train_datagen.flow_from_directory(train_dir,# 训练图片的位置
  30. batch_size=20,# 每一个投入多少张图片训练
  31. class_mode='binary',# 设置我们需要的标签类型
  32. target_size=(150,150))# 将图片统一大小# 生成验证集带标签的数据
  33. validation_generator = test_datagen.flow_from_directory(validation_dir,# 验证图片的位置
  34. batch_size=20,# 每一个投入多少张图片训练
  35. class_mode='binary',# 设置我们需要的标签类型
  36. target_size=(150,150))# 将图片统一大小# 进行训练
  37. history = model.fit_generator(train_generator,
  38. validation_data=validation_generator,
  39. steps_per_epoch=100,
  40. epochs=15,
  41. validation_steps=50,
  42. verbose=2)# 保存训练的模型
  43. model.save('model.h5')# 得到精度和损失值
  44. acc = history.history['acc']
  45. val_acc = history.history['val_acc']
  46. loss = history.history['loss']
  47. val_loss = history.history['val_loss']
  48. epochs =range(len(acc))# 得到迭代次数# 绘制精度曲线
  49. plt.plot(epochs, acc)
  50. plt.plot(epochs, val_acc)
  51. plt.title('Training and validation accuracy')
  52. plt.legend(('Training accuracy','validation accuracy'))
  53. plt.figure()# 绘制损失曲线
  54. plt.plot(epochs, loss)
  55. plt.plot(epochs, val_loss)
  56. plt.legend(('Training loss','validation loss'))
  57. plt.title('Training and validation loss')
  58. plt.show()
  1. 运行classification.py文件,开始训练模型。在这里插入图片描述
  2. 训练结束后可以在根路径下得到最终模型model.h5,如下图所示。在这里插入图片描述 还可以得到精度曲线和损失曲线,如下图所示。在这里插入图片描述   分析曲线可以发现,存在着过拟合的现象,而且验证集的准确率比较低,下面将使用数据增强和dropout方式解决过拟合。
  3. 新建一个classification_DataEnhancement and Dropout.py文件,在classification.py文件的基础上通过采用数据增强和dropout方式来对过拟合问题进行解决,代码如下所示。
  1. import os
  2. import tensorflow as tf
  3. from tensorflow.keras.optimizers import RMSprop
  4. from tensorflow.keras.preprocessing.image import ImageDataGenerator
  5. import matplotlib.pyplot as plt
  6. base_dir ='E:/Remote Sensing/Data Set/cats_and_dogs'
  7. train_dir = os.path.join(base_dir,'train')
  8. validation_dir = os.path.join(base_dir,'validation')
  9. train_cats_dir = os.path.join(train_dir,'cats')
  10. train_dogs_dir = os.path.join(train_dir,'dogs')
  11. validation_cats_dir = os.path.join(validation_dir,'cats')
  12. validation_dogs_dir = os.path.join(validation_dir,'dogs')# 模型处添加了dropout随机失效,也就是说有时候可能不用到某些神经元,失效率为0.5
  13. model = tf.keras.models.Sequential([
  14. tf.keras.layers.Conv2D(32,(3,3), activation='relu', input_shape=(150,150,3)),
  15. tf.keras.layers.MaxPooling2D(2,2),
  16. tf.keras.layers.Conv2D(64,(3,3), activation='relu'),
  17. tf.keras.layers.MaxPooling2D(2,2),
  18. tf.keras.layers.Conv2D(128,(3,3), activation='relu'),
  19. tf.keras.layers.MaxPooling2D(2,2),
  20. tf.keras.layers.Conv2D(128,(3,3), activation='relu'),
  21. tf.keras.layers.MaxPooling2D(2,2),
  22. tf.keras.layers.Dropout(0.5),
  23. tf.keras.layers.Flatten(),
  24. tf.keras.layers.Dense(512, activation='relu'),
  25. tf.keras.layers.Dense(1, activation='sigmoid')])
  26. model.compile(loss='binary_crossentropy',
  27. optimizer=RMSprop(lr=1e-4),
  28. metrics=['acc'])# 这里的代码进行了更新,原来这里只进行归一化处理,现在要进行数据增强。
  29. train_datagen = ImageDataGenerator(
  30. rescale=1./255,
  31. rotation_range=40,
  32. width_shift_range=0.2,
  33. height_shift_range=0.2,
  34. shear_range=0.2,
  35. zoom_range=0.2,
  36. horizontal_flip=True,
  37. fill_mode='nearest')
  38. test_datagen = ImageDataGenerator(rescale=1./255)
  39. train_generator = train_datagen.flow_from_directory(
  40. train_dir,
  41. target_size=(150,150),
  42. batch_size=20,
  43. class_mode='binary')
  44. validation_generator = test_datagen.flow_from_directory(
  45. validation_dir,
  46. target_size=(150,150),
  47. batch_size=20,
  48. class_mode='binary')
  49. history = model.fit_generator(
  50. train_generator,
  51. steps_per_epoch=100,
  52. epochs=100,
  53. validation_data=validation_generator,
  54. validation_steps=50,
  55. verbose=2)# 保存训练的模型
  56. model.save('model.h5')# 得到精度和损失值
  57. acc = history.history['acc']
  58. val_acc = history.history['val_acc']
  59. loss = history.history['loss']
  60. val_loss = history.history['val_loss']
  61. epochs =range(len(acc))# 得到迭代次数# 绘制精度曲线
  62. plt.plot(epochs, acc)
  63. plt.plot(epochs, val_acc)
  64. plt.title('Training and validation accuracy')
  65. plt.legend(('Training accuracy','validation accuracy'))
  66. plt.figure()# 绘制损失曲线
  67. plt.plot(epochs, loss)
  68. plt.plot(epochs, val_loss)
  69. plt.legend(('Training loss','validation loss'))
  70. plt.title('Training and validation loss')
  71. plt.show()
  1. 运行classification_DataEnhancement and Dropout.py文件可以得到新的模型及精度和损失曲线如下图所示。在这里插入图片描述   分析曲线可以发现,过拟合情况得到了改善。
  2. 新建一个predict.py文件对需要测试的图片进行类别预测,代码如下所示。
  1. # 预测from tensorflow.keras.models import load_model
  2. import numpy as np
  3. from tensorflow.keras.preprocessing import image
  4. path ='E:/Remote Sensing/Classification-cats-and-dogs/dog.jpeg'
  5. model = load_model('model.h5')
  6. img = image.load_img(path, target_size=(150,150))
  7. x = image.img_to_array(img)/255.0# 在第0维添加维度变为1x150x150x3,和我们模型的输入数据一样
  8. x = np.expand_dims(x, axis=0)# np.vstack:按垂直方向(行顺序)堆叠数组构成一个新的数组,我们一次只有一个数据所以不这样也可以
  9. images = np.vstack([x])# batch_size批量大小,程序会分批次地预测测试数据,这样比每次预测一个样本会快
  10. classes = model.predict(images, batch_size=1)if classes[0]>0.5:print("It is a dog")else:print("It is a cat")
  1. 在网上下载一张狗的图片,如下图所示。在这里插入图片描述 运行predict.py文件,就可以得到分类结果,如下图所示。在这里插入图片描述 在网上下载一张猫的图片,如下图所示。在这里插入图片描述 运行predict.py文件,就可以得到分类结果,如下图所示。在这里插入图片描述
  2. 新建visual.py文件对每个卷积层的特征进行可视化,代码如下所示。
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from tensorflow.keras.preprocessing.image import img_to_array, load_img
  4. import tensorflow as tf
  5. from tensorflow.keras.models import load_model
  6. np.seterr(divide='ignore', invalid='ignore')
  7. model = load_model('model.h5')# 让我们定义一个新模型,该模型将图像作为输入,并输出先前模型中所有层的中间表示。
  8. successive_outputs =[layer.output for layer in model.layers[1:]]# 进行可视化模型搭建,设置输入和输出
  9. visualization_model = tf.keras.models.Model(inputs=model.input, outputs=successive_outputs)# 选取一张随机的图片
  10. img_path ='E:/Remote Sensing/Classification-cats-and-dogs/dog.jpeg'
  11. img = load_img(img_path, target_size=(150,150))# 以指定大小读取图片
  12. x = img_to_array(img)# 变成array
  13. x = x.reshape((1,)+ x.shape)# 变成 (1, 150, 150, 3)# 统一范围到01
  14. x /=255# 运行我们的模型,得到我们要画的图。
  15. successive_feature_maps = visualization_model.predict(x)# 选取每一层的名字
  16. layer_names =[layer.name for layer in model.layers]# 开始画图for layer_name, feature_map inzip(layer_names, successive_feature_maps):iflen(feature_map.shape)==4:# 只绘制卷积层,池化层,不画全连接层。
  17. n_features = feature_map.shape[-1]# 最后一维的大小,也就是通道数,也是我们提取的特征数# feature_map的形状为 (1, size, size, n_features)
  18. size = feature_map.shape[1]# 我们将在此矩阵中平铺图像
  19. display_grid = np.zeros((size, size * n_features))for i inrange(n_features):# 后期处理我们的特征,使其看起来更美观。
  20. x = feature_map[0,:,:, i]
  21. x -= x.mean()
  22. x /= x.std()
  23. x *=64
  24. x +=128
  25. x = np.clip(x,0,255).astype('uint8')# 我们把图片平铺到这个大矩阵中
  26. display_grid[:, i * size:(i +1)* size]= x
  27. # 绘制这个矩阵
  28. scale =20./ n_features
  29. plt.figure(figsize=(scale * n_features, scale))# 设置图片大小
  30. plt.title(layer_name)# 设置题目
  31. plt.grid(False)# 不绘制网格线# aspect='auto'自动控制轴的长宽比。 这方面对于图像特别相关,因为它可能会扭曲图像,即像素不会是正方形的。# cmap='viridis'设置图像的颜色变化
  32. plt.imshow(display_grid, aspect='auto', cmap='viridis')
  33. plt.show()
  1. 运行可视化代码后得到的结果如下图所示。在这里插入图片描述   分析可视化结果可以发现,越浅的层对应的特征图中包含的图像底层像素信息越多,轮廓越清晰,与原图更为相近;随着层数的增加,所得到的特征图中包含的有效特征越来越少,特征图变得越来越抽象,稀疏程度也更高。

  参考文章:https://blog.csdn.net/weixin_43398590/article/details/105173936
       https://blog.csdn.net/weixin_43398590/article/details/105174367?spm=1001.2014.3001.5502

标签: cnn 分类 图像分类

本文转载自: https://blog.csdn.net/HUAI_BI_TONG/article/details/124746643
版权归原作者 大彤小忆 所有, 如有侵权,请联系我们删除。

“使用卷积神经网络实现猫狗分类任务”的评论:

还没有评论