这个项目使用卷积神经网络,《Python深度学习》中使用了两个方法实现。一个是自己搭建卷积网络,另一个是直接使用VGG16。其中直接使用VGG16又可以分为抽取特征和微调模型两种方法。

1.数据集介绍:

本项目使用的数据集需要从http://www.kaggle.com/c/dog-vs-cats/data下载,一共包含25000张猫狗图像,每个类别有12500张。

2.数据准备

创建一个新的数据集,猫狗各含1000个测试集,500个验证集,500个测试集。
创建一个新的文件夹dogs_and_cats_small,在该文件夹下,创建‘train’,‘validation’,‘test’,在这三个子文件下,再分别创建‘dogs’,‘cats’,然后将对应数据放到对应文件夹下。

import os, shutiloriginal_dataset_dir = './dogs-vs-cats' #原数据位置base_dir = './dogs_and_cats_small' #选取的数据的新位置
os.mkdir(base_dir) #创建新位置文件夹#在新文件夹中依次新增‘train’,‘validation’,‘test’文件夹
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’文件夹中新增‘dogs’,‘cats’文件夹
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’文件夹中新增‘dogs’,‘cats’文件夹
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’文件夹新增‘dogs’,‘cats’文件夹
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) #复制文件#将原数据中1000-1500张猫的图片复制到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)#将原数据中1500-2000张猫的图片复制到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)#将原数据中1000-1500张狗的图片复制到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)#将原数据中1500-2000张狗的图片复制到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)

3.搭建卷积神经网络实现

网络结构:

代码详解:

import os
from keras import layers
from keras import models
from keras import optimizers
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGeneratorbase_dir = './dogs_and_cats_small' #数据集目录
train_dir = os.path.join(base_dir, 'train') #训练集目录
validation_dir = os.path.join(base_dir, 'validation') #验证集目录
test_dir = os.path.join(base_dir, 'test') #测试集目录#图片的预处理,rescale参数表示将图片乘1/255缩放,其余参数都是用于数据增强
#rotation_range表示图像随机旋转的角度范围
#width_shift,height_shift表示图像在水平或者垂直方向上平移的范围
#shear_range表示随机错切变换的角度范围
#zoom_range为图像随机缩放的范围
#horizontal_flip将一半的图像水平翻转
#fill_mode用于填充新创建像素的方法
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)
test_datagen = ImageDataGenerator(rescale=1./255) #将测试集乘乘1/255缩放#读取图像,将所有图像大小调整为150*150,使用了二元交叉熵,因此class_mode设为‘binary’
train_generator = train_datagen.flow_from_directory(train_dir, target_size=(150,150), batch_size=32, class_mode='binary')
validation_generator = test_datagen.flow_from_directory(validation_dir, target_size=(150, 150), batch_size=32,class_mode='binary')#搭建网络
model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), activation='relu', input_shape=(150,150,3)))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Flatten()) #添加flatten层,将3D张量展开为向量
model.add(layers.Dropout(0.5)) #添加Dropout层,将50%的参数改成0,防止过拟合
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
#编译网络
model.compile(loss='binary_crossentropy', optimizer = optimizers.RMSprop(lr = 1e-4), metrics=['acc'])
#训练模型
history = model.fit_generator(train_generator, steps_per_epoch = 100, epochs = 100, validation_data=validation_generator,validation_steps=50)
model.save('cats_and_dogs_small_2.h5')#保存模型#绘制loss和准确度的图
acc = history.history['acc'] #训练精度
val_acc = history.history['val_acc'] #验证精度
loss = history.history['loss'] #训练损失
val_loss = history.history['val_loss'] #验证损失epochs = range(1, len(acc) + 1) #横坐标的长度
#绘制精度图
plt.plot(epochs, acc, 'bo', label = 'Training acc')
plt.plot(epochs, val_acc, 'b', label = 'Validation')
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()

运行结果

4.VGG16

网络结构

4.1抽取特征(不可数据增强)

在数据集上运行卷积基,将输出保存为numpy数组,在搭建新的全连接分类器,将numpy的输出作为输入进行分类。
代码详解:

