【一起入坑AI】手把手教你 keras+CNN实现经典入门实战案例---猫狗识别

目录

    • 一、卷积神经网络简述
    • 二、猫狗数据下载与代码实现
      • 2.1 猫狗数据下载链接
      • 2.2 代码实现
        • 2.2.1 我将代码分为两部分:
        • 2.2.2 代码
    • 三、优化过程

一、卷积神经网络简述

典型的卷积神经网络通常由以下三种层结构共同组成:
卷积层(Convolution)、下采样池化层(Pooling)、全连接层(Fully connected)

其中卷积是为了提取出局部特征值,池化是从这些特征值里面筛选更有特征的特征值,使得卷积输出的数组尺寸近一步缩小,而全连接就是把以前的局部特征重新通过权值矩阵组装成完整的图。
注:只用一层全连接层有时候没法解决非线性问题,而如果有两层或以上全连接层就可以很好地解决非线性问题了,这也是代码用两层全连接层(Dense)原因。

具体CNN原理可以看看我另一篇博客,相信仔细看完会对CNN有更深刻的理解:https://blog.csdn.net/weixin_39615182/article/details/109854446

二、猫狗数据下载与代码实现

2.1 猫狗数据下载链接

分享两个数据下载链接,一个是kaggle提供的,另一个是我自己取了一部分并处理好的图片。说下区别,kaggle提供的训练集就有25000张图片,训练集太大了,如果每张图片要处理成150×150的图片,图片表示150×150的数组,也就是25000×150×150=562500000,数据量太大,我笔记本根本跑不动,如果你电脑配置很高,有很强大的独显可以拿原数据去跑下,我自己取了4000张图片作为训练集,1000张作为测试集,其中每个数据集中猫狗图片各一半(训练/测试=4/1)。

链接: https://pan.baidu.com/s/1XrVZ04IKr4jughz3OwcQPA 提取码:6swb
在这里插入图片描述

2.2 代码实现

2.2.1 我将代码分为两部分:

1、数据预处理部分:将所有原图片处理成相同大小的新图片,再将图片转成对应数组,保存为.npy文件,保存为npy文件是为了避免每次都要长时间将所有图片转换为数组,这样保存一次就能以后直接加载数组即可 → data_preprocessing.py
注:npy文件是一种用python程序生成,用于存放数据的文件格式,npy文件存的就是数组,由numpy库的save与load来生成与加载

2、对数据进行训练、建模、预测部分 → cat_dog_main.py

2.2.2 代码

data_preprocessing.py

import os
import random
import cv2
import numpy as np
from keras.preprocessing import image


####################################### Method part
def load_data(path, flag):
    files = os.listdir(path)  # os.listdir() 方法用于返回指定的文件夹中的文件或文件夹的名字的列表
    random.shuffle(files)  # 打乱数据集图片顺序,随机化
    images, labels = [], []
    for filename in files:
        # 图片批处理成128*128像素的数据集(opencv处理)
        print(filename)  # 打印正在转换的图片名
        img_path = path + filename
        img = cv2.imread(img_path)
        res = cv2.resize(img, (128, 128), interpolation=cv2.INTER_CUBIC)
        cv2.imwrite(img_path, res)

        # 以下循环都是将图片转成数组存到images列表(数组)中,并且给每个图片上标签
        img = image.load_img(img_path, target_size=(128, 128))  # 加载128*128的图片
        img_array = image.img_to_array(img)
        images.append(img_array)
        if 'cat' in filename:
            labels.append(0)  # 0 表示猫,1表示狗
        else:
            labels.append(1)
    images = np.array(images)
    labels = np.array(labels)
    if flag == 1:
        np.save("./npy_file/train_images.npy", images)  # 将images数组保存成npy文件,以防每次都要将图片转成数组
        np.save("./npy_file/train_labels.npy", labels)
        print("save train_data success...")
    else:
        np.save("./npy_file/test_images.npy", images)
        np.save("./npy_file/test_labels.npy", labels)
        print("save test_data success...")
    return images, labels

cat_dog_main.py

import matplotlib.pyplot as plt
import numpy as np
from keras.utils import to_categorical
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from keras import models, optimizers, regularizers, initializers
from data_preprocessing import load_data

