本次项目首先使用CNN卷积神经网络模型进行训练,最终训练效果不太理想,出现了过拟合的情况。准确率达到0.72,loss达到0.54。使用预训练的VGG模型后,在测试集上准确率达到0.91,取得了不错的改进效果。

数据集

本次项目使用The Asirra 数据集,Asirra(Animal Species Image Recognition for Restricting Access)是一套人机交互证明系统(Human Interactive Proof),它使用猫和狗的图片来验证网站访问者是真人还是机器人。
Asirra使用的猫狗图片来自于世界上最大的流浪动物救助网站petfinder.com,图片被数千个流浪动物救助者进行手动分类和标准。它也为微软研究院提供了超过300万张猫狗图片。
我们使用的数据集包含25000张已标注的猫狗图片,和12500张未标注的测试图片。

数据处理

由于测试数据集的图片没有标签,所以我们从训练集中划出一部分作为测试集。

import numpy as np
import pandas as pd
from keras.preprocessing.image import ImageDataGenerator, load_img
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import random
import os filenames= os.listdir("./train") categories=[] for filename in filenames:
#从文件名中分离标签,0代表猫,1代表狗
category=filename.split(".")[0]
if category=="dog":
categories.append(1)
else:
categories.append(0) df=pd.DataFrame({'filename':filenames,
'category':categories
})
df.shape #(25000,2)
df.head()

随机展示一张图片。

random_Img=random.choice(filenames)
image=load_img("./train/"+random_Img)
plt.imshow(image)


我们也可以发现数据集中的图片尺寸并不一致,有些图片中的猫狗太小不足以识别,或者只露了部分部位,这些都是属于质量不高的数据。

卷积神经网络

我们尝试使用卷积神经网络来进行模型训练

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization model1 = Sequential() model1.add(Conv2D(128, (3, 3), activation='relu', input_shape=(128,128,3)))
model1.add(BatchNormalization())
model1.add(MaxPooling2D(pool_size=(2, 2)))
model1.add(Dropout(0.25)) model1.add(Conv2D(64, (3, 3), activation='relu'))
model1.add(BatchNormalization())
model1.add(MaxPooling2D(pool_size=(2, 2)))
model1.add(Dropout(0.25)) model1.add(Conv2D(64, (3, 3), activation='relu'))
model1.add(BatchNormalization())
model1.add(MaxPooling2D(pool_size=(2, 2)))
model1.add(Dropout(0.25)) model1.add(Flatten())
model1.add(Dense(512, activation='relu'))
model1.add(BatchNormalization())
model1.add(Dropout(0.2))
model1.add(Dense(2, activation='softmax')) # 2 because we have cat and dog classes model1.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

使用sklearn的train_test_split把数据集划分为训练集和测试集,测试集的比例test_size设置为0.20,随机数种子random_state设置为任意整数,这样不管重复多少次划分结果都是一致的。该函数默认参数 shuffle为True,对数据集进行随机打散。

train_df,validate_df=train_test_split(df,test_size=.20,random_state=4)
train_df=train_df.reset_index(drop=True)
validate_df=validate_df.reset_index(drop=True) total_train=train_df.shape[0]
total_validate=validate_df.shape[0] #5000
batch_size=16

数据增强

为了避免过拟合,增加我们的训练数据集大小,通过对图片进行旋转、移位、缩放、亮度改变、色调改变、增加噪音等转换成一张与已有图片类似但却稍有不同的新图片。对于人眼来说这些图片很相似,但是对于一个未训练完成的机器学习模型来说却是不同的。卷积神经网络可以学习图片的细节特征,对于旋转、移位等具有不变性。通过数据增强可以强化我们训练出的模型的鲁棒性。
keras中提供了ImageDataGenerator类来进行图像数据增强,可以在训练过程中进行图像的随机变化,增加训练数据;还附带赠送了获取数据batch生成器对象的功能,省去了手工再去获取batch数据的部分。该类可以对图像进行多种变换操作,默认的初始化参数如下:

