深度学习之基于CNN和VGG19实现猫狗大战

猫狗大战在一开始接触深度学习的时候,实现过,也写过一篇博客。但是当时的理解并不是很深,在做过之前的实验之后,再次接触猫狗大战,就有一些别的体会了。
本次实验基于自己搭建的CNN与VGG19的官方模型,实现猫狗大战。引入混淆矩阵与Accuracy_Loss图观察模型准确率。

1.导入库

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import os,pathlib,PIL
from tensorflow import keras
from tensorflow.keras import layers,models,Sequential,Input,Model
from tensorflow.keras.layers import Conv2D,MaxPooling2D,Flatten,Dense

# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

2.数据准备

#数据所在文件地址
data_dir = "E:/tmp/.keras/datasets/cats_and_dogs"
data_dir = pathlib.Path(data_dir)
img_count = len(list(data_dir.glob('*/*.jpg')))
print(img_count)#共3400张图片

all_images_paths = list(data_dir.glob('*'))##”*”匹配0个或多个字符
all_images_paths = [str(path) for path in all_images_paths]
all_label_names = [path.split("\\")[5].split(".")[0] for path in all_images_paths]
#['cats','dogs']

参数设置

height = 224
width = 224
epochs = 40
batch_size = 128

数据处理
包括数据增强的一系列操作以及按照8:2的比例划分为训练集和测试集

train_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,
    rotation_range=45,
    shear_range=0.2,
    zoom_range=0.2,
    validation_split=0.2,
    horizontal_flip=True
)
train_ds = train_data_gen.flow_from_directory(
    directory=data_dir,
    target_size=(height,width),
    batch_size=batch_size,
    shuffle=True,
    class_mode='categorical',
    subset='training'
)
test_ds = train_data_gen.flow_from_directory(
    directory=data_dir,
    target_size=(height,width),
    batch_size=batch_size,
    shuffle=True,
    class_mode='categorical',
    subset='validation'
)

查看数据

plt.figure(figsize=(15, 10))  # 图形的宽为15高为10

for images, labels in train_ds:
    for i in range(8):
        ax = plt.subplot(5, 8, i + 1)
        plt.imshow(images[i])
        plt.title(all_label_names[np.argmax(labels[i])])
        plt.axis("off")
    break
plt.show()

达到了预期的目标
在这里插入图片描述

3.模型搭建

包括三层卷积池化层+Dropout+两层Dense层

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(16,3,padding="same",activation="relu",input_shape=(height,width,3)),
    tf.keras.layers.MaxPool2D(),
    tf.keras.layers.Conv2D(32,3,padding="same",activation="relu"),
    tf.keras.layers.MaxPool2D(),
    tf.keras.layers.Conv2D(64,3,padding="same",activation="relu"),
    tf.keras.layers.MaxPool2D(),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(512,activation="relu"),
    tf.keras.layers.Dense(2)
])

优化器的设置:
learning_rate是影响模型准确率的一个重要因素。
①学习率大
优点:学习速率加快、有助于跳出局部最优值
缺点:模型训练不收敛、模型不精确
②学习率小
优点:有助于模型收敛,模型细化、提高模型精度
缺点:收敛缓慢,很难跳出局部最优值
动态学习率:指数衰减型(ExponentialDecay)。在每一个epoch开始前,学习率(learning_rate)都将会重置为初始学习率(initial_learning_rate),然后再重新开始衰减。
计算公式如下所示:

learning_rate =initial_learning_rate * decay_rate ^ (step / decay_steps)
#设置优化器
#起始学习率
init_learning_rate = 1e-4
lr_sch = tf.keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate=init_learning_rate,
    decay_steps=50,
    decay_rate=0.96,
    staircase=True
)

gen_optimizer = tf.keras.optimizers.Adam(learning_rate=lr_sch)

模型编译&&训练

model.compile(
    optimizer=gen_optimizer,
    loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
    metrics=['accuracy']
)

history = model.fit(
    train_ds,
    epochs=epochs,
    validation_data=test_ds
)

