基于Keras的CNN模型做猫狗分类

选择了猫狗分类这个不是很困难的例子来做CNN的demo,数据可从kaggle下载:
kaggle Dogs vs Cats

猫狗数据各有12500张训练数据即25000张,每张图片前三个字母为cat或者dog,可以此作为分类。测试共有12500张,测试数据没有进行分类。

先对数据进行预处理操作:

import os
import shutil

file_names = os.listdir('./train/')
train_cats = filter(lambda x:x[:3]=='cat',file_names)
train_dogs = filter(lambda x:x[:3]=='dog',file_names)
def createDir(path):
    if not os.path.exists(path):
        try:
            os.makedirs(path)
        except:
            print("创建文件夹失败")
            exit(1)
createDir('./train_data')
createDir('./train_data/cats')
createDir('./train_data/dogs')
cats = list(train_cats)
dogs = list(train_dogs)
for cat in cats[:5000]:
    shutil.move('./train/'+cat,'./train_data/cats/')
print(' 猫猫操作成功!')
for dog in dogs[:5000]:
    shutil.move('./train/'+dog,'./train_data/dogs/')
print(' 狗狗操作成功!')  

这时候拥有了分好类的两组图,各5000张存到了对应的文件夹里。

进行训练

from keras.preprocessing.image import ImageDataGenerator
train_pic_gen = ImageDataGenerator(rescale=1./255,
                                   fill_mode='nearest',
                                   horizontal_flip=True,
                                   rotation_range=20,
                                   width_shift_range=0.2,
                                   height_shift_range=0.5,
                                   shear_range=0.5,
                                   zoom_range=0.2)
test_pic_gen = ImageDataGenerator(rescale=1./255)

train_flow = train_pic_gen.flow_from_directory(train_dir,target_size=(128,128),batch_size = 32,class_mode ='binary' )
test_flow = test_pic_gen.flow_from_directory(test_dir,(128,128),batch_size=32,class_mode='binary')
print(train_flow.class_indices)

建立循环神经网络,为常规的CNN模型,并将模型保存下来

from keras.models import Sequential
from keras.layers import Conv2D,Dense,MaxPooling2D,Flatten,Dropout,BatchNormalization
model = Sequential()
model.add(Conv2D(filters=32,kernel_size=(3,3),input_shape=(128,128,3),activation='relu'))
model.add(MaxPooling2D(2,2))
model.add(Conv2D(filters=164,kernel_size=(3,3),activation='relu'))
model.add(MaxPooling2D(2,2))
model.add(Flatten())
model.add(Dense(100,activation='relu'))
model.add(Dense(1,activation='sigmoid'))
model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['accuracy'])
his = model.fit_generator(train_flow,steps_per_epoch=100,epochs=20,validation_data=test_flow,validation_steps=100)
model.save('./model_1.h5')

训练结果:

import matplotlib.pyplot as plt
plt.plot(his.history['acc'])
plt.plot(his.history['val_acc'])
plt.title('model_accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
plt.plot(his.history['loss'])
plt.plot(his.history['val_loss'])
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
#plt.show()

模型准确率
可以看出模型在训练集和测试集上的预测准确率达到了70%,但是我还是希望他能更准确一点,下面开始调参,各种参数调一调试一试吧。

将图片大小调为64*64后:
在这里插入图片描述
加入新的一层卷积层,并调大了训练的步长:
在这里插入图片描述

最后用上面这个模型再fit一次整个数据集,进行五十步,得到下面结果:
在这里插入图片描述
利用这个模型进行预测。测试图为这只可爱猫猫:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import cv2

这里有两种方式读图,都是读为np.array格式,但是细节上有所区别。这里用cv2打印mlt读的图就能看到区别

pre_x = cv2.imread('./cat.jpg')
pre_x1 = mpimg.imread('./cat.jpg')
cv2.imshow('show',pre_x1)
cv2.waitKey()
plt.imshow(pre_x)

在这里插入图片描述
cv2中的色彩排列是(b,g,r),而matplotlib库中的排列方式是(r,g,b),具体可以参考:
Python中cv2库和matplotlib库色彩空间排布不一致

所以在数据处理时,如果使用cv2读的图则需要将色彩排布空间修改一下,下面是处理部分:

pre_x = cv2.resize(pre_x,(128,128))#resize成训练时的大小
pre_x = cv2.cvtColor(pre_x_fi, cv2.COLOR_BGR2RGB)#修改色彩排布
pre_x = pre_x/255
pre_x = np.expand_dims(pre_x,axis=0)#手动添加一维,让网络能读取,原先的shape是(128,128,3),变成(1,128,128,3)

预测:

model_3 = load_model('./model_3.h5')
pre_y = model_3.predict(pre_x_fi)
print(pre_y)

结果为:

[[0.38590088]]

可用如下的语句查看原先的分类:

print(train_flow.class_indices)
{'cats': 0, 'dogs': 1}

结果值<0.5,所以为猫,预测成功。

目前只学了CNN的一点知识,这个demo完成度还可以,后面会学习机器学习的更多东西,有问题一起交流讨论。

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值