# keras/preprocessing/image.py
class ImageDataGenerator(image.ImageDataGenerator):
def __init__(self,
featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
zca_epsilon=1e-6,
rotation_range=0,
width_shift_range=0.,
height_shift_range=0.,
brightness_range=None,
shear_range=0.,
zoom_range=0.,
channel_shift_range=0.,
fill_mode='nearest',
cval=0.,
horizontal_flip=False,
vertical_flip=False,
rescale=None,
preprocessing_function=None,
data_format=None,
validation_split=0.0,
dtype=None):

在这里我们对训练数据进行旋转、标准化、剪切范围、缩放范围、水平翻转、宽度变换、高度变换。对测试集的图片就无需进行数据增强了,只需要按照训练集一样进行rescaling标准化。
ImageDataGenerator的flow_from_dataframe用于从pandas的DataFrame中载入图片数据,同时自动进行数据增强和生成批数据。我们之前定义的tran_df,一列为图片文件名,一列为图片对于的分类。传入flow_from_dataframe后,会通过我们定义的dataframe、文件路径读取图片,target_size设置目标图像尺寸,batch_size则是批大小,x_col和y_col为dataframe中的图片名和标签列名称。对于class_mode的设置,‘categorical’为one-hot编码。该方法shuffle参数默认为True,即也默认打散数据。

train_datagen=ImageDataGenerator(
rotation_range=30,
rescale=1./255,
shear_range=0.4,
zoom_range=0.4,
horizontal_flip=True,
width_shift_range=0.4,
height_shift_range=0.4
) train_generator=train_datagen.flow_from_dataframe( train_df,
"./train",
x_col='filename',
y_col='category',
target_size=(128,128),
class_mode='categorical',
batch_size=batch_size ) validate_datagen=ImageDataGenerator(
rescale=1./255
) validate_generator=validate_datagen.flow_from_dataframe(
validate_df,
"./train",
x_col='filename',
y_col='category',
target_size=(128,128),
class_mode='categorical',
batch_size=batch_size )

回调函数callback

回调函数是一个函数的合集,会在训练的阶段中所使用。你可以使用回调函数来查看训练模型的内在状态和统计。你可以传递一个列表的回调函数(作为 callbacks 关键字参数)到 Sequential 或 Model 类型的 .fit() 方法。在训练时,相应的回调函数的方法就会被在各自的阶段被调用。通过定义回调函数,我们可以检测训练过程并在符合条件时执行我们的回调函数。
EarlyStop用于监测定义的指标,当它不再提升时就停止训练。用于在训练中监测loss指标,防止过拟合。

EarlyStopping
keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=0, verbose=0, mode='auto', baseline=None, restore_best_weights=False)
当被监测的数量不再提升,则停止训练。 参数 monitor: 被监测的数据。
min_delta: 在被监测的数据中被认为是提升的最小变化, 例如,小于 min_delta 的绝对变化会被认为没有提升。
patience: 没有进步的训练轮数,在这之后训练就会被停止。
verbose: 详细信息模式。
mode: {auto, min, max} 其中之一。 在 min 模式中, 当被监测的数据停止下降,训练就会停止;在 max 模式中,当被监测的数据停止上升,训练就会停止;在 auto 模式中,方向会自动从被监测的数据的名字中判断出来。
baseline: 要监控的数量的基准值。 如果模型没有显示基准的改善,训练将停止。
restore_best_weights: 是否从具有监测数量的最佳值的时期恢复模型权重。 如果为 False,则使用在训练的最后一步获得的模型权重。

ReduceLROnPlateau用于评估当模型停止提升时降低学习率。

keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', min_delta=0.0001, cooldown=0, min_lr=0)
当标准评估停止提升时,降低学习速率。 当学习停止时,模型总是会受益于降低 2-10 倍的学习速率。 这个回调函数监测一个数据并且当这个数据在一定「有耐心」的训练轮之后还没有进步, 那么学习速率就会被降低。 例子 reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,
patience=5, min_lr=0.001)
model.fit(X_train, Y_train, callbacks=[reduce_lr])
参数 monitor: 被监测的数据。
factor: 学习速率被降低的因数。新的学习速率 = 学习速率 * 因数
patience: 没有进步的训练轮数,在这之后训练速率会被降低。
verbose: 整数。0:安静,1:更新信息。
mode: {auto, min, max} 其中之一。如果是 min 模式,学习速率会被降低如果被监测的数据已经停止下降; 在 max 模式,学习塑料会被降低如果被监测的数据已经停止上升; 在 auto 模式,方向会被从被监测的数据中自动推断出来。
min_delta: 对于测量新的最优化的阀值,只关注巨大的改变。
cooldown: 在学习速率被降低之后,重新恢复正常操作之前等待的训练轮数量。
min_lr: 学习速率的下边界。