训练结果可视化

#训练结果可视化
accuracy = history.history["accuracy"]
test_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
test_loss = history.history["val_loss"]
epochs_range = range(epochs)
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.plot(epochs_range,accuracy,label = "Training Acc")
plt.plot(epochs_range,test_accuracy,label = "Test Acc")
plt.legend()
plt.title("Training and Test Acc")

plt.subplot(1,2,2)
plt.plot(epochs_range,loss,label = "Training loss")
plt.plot(epochs_range,test_loss,label = "Test loss")
plt.legend()
plt.title("Training and Test loss")
plt.show()

在这里插入图片描述
40个epochs之后,模型的准确率在97%左右,准确率比较高。而且经过数据增强之后,模型的过拟合效果得到了改善。下图是上次经过50个epochs之后的效果,这次的网络模型与上次一样,但是优化器不同,致使模型的准确率得到了提高。在这里插入图片描述
模型保存:

model.save("E:/tmp/.keras/datasets/model.h5")

模型加载:

model = tf.keras.models.load_model("E:/tmp/.keras/datasets/model.h5")

利用模型进行预测:

plt.figure(figsize=(18,18))
plt.suptitle("预测结果展示")
for images,labels in test_ds:
    for i in range(16):
        ax = plt.subplot(4,4,i+1)
        plt.imshow(images[i])
        img_array = tf.expand_dims(images[i], 0)

        # 使用模型预测图片中的动物
        predictions = model.predict(img_array)
        plt.title(all_label_names[np.argmax(predictions)])

        plt.axis("off")
    break
plt.show()

在这里插入图片描述

4.VGG19

本次利用官方搭建的VGG19网络对同样的数据集进行识别。

conv_base = tf.keras.applications.VGG19(weights='imagenet',include_top=False)
#设置为不可训练
conv_base.trainable =False
#模型搭建
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(512,activation='relu'))
model.add(tf.keras.layers.Dense(2,activation='sigmoid'))

在这里插入图片描述
在epochs=10的情况下,准确率达到了99%左右,效果已经非常好了。

5.混淆矩阵

绘制混淆矩阵时的模型为自己搭建的CNN网络模型

from sklearn.metrics import confusion_matrix
import seaborn as sns
import pandas as pd

#绘制混淆矩阵
def plot_cm(labels,pre):
    conf_numpy = confusion_matrix(labels,pre)#根据实际值和预测值绘制混淆矩阵
    conf_df = pd.DataFrame(conf_numpy,index=all_label_names,columns=all_label_names)#将data和all_label_names制成DataFrame
    plt.figure(figsize=(8,7))

    sns.heatmap(conf_df,annot=True,fmt="d",cmap="BuPu")#将data绘制为混淆矩阵
    plt.title('混淆矩阵',fontsize = 15)
    plt.ylabel('真实值',fontsize = 14)
    plt.xlabel('预测值',fontsize = 14)
    plt.show()
test_pre = []
test_label = []
for images,labels in test_ds:
    for image,label in zip(images,labels):
        img_array = tf.expand_dims(image,0)#增加一个维度
        pre = model.predict(img_array)#预测结果
        test_pre.append(all_label_names[np.argmax(pre)])#将预测结果传入列表
        test_label.append(all_label_names[np.argmax(label)])#将真实结果传入列表
    break#由于硬件问题。这里我只用了一个batch,一共128张图片。
plot_cm(test_label,test_pre)#绘制混淆矩阵

在这里插入图片描述
总结:
经过数据增强,模型的过拟合问题得到了解决。改变优化器之后,模型的准确率得到了提高。VGG19的官方模型准确率很高,但是运行速度偏慢。其实博主也利用了VGG16的官方模型,但是不知是何缘故,模型的准确率一直是50%,而上次进行猫狗大战时,VGG16的模型准确率很高,其中的问题目前还不得而知。路过的大佬有知道的,希望不吝赐教。
努力加油a啊

  • 5
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值