####################################### 1、加载与处理数据,训练集/测试集=4/1
# train_images, train_labels = load_data(path='./cat_dog/train/', flag=1)  # flag=1表示训练数据
# test_images, test_labels = load_data(path='./cat_dog/test/', flag=2)
train_images = np.load("./npy_file/train_images.npy")
train_labels = np.load("./npy_file/train_labels.npy")
test_images = np.load("./npy_file/test_images.npy")
test_labels = np.load("./npy_file/test_labels.npy")
print("train_image:", train_images.shape, "train_labels:", train_labels.shape)  # (4000, 128, 128, 3)
print("test_image:", test_images.shape, "test_labels:", test_labels.shape)

img_w = train_images.shape[1]
img_h = train_images.shape[2]
train_images = train_images.astype("float")
test_images = test_images.astype("float")
train_labels = to_categorical(train_labels)  # 转成一维行向量
test_labels = to_categorical(test_labels)

# 归一化
train_images = train_images / 255
test_images = test_images / 255

####################################### 2、搭建神经网络
# 卷积->池化->卷积->池化->卷积->池化->Flatten(扁平化)->全连接->全连接
model = models.Sequential()
# 第一次卷积可以提取出低层次的特征,32个卷积核
model.add(Conv2D(32, 3, input_shape=(128, 128, 3), activation="relu"))  # 卷积
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2))) 
# 第二次卷积可以提取出中层次的特征
model.add(Conv2D(64, 3, activation='relu'))
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2)))
# 第三次卷积可以提取出高层次的特征
model.add(Conv2D(128, 3, activation='relu'))
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())  # Flatten层用来将多维的输入一维化,常用在从卷积层到全连接层的过渡,即扁平化操作

model.add(Dense(units=256, activation='relu', kernel_regularizer=regularizers.l2(0.01),
                kernel_initializer=initializers.truncated_normal(mean=0.0, stddev=0.01, seed=None)))
model.add(Dropout(0.3))
model.add(Dense(units=2, activation='softmax'))  # 二分类问题
model.summary()

######################################## 3、训练

# TBCallbacks = callbacks.TensorBoard(log_dir='./logs', histogram_freq=1, write_graph=True, write_images=True)
# 模型编译
EPOCHS = 25
model.compile(loss='categorical_crossentropy', optimizer=optimizers.Adam(lr=0.0001), metrics=['accuracy'])
H = model.fit(train_images, train_labels, epochs=EPOCHS, batch_size=150, verbose=2,
              validation_data=(test_images, test_labels))

######################################## 4、预测与绘图
# 预测(取前10个观察预测情况)
y_pre = model.predict(test_images[:10])
print("预测值:", y_pre, "\n真实值:", test_labels[:10])

# 绘图
N = np.arange(0, EPOCHS)  # 迭代数
plt.figure()  # 新建画布
plt.plot(N, H.history["accuracy"], label="train_acc")
plt.plot(N, H.history["val_accuracy"], label="test_acc")
plt.title("accuracy")
plt.xlabel("EPOCHS")
plt.ylabel("accuracy")
plt.legend()
plt.show()

三、优化过程

第一次运行结果(EPochs=20,batch_size=150)
在这里插入图片描述
可以观察到训练集拟合的太好,出现过拟合,而且很大,相差27%,我们开始优化,用正则化与初始化以及dropout来解决过拟合问题
关于过拟合及其常见处理办法推荐下面的文章:
https://blog.csdn.net/jingbo18/article/details/80609006

第二次运行结果
【一起入坑AI】手把手教你 keras+CNN实现经典入门实战案例---猫狗识别_第1张图片
训练准确率:0.7703,测试准确率为0.7110

第三次运行结果(Epochs=25,batch_size=150)
【一起入坑AI】手把手教你 keras+CNN实现经典入门实战案例---猫狗识别_第2张图片
学习率:0.0001 l2(0.01) 初始化中参数stddev=0.01

结果:训练准确率=0.8192 测试准确率=0.7560,还是有点过拟合,这里我没有继续调了,因为跑一次就要30-40分钟,我这三次就用了将近两小时,太费时了,无奈没办法电脑还是2016年买的,现在有点小垃圾了,大家有兴趣可以继续调下,电脑配置好的,可以多取些图片作为样本跑,因为也不排除我取4000张图片训练,样本还是少,这也可能是过拟合的原因。

结论:取4000张作为训练集正确率达70-80%。

下面是代码中预测部分,取打乱后的前十张图片观察预测结果,发现7对,3错
注:softmax函数,预测结果是概率,第一个位置表示猫,第二个位置表示狗,观察预测出的哪个概率大,并与真实比较,看预测对不对。
【一起入坑AI】手把手教你 keras+CNN实现经典入门实战案例---猫狗识别_第3张图片
以上就是猫狗大战的讲解,希望其中的某一点对你有帮助。

你可能感兴趣的