在这里我们定义Early Stopping的patience为10,即val_loss十轮训练后没有下降则训练停止。定义ReduceLROnPlateau的监测参数monitor为'val_acc'即验证集的accuracy,patience为2,减小因子为0.5(学习率每次更次为上次的0.5),学习率下边界为0.00001(学习率降到0.00001后不再下降)。

from keras.callbacks import EarlyStopping, ReduceLROnPlateau

earlystop = EarlyStopping(patience=10)
learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc',
patience=2,
verbose=1,
factor=0.5,
min_lr=0.00001)
callbacks = [earlystop, learning_rate_reduction]

训练卷积神经网络模型

history1=model1.fit_generator(
train_generator,
steps_per_epoch=total_train//batch_size,
epochs=10,
verbose=1,
callbacks=callbacks,
validation_data=validate_generator,
validation_steps=total_validate//batch_size,
)

训练过程如下:

加载预训练VGG模型

TensorFlow为我们提供了预训练的VGG模型,我们可以很方便的调用它。VGG预训练模型在大规模图像数据集上训练完成后,在图像识别和分类任务上表现良好。我们可以使用预训练模型进行迁移学习(transfer learning),在类似的图片识别任务上取得良好的效果。

from tensorflow.keras.applications import VGG16
from keras.models import Model
from keras.layers import Dense,Dropout
from keras.backend import pool2d
from keras.layers.pooling import GlobalAveragePooling2D base_model = VGG16(input_shape = (128, 128, 3), # Shape of our images
include_top = False, # Leave out the last fully connected layer
weights = 'imagenet')

我们不需要训练VGG模型,可以以它为基础,添加更多的隐藏层。只有后面被添加的层才会被训练。我们在VGG模型的基础上添加了输出为512维的全连接层,一个平均池化层,一个rate为0.5的Dropout层,一个softmax全连接层。

base_model.trainable=False

model=base_model.output

model=Dense(512, activation='relu')(model)
model= GlobalAveragePooling2D()(model)
model=Dropout(rate=0.5)(model)
model=Dense(2, activation='softmax')(model)
model=Model(inputs=base_model.inputs, outputs=model) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.summary()

定义好后的模型结构如下:

Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 128, 128, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 128, 128, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 128, 128, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 64, 64, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 64, 64, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 64, 64, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 32, 32, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 32, 32, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 32, 32, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 32, 32, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 16, 16, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 16, 16, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 16, 16, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 16, 16, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 8, 8, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 8, 8, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 8, 8, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 8, 8, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 4, 4, 512) 0
_________________________________________________________________
dense_2 (Dense) (None, 4, 4, 512) 262656
_________________________________________________________________
global_average_pooling2d (Gl (None, 512) 0
_________________________________________________________________
dropout_4 (Dropout) (None, 512) 0
_________________________________________________________________
dense_3 (Dense) (None, 2) 1026
=================================================================
Total params: 14,978,370
Trainable params: 263,682
Non-trainable params: 14,714,688
_________________________________________________________________

VGG模型训练

与之前CNN网络模型训练一样,我们进行数据集的载入和处理,打散之后生成批训练数据。

from sklearn.model_selection import train_test_split
from tqdm import tqdm
import cv2
from sklearn.utils import shuffle df["category"] = df["category"].replace({0: 'cat', 1: 'dog'}) #进行数据集划分交叉验证
train_df, validate_df = train_test_split(df, test_size=0.20, random_state=42)
train_df = train_df.reset_index(drop=True)
validate_df = validate_df.reset_index(drop=True) total_train = train_df.shape[0]
total_validate = validate_df.shape[0]
batch_size=4 #生成训练数据
train_datagen=ImageDataGenerator(
rescale=1/255
) train_generator=train_datagen.flow_from_dataframe(train_df,
'./train',
x_col='filename',
y_col='category',
weight_col=None,
target_size=(128, 128),
class_mode='categorical',
batch_size=batch_size,
)
#生成测试数据
validation_datagen = ImageDataGenerator(rescale=1./255)
validation_generator = validation_datagen.flow_from_dataframe(
validate_df,
"./train",
x_col='filename',
y_col='category',
target_size=(128,128),
class_mode='categorical',
batch_size=batch_size
)
#定义回调函数
earlystop = EarlyStopping(patience=10)
learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc',
patience=2,
verbose=1,
factor=0.5,
min_lr=0.00001)
callbacks = [earlystop, learning_rate_reduction]
#进行模型训练
history = model.fit_generator(
train_generator,
epochs=12,
validation_data=validation_generator,
validation_steps=total_validate//batch_size,
steps_per_epoch=total_train//batch_size,
callbacks=callbacks,
verbose=1
)