import os
import numpy as np
from keras.applications import VGG16
from keras.preprocessing.image import ImageDataGenerator
from keras import models
from keras import layers
from keras import optimizers
import matplotlib.pyplot as pltconv_base = VGG16(weights = 'imagenet', include_top = False, input_shape = (150, 150, 3))base_dir = './dogs_and_cats_small'
train_dir = os.path.join(base_dir, 'train') #训练集目录
validation_dir = os.path.join(base_dir, 'validation') #验证集目录
test_dir = os.path.join(base_dir, 'test') #测试集目录datagen = ImageDataGenerator(rescale=1./255) #图片乘1/255进行缩放
batch_size = 20 #每次样本个数#抽取特征
def extract_features(directory, sample_count):features = np.zeros(shape=(sample_count, 4, 4, 512)) #特征(格式为VGG16训练后的输出格式)labels = np.zeros(shape=(sample_count)) #图片标签#载入数据集,将图片大小裁剪为150*150generator = datagen.flow_from_directory(directory, target_size=(150, 150), batch_size=batch_size, class_mode='binary')#每20个为一组,抽取特征并保存i = 0for inputs_batch, labels_batch in generator:features_batch = conv_base.predict(inputs_batch) #将数据集放入VGG16进行训练features[i * batch_size : (i+1) * batch_size] = features_batchlabels[i*batch_size : (i+1) * batch_size] = labels_batchi += 1if i * batch_size >= sample_count:breakreturn features, labelstrain_features, train_labels = extract_features(train_dir, 2000) #抽取训练集特征
validation_features, validation_labels = extract_features(validation_dir, 1000) #抽取验证集特征
test_features, test_labels = extract_features(test_dir, 1000) #抽取测试集特征#将得到的特征展开,即对每条数据而言,得到的特征为(4,4,512)的张量,现展开为一维向量
train_features = np.reshape(train_features, (2000, 4*4*512))
validation_features = np.reshape(validation_features, (1000, 4*4*512))
test_features = np.reshape(test_features, (1000, 4*4*512))#搭建分类网络
model = models.Sequential()
model.add(layers.Dense(256, activation='relu', input_dim=4*4*512)) #添加全连接层
model.add(layers.Dropout(0.5)) #使用Dropout
model.add(layers.Dense(1, activation='sigmoid')) #分类层
#网咯编译
model.compile(optimizer = optimizers.RMSprop(lr=2e-5), loss = 'binary_crossentropy', metrics=['acc'])
history = model.fit(train_features, train_labels, epochs = 30, batch_size = 20, validation_data=(validation_features, validation_labels)) #网络训练#绘制损失函数和模型准确度
#分别返回测试精度,验证精度,训练损失,验证损失
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']epochs = range(1, len(acc) + 1)#迭代次数#绘制训练精度和验证精度的图,bo表示蓝色圆点表示,b为蓝色曲线
plt.plot(epochs, acc, 'bo', label = 'Training acc')
plt.plot(epochs, val_acc, 'b', label = 'Validation')
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()

运行结果:


4.2抽取特征(可数据增强)

在顶部添加Dense层扩展已有模型,在数据集上端到端地运行整个模型。
代码详解:

