猫狗识别-CNN与VGG实现
本次项目首先使用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实现的更多相关文章
- 猫狗识别——PyTorch
猫狗识别 数据集下载: 网盘链接:https://pan.baidu.com/s/1SlNAPf3NbgPyf93XluM7Fg 提取密码:hpn4 1. 要导入的包 import os import ...
- pytorch实现kaggle猫狗识别
参考:https://blog.csdn.net/weixin_37813036/article/details/90718310 kaggle是一个为开发商和数据科学家提供举办机器学习竞赛.托管数据 ...
- 深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 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表示变 ...
- keras猫狗图像识别
这里,我们介绍的是一个猫狗图像识别的一个任务.数据可以从kaggle网站上下载.其中包含了25000张毛和狗的图像(每个类别各12500张).在小样本中进行尝试 我们下面先尝试在一个小数据上进行训练, ...
- 人工智能——CNN卷积神经网络项目之猫狗分类
首先先导入所需要的库 import sys from matplotlib import pyplot from tensorflow.keras.utils import to_categorica ...
- 1.keras实现-->自己训练卷积模型实现猫狗二分类(CNN)
原数据集:包含 25000张猫狗图像,两个类别各有12500 新数据集:猫.狗 (照片大小不一样) 训练集:各1000个样本 验证集:各500个样本 测试集:各500个样本 1= 狗,0= 猫 # 将 ...
- 使用pytorch完成kaggle猫狗图像识别
kaggle是一个为开发商和数据科学家提供举办机器学习竞赛.托管数据库.编写和分享代码的平台,在这上面有非常多的好项目.好资源可供机器学习.深度学习爱好者学习之用.碰巧最近入门了一门非常的深度学习框架 ...
- Kaggle系列1:手把手教你用tensorflow建立卷积神经网络实现猫狗图像分类
去年研一的时候想做kaggle上的一道题目:猫狗分类,但是苦于对卷积神经网络一直没有很好的认识,现在把这篇文章的内容补上去.(部分代码参考网上的,我改变了卷积神经网络的网络结构,其实主要部分我加了一层 ...
- paddlepaddle实现猫狗分类
目录 1.预备工作 1.1 数据集准备 1.2 数据预处理 2.训练 2.1 模型 2.2 定义训练 2.3 训练 3.预测 4.参考文献 声明:这是我的个人学习笔记,大佬可以点评,指导,不喜勿喷.实 ...
随机推荐
- 大数据开发,Hadoop Spark太重?你试试esProc SPL
摘要:由于目标和现实的错位,对很多用户来讲,Hadoop成了一个在技术.应用和成本上都很沉重的产品. 本文分享自华为云社区<Hadoop Spark太重,esProc SPL很轻>,作者: ...
- LuoguP1456 Monkey King (左偏树)
struct LeftTree{ int l,r,val,dis; }t[N]; int fa[N]; inline int Find(int x){ return x == fa[x] ? x : ...
- HDU4348 To the moon (主席树)
标记永久化,除非想\(MLE\) 忽然感到主席树不过是函数式的树套树 #include <iostream> #include <cstdio> #include <cs ...
- MySQL 连接超时:报错SQLSTATE[HY000] [2002] Connection timed out
在网上找了一堆,结果全部是错的 后来,我明白了其实是设置问题. 当你的代码部署到服务器里的时候,你的mysql 的host 值 应该为 127.0.0.1 而不是 你的服务器ip 不然就会报错. 其实 ...
- 微服务性能分析|Pyroscope 集合 Spring Cloud Pig 的实践分享
随着微服务体系在生产环境落地,也会伴随着一些问题出现,比如流量过大造成某个微服务应用程序的性能瓶颈.CPU利用率高.或内存泄漏等问题.要找到问题的根本原因,我们通常都会通过日志.进程再结合代码去判断根 ...
- Python逆向爬虫之pyquery,非常详细
系列目录 Python逆向爬虫之pyquery pyquery是一个类似jquery的python库,它实现能够在xml文档中进行jQuery查询,pyquery使用lxml解析器进行快速在xml和h ...
- RabbitMQ 入门系列:3、基础含义:持久化、排它性、自动删除、强制性、路由键。
系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...
- [CF1537E] Erase and Extend (字符串)
题面 给一个长度为 n \tt n n 的字符串,你可以进行无限次以下两种操作之一: 删去末尾的字符(此时要保证删去后字符串非空). 把当前整个字符串复制一份,接到自己的后面. 输出最终通过操作能达到 ...
- MixCSE:困难样本在句子表示中的使用
Unsupervised Sentence Representation via Contrastive Learning with Mixing Negatives 论文地址:https://www ...
- 一次较波折的MySQL调优
春节长假某日,阳光明媚,春暖花开,恰逢冬奥会开幕,想着一定是一个黄道吉日,必能顺风顺水.没想到却遇到一个有点小波折 的客户报障. 01故障起因 故障起因是客户前一天从自建MySQL迁移到云上RDS,在 ...