训练的过程如下,最终在验证集上accuracy达到0.91。

Epoch 1/12
5000/5000 [==============================] - 99s 20ms/step - loss: 0.3466 - accuracy: 0.8461 - val_loss: 0.2575 - val_accuracy: 0.8920
Epoch 2/12
5000/5000 [==============================] - 90s 18ms/step - loss: 0.2886 - accuracy: 0.8752 - val_loss: 0.2365 - val_accuracy: 0.8992
Epoch 3/12
5000/5000 [==============================] - 89s 18ms/step - loss: 0.2625 - accuracy: 0.8877 - val_loss: 0.2296 - val_accuracy: 0.9016
Epoch 4/12
5000/5000 [==============================] - 90s 18ms/step - loss: 0.2415 - accuracy: 0.8970 - val_loss: 0.2215 - val_accuracy: 0.9076
Epoch 5/12
5000/5000 [==============================] - 90s 18ms/step - loss: 0.2358 - accuracy: 0.9004 - val_loss: 0.2331 - val_accuracy: 0.8982
Epoch 6/12
5000/5000 [==============================] - 90s 18ms/step - loss: 0.2195 - accuracy: 0.9074 - val_loss: 0.2387 - val_accuracy: 0.9002
Epoch 7/12
5000/5000 [==============================] - 89s 18ms/step - loss: 0.2106 - accuracy: 0.9096 - val_loss: 0.2237 - val_accuracy: 0.9094
Epoch 8/12
5000/5000 [==============================] - 90s 18ms/step - loss: 0.2028 - accuracy: 0.9155 - val_loss: 0.2173 - val_accuracy: 0.9126
Epoch 9/12
5000/5000 [==============================] - 95s 19ms/step - loss: 0.1908 - accuracy: 0.9204 - val_loss: 0.2285 - val_accuracy: 0.9076
Epoch 10/12
5000/5000 [==============================] - 94s 19ms/step - loss: 0.1821 - accuracy: 0.9247 - val_loss: 0.2242 - val_accuracy: 0.9112
Epoch 11/12
5000/5000 [==============================] - 94s 19ms/step - loss: 0.1740 - accuracy: 0.9278 - val_loss: 0.2364 - val_accuracy: 0.9044
Epoch 12/12
5000/5000 [==============================] - 94s 19ms/step - loss: 0.1644 - accuracy: 0.9322 - val_loss: 0.2335 - val_accuracy: 0.9106