from keras.applications import VGG16
from keras.preprocessing.image import ImageDataGenerator
from keras import models
from keras import layers
from keras import optimizers
import os
import numpy as np
import matplotlib.pyplot as pltbase_dir = './dogs_and_cats_small'
train_dir = os.path.join(base_dir, 'train') #训练集目录
validation_dir = os.path.join(base_dir, 'validation') #验证集目录
test_dir = os.path.join(base_dir, 'test') #测试集目录#对训练集使用数据增强,并且将图片*1/255进行缩放
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,fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale=1./255)
#载入数据集,并裁剪为150*150
train_generator = train_datagen.flow_from_directory(train_dir,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')#weights指定模型初始化的权重检查点;include_top指定模型是否包含密集连接分类器
conv_base = VGG16(weights = 'imagenet', include_top = False, input_shape = (150, 150, 3)) #调用VGG16模型#搭建网络
model = models.Sequential()
model.add(conv_base) #直接将VGG16搭建到目标网络中
model.add(layers.Flatten()) #将VGG16输出张量展开
#在先前的项目中介绍过,对于输入为向量,输出为数值的问题,使用激活函数为relu的全连接层,效果较好
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid')) #最后一层为分类层,此为二分类问题,激活函数设为sigmoid
#编译网络
model.compile(loss = 'binary_crossentropy', optimizer=optimizers.RMSprop(lr=2e-5),metrics=['acc'])
history = model.fit_generator(train_generator, steps_per_epoch=100, epochs = 30,validation_data=validation_generator, validation_steps=50) #训练网络#绘制损失函数和模型准确度
#分别返回测试精度,验证精度,训练损失,验证损失
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']epochs = range(1, len(acc) + 1)#迭代次数#绘制训练精度和验证精度的图,bo表示蓝色圆点表示,b为蓝色曲线
plt.plot(epochs, acc, 'bo', label = 'Training acc')
plt.plot(epochs, val_acc, 'b', label = 'Validation')
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()

运行结果“:


4.3微调模型

将VGG16的顶部几层“解冻”,并将这解冻的几层和新增加的部分联合训练。
微调模型的步骤为:(1)在VGG16上添加自定义网络;(2)冻结基网络;(3)训练所添加部分;(4)解冻基网络的一些层;(5)联合训练解冻的这些层和添加的部分
代码详解:

import os
import numpy as np
from keras.applications import VGG16
from keras.preprocessing.image import ImageDataGenerator
from keras import models
from keras import layers
from keras import optimizers
import matplotlib.pyplot as pltbase_dir = './dogs_and_cats_small'
train_dir = os.path.join(base_dir, 'train') #训练集目录
validation_dir = os.path.join(base_dir, 'validation') #验证集目录
test_dir = os.path.join(base_dir, 'test') #测试集目录#对训练集使用数据增强,并且将图片*1/255进行缩放
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,fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale=1./255)
#载入数据集,并裁剪为150*150
train_generator = train_datagen.flow_from_directory(train_dir,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')conv_base = VGG16(weights = 'imagenet', include_top = False, input_shape = (150, 150, 3))
conv_base.trainable = Trueset_trainable = False
for layer in conv_base.layers:if layer.name == ' block5_conv1':set_trainable = Falseif set_trainable:layer.trainable = Trueelse:layer.trainable = False#搭建网络
model = models.Sequential()
model.add(conv_base) #直接将VGG16搭建到目标网络中
model.add(layers.Flatten()) #将VGG16输出张量展开
#在先前的项目中介绍过,对于输入为向量,输出为数值的问题,使用激活函数为relu的全连接层,效果较好
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid')) #最后一层为分类层,此为二分类问题,激活函数设为sigmoid
model.compile(loss ='binary_crossentropy', optimizer = optimizers.RMSprop(lr = 1e-5), metrics=['acc'])history = model.fit_generator(train_generator,steps_per_epoch=100,epochs = 100,validation_data=validation_generator,validation_steps=50)#绘制损失函数和模型准确度
#分别返回测试精度,验证精度,训练损失,验证损失
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']epochs = range(1, len(acc) + 1)#迭代次数#绘制训练精度和验证精度的图,bo表示蓝色圆点表示,b为蓝色曲线
plt.plot(epochs, acc, 'bo', label = 'Training acc')
plt.plot(epochs, val_acc, 'b', label = 'Validation')
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()

训练结果:

Python深度学习(4):猫狗分类相关推荐

  1. PyTorch深度学习实战 | 猫狗分类

    本文内容使用TensorFlow和Keras建立一个猫狗图片分类器. 图1 猫狗图片 01.安装TensorFlow和Keras库 TensorFlow是一个采用数据流图(data flow grap ...

  2. 深度学习实现猫狗分类

    本文使用vgg网络实现对猫狗分类. 可以当做图像分类的一个baseline. 一.前期工作 数据:直接到kaggle上下载相应的数据集即可. 1.导入模块 # 数据import torchfrom t ...

  3. 基于tensorflow深度学习的猫狗分类识别

  4. 【深度学习】猫狗识别TensorFlow2实验报告

    实验二:猫狗识别 一.实验目的 利用深度学习实现猫狗动物识别,采用Kaggle提供的公开数据集,训练深度学习模型,对测试集猫狗中的图片准确分类.通过该实验掌握深度学习中基本的CV处理过程. 二.实验原 ...

  5. Tensorflow 学习之猫狗分类案例

    Tensorflow 学习之猫狗分类案例 本人一直在Cousera上学习Ng Andrew老师的Tensorflow课程,在本次猫狗分类案例当中,我对课程做了相应的记录,呈现在此,一方面加深学习的印象 ...

  6. 基于MATLAB的Alexnet迁移学习进行猫狗分类(数据集:Kaggle)

    基本介绍 软件:Matlab R2018b 数据集:Kaggle猫狗数据集 网络:AlexNet 前期准备 数据集 Kaggle猫狗数据集猫与狗用于训练的图片(train)分别12500张,每张图片的 ...

  7. 华为云深度学习kaggle猫狗识别

    使用华为云深度学习服务完成kaggle猫狗识别竞赛 参考: kaggle猫狗竞赛kernel第一名的代码 Tensorflow官网代码 华为云DLS服务github代码 1. 环境配置与数据集处理 首 ...

  8. Python深度学习婴儿啼哭声分类识别,测试集准确率67.5%

    随着AI技术的发展,人工智能已在各行业中不断被应用.         正常新生儿一天至少哭3小时,但不同的哭声代表不同涵义,一般家长可能听不出来.         对婴儿来说,哭声是一种通讯的方式,一 ...

  9. python 动物分类_《python深度学习》笔记---5.3-1、猫狗分类(使用预训练网络)

    <python深度学习>笔记---5.3-1.猫狗分类(使用预训练网络) 一.总结 一句话总结: [小型图像数据集]:想要将深度学习应用于小型图像数据集,一种常用且非常高效的方法是使用预训 ...

最新文章

  1. 3大主流前端框架对比
  2. 计算机学机械制图吗,机械制图与计算机绘图(少学时·任务驱动模式)
  3. 怎么在python下载网站内容-分析某网站,并利用python自动登陆该网站,下载网站内容...
  4. eja变送器故障代码al01_EJA系列差压变送器的使用及故障分析
  5. java开发架构设计_跪了!阿里技术官出品:Java架构设计之完美,看完秒进大厂。...
  6. Qt中的测试 枚举与 QFlags详解
  7. app store 关键词
  8. 程序员成长之路--软件架构
  9. [渝粤教育] 西南科技大学 单片机原理与应用 在线考试复习资料
  10. 可以直接复制的emoji符号(表情)
  11. java实现ftl文件转图片
  12. 自己制作深度学习数据集教程
  13. matlab 变限积分计算,Matlab变限积分计算【方法教程】
  14. TCP协议与UDP协议详解
  15. MySQL-学习数据库必备的基础知识
  16. JS中常见的 “Uncaught TypeError: XXXX is not a function” 错误解析
  17. IPhone弹出基于Phonegap的工程的Admob广告
  18. TP5接入快递查询api
  19. 404丨天朝BAT者……牛么?
  20. css背景图片重复相关知识

热门文章

  1. TI公司TMS封装与引脚对应关系
  2. 对残差网络resnet shortcut的解释
  3. 【转】Eclipse启动之后卡顿,CPU占用率接近100%
  4. 41.Android之图片放大缩小学习
  5. 使用nginx 同一端口根据不同域名转发到不同端口
  6. 各种电平标准的讨论(TTL,ECL,PECL,LVDS、CMOS、CML.......)
  7. 什么是远程桌面?远程桌面软件是如何进行连接工作的?
  8. fuse文件系统调试环境
  9. 电磁炉各主要元件名词,符号及功能解析
  10. git 安装windows错误处理