猫狗识别-CNN与VGG实现的更多相关文章

  1. 猫狗识别——PyTorch

    猫狗识别 数据集下载: 网盘链接:https://pan.baidu.com/s/1SlNAPf3NbgPyf93XluM7Fg 提取密码:hpn4 1. 要导入的包 import os import ...

  2. pytorch实现kaggle猫狗识别

    参考:https://blog.csdn.net/weixin_37813036/article/details/90718310 kaggle是一个为开发商和数据科学家提供举办机器学习竞赛.托管数据 ...

  3. 深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)

    1.cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR) 参数说明:image表示输入图片,image_size表示变 ...

  4. keras猫狗图像识别

    这里,我们介绍的是一个猫狗图像识别的一个任务.数据可以从kaggle网站上下载.其中包含了25000张毛和狗的图像(每个类别各12500张).在小样本中进行尝试 我们下面先尝试在一个小数据上进行训练, ...

  5. 人工智能——CNN卷积神经网络项目之猫狗分类

    首先先导入所需要的库 import sys from matplotlib import pyplot from tensorflow.keras.utils import to_categorica ...

  6. 1.keras实现-->自己训练卷积模型实现猫狗二分类(CNN)

    原数据集:包含 25000张猫狗图像,两个类别各有12500 新数据集:猫.狗 (照片大小不一样) 训练集:各1000个样本 验证集:各500个样本 测试集:各500个样本 1= 狗,0= 猫 # 将 ...

  7. 使用pytorch完成kaggle猫狗图像识别

    kaggle是一个为开发商和数据科学家提供举办机器学习竞赛.托管数据库.编写和分享代码的平台,在这上面有非常多的好项目.好资源可供机器学习.深度学习爱好者学习之用.碰巧最近入门了一门非常的深度学习框架 ...

  8. Kaggle系列1:手把手教你用tensorflow建立卷积神经网络实现猫狗图像分类

    去年研一的时候想做kaggle上的一道题目:猫狗分类,但是苦于对卷积神经网络一直没有很好的认识,现在把这篇文章的内容补上去.(部分代码参考网上的,我改变了卷积神经网络的网络结构,其实主要部分我加了一层 ...

  9. paddlepaddle实现猫狗分类

    目录 1.预备工作 1.1 数据集准备 1.2 数据预处理 2.训练 2.1 模型 2.2 定义训练 2.3 训练 3.预测 4.参考文献 声明:这是我的个人学习笔记,大佬可以点评,指导,不喜勿喷.实 ...

随机推荐

  1. Apache DolphinScheduler 使用文档(5/8):使用与测试

    本文章经授权转载,原文链接: https://blog.csdn.net/MiaoSO/article/details/104770720 目录 5. 使用与测试 5.1 安全中心(Security) ...

  2. 走进Redis:哨兵集群

    为什么需要哨兵 在 Redis 的主从库模式中,如果从库发生了故障,用户的操作是可以继续进行的,因为写操作是只在主库中进行的.那么,如果主库发生了故障,用户的操作将会收到影响.这时候可能会需要选择一个 ...

  3. Luogu3802 小魔女帕琪 (排列组合)

    注意除数为0情况 #include <iostream> #include <cstdio> #include <cstring> #include <alg ...

  4. 微服务性能分析|Pyroscope 集合 Spring Cloud Pig 的实践分享

    随着微服务体系在生产环境落地,也会伴随着一些问题出现,比如流量过大造成某个微服务应用程序的性能瓶颈.CPU利用率高.或内存泄漏等问题.要找到问题的根本原因,我们通常都会通过日志.进程再结合代码去判断根 ...

  5. UE蓝图---实现场景物体Transform状态重置效果

    在工业领域应用中,通常会遇到操作场景模型变换的操作,经过了移动.旋转.缩放后,要求可一键重置还原最初的Transform状态. 思路:1.在模型阶段设置每个模型Tag值为Oper,表明是可被操作的对象 ...

  6. SecureCRT 和 Xshell 连接ENSP 教程

    前言:很多人问我说想尝试使用 CRT和Xshell连接 ENSP的某台设备,以模拟现网中的工作状态,所以出了这篇随笔. ENSP版本: Xshell 连接教程 Xshell 7 评估版(其他版本没测试 ...

  7. 垃圾收集器 参阅<<深入理解JAVA虚拟机>>

    一.新生代 1.Serial收集器 新生代单线程复制算法GC(暂停工作线程)---------- 支持组合老年代Serial odl和CMS 2.ParNew Serial多线程版本 支持组合cms| ...

  8. 第三十三篇:关于ES6,JSON和Webpack

    好家伙 1.什么是ES6? ECMAScript是javascript标准 ES6就是ECMAScript的第6个版本 (大概是一个语法标准规范) 2.什么是JSON? JSON 是什么,在数据交换中 ...

  9. helm安装csi-driver-nfs-v4.1.0

    Application version v4.1.0 Chart version v4.1.0 获取chart包 helm repo add csi-driver-nfs https://raw.gi ...

  10. 手写tomcat——编写一个提供servlet能力的 http服务器

    点击查看代码 package com.grady.diytomcat; import com.grady.diytomcat.handler.RequestHandler; import org.do ...