深度学习之CNN实例分析

学习笔记


前言

本次案例是基于keras库实现的狗分类模型

所用版本
python 3.7
keras 2.6.0


一、数据处理

1.所需库

import os  # 读取文件名
import cv2 as cv  # 读取数据集图片
from sklearn.preprocessing import LabelEncoder  # 标签张量化
from sklearn.model_selection import train_test_split  # 划分数据集
from keras.utils.np_utils import to_categorical

2.处理步骤

本次案例中使用的数据集来自kaggle的stanford-dogs-dataset数据集
https://www.kaggle.com/datasets/jessicali9530/stanford-dogs-dataset
有现成数据集的原因,大致分为两步读取数据张量化划分数据集

读取

本次案例读取采用python基本库os,和opencv库完成

# 读取文件目录名
os.listdir('input/stanford_dogs_date/images/Images')
dir = 'input/stanford_dogs_date/images/Images/'
chihuahua_dir = dir + 'n02085620-Chihuahua'  # 吉娃娃
japanese_spaniel_dir = dir + 'n02085782-Japanese_spaniel'  # 日本种
maltese_dog_dir = dir + 'n02085936-Maltese_dog'  # 马尔济斯犬
pekinese_dir = dir + 'n02086079-Pekinese'  # 北京狮子狗
shih_Tzu_dir = dir + 'n02086240-Shih-Tzu'  # 西施犬
blenheim_spaniel_dir = dir + 'n02086646-Blenheim_spaniel'  # 英国可卡犬
papillon_dir = dir + 'n02086910-papillon'  # 蝴蝶犬
toy_terrier_dir = dir + 'n02087046-toy_terrier'  # 玩具猎狐梗
afghan_hound_dir = dir + 'n02088094-Afghan_hound'  # 阿富汗猎犬
basset_dir = dir + 'n02088238-basset'  # 巴吉度猎犬


# 将图片和标签存入X_data和y_lable数据集中
X_data = []
y_label = []
imgsize = 150
def tarin_data(label, data_dir):
    for img_name in os.listdir(data_dir):  # 遍历单个狗狗种类文件夹里所有照片的名字
        path = os.path.join(data_dir, img_name)  # 生成照片的路径
        img = cv.imread(path, cv.IMREAD_COLOR)  # 读取照片
        img = cv.resize(img, (imgsize, imgsize))  # 缩放 使生成的图像数组形状(shape)一致
        print(type(img))
        X_data.append(np.array(img))
        y_label.append(str(label))


# 将十个不同品种的狗狗图片传入 X_data 并把标签传入 y_lable
tarin_data('chihuahua', chihuahua_dir)
tarin_data('japanese_spaniel', japanese_spaniel_dir)
tarin_data('maltese_dog', maltese_dog_dir)
tarin_data('pekinese', pekinese_dir)
tarin_data('shih_Tzu', shih_Tzu_dir)
tarin_data('blenheim_spaniel', blenheim_spaniel_dir)
tarin_data('papillon', papillon_dir)
tarin_data('toy_terrier', toy_terrier_dir)
tarin_data('afghan_hound', afghan_hound_dir)
tarin_data('basset', basset_dir)

img = cv.resize(img, (imgsize, imgsize))

resize()方法设置照片的大小,更重要的是将照片大小规范、统一化

张量化

因为深度学习模型只能处理张量数值,本案例中主要是对图片X_data和对应标签y_label进行张量化

# X,y张量化
label_Encoder = LabelEncoder()
y = label_Encoder.fit_transform(y_label)
y = to_categorical(y, 10)  # to_categorical 将标签向量转化成只包含[0,1]的矩阵,一个标签对应矩阵的一个行向量
X = np.array(X_data)  # 将X_data 转化成张量
X = X / 255  # 归一化,将数据范围限制到[0-1]之间
"""
fit()这个方法把传入的序列去重以升序排列
transform()方法必须在使用fit()方法后才能使用, 其目的是将序列按照
fit()排好的顺序取一个标签(从0开始),然后按照输入序列对应的位置输出对应的标签序列
fit_transform()方法就是fit 与 transform的结合 返回array类型
"""

划分数据集

本案例使用train_test_split()方法将数据集按照一定比例划分为训练集和验证集

# 划分数据集
X_tarin, X_test, y_tarin, y_test = train_test_split(X, y, train_size=0.8, random_state=0)  # random_state表示训练集和测试集打乱的个数

二、模型网络构建及模型训练

1.所需库

from keras import layers  # 图层
from keras import models  # 模型
from keras import optimizers  # 优化器
from keras.preprocessing.image import ImageDataGenerator  # 图像生成器

2.构建模型

本案例中采用了卷积层、池化层、随机失活、展平层、全连接层

卷积层:提取特征,生成特征图
池化层:池化的作用主要体现在减少了参数,减少了不必要的计算量,缓解过拟合问题
随即失活:模拟人脑神经元,缓解过拟合
展平层:主要用于卷积层和全连接层的过渡
全连接层:主要实现分类功能

# 构建网络模型 CNN
cnn_model = models.Sequential()  # Sequential模型是顺序模型,线性结构,可以简单理解为多个图层顺序堆叠构建神经网络
cnn_model.add(layers.Conv2D(32, (3, 3), activation='relu',
                            input_shape=(150, 150, 3)))  # 卷积层 Conv2D二维卷积,常用于图像数据,Con1D一维卷积,常用于时间序列和文本数据
cnn_model.add(layers.MaxPool2D((2, 2)))  # 池化层-最大池化
cnn_model.add(layers.Conv2D(64, (3, 3), activation='relu'))  # 卷积层
cnn_model.add(layers.Dropout(0.5))  # Dropout层 随机失活
cnn_model.add(layers.MaxPool2D((2, 2)))  # 池化层-最大池化
cnn_model.add(layers.Conv2D(128, (3, 3), activation='relu'))  # 卷积层
cnn_model.add(layers.Dropout(0.5))  # Dropout层 随机失活
cnn_model.add(layers.MaxPool2D((2, 2)))  # 池化层-最大池化
cnn_model.add(layers.Conv2D(256, (3, 3), activation='relu'))  # 卷积层
cnn_model.add(layers.MaxPool2D((2, 2)))  # 池化层-最大池化
cnn_model.add(layers.Flatten())  # 展平层 将数据一维化,全连接层只能处理一维数据,用于卷积层与全连接层之间
cnn_model.add(layers.Dropout(0.5))  # Dropout层 随机失活
cnn_model.add(layers.Dense(512, activation='relu'))  # 全连接层
cnn_model.add(layers.Dense(10, activation='sigmoid'))  # 全连接层, 通过特征提取实现分类
# compile()方法用于设置训练时的 损失函数、优化器、评估指标
cnn_model.compile(
    loss='categorical_crossentropy',  # 损失函数
    optimizer=optimizers.adam_v2.Adam(1e-4),  # 优化器,设置学习率为1e-4
    metrics=['acc']  # 评估指标,acc以准确度为指标(全体样本),与准确率区分(部分)
)

compile()方法用于设置损失函数、优化器、评估指标

3.模型训练

keras中常用的训练方法有两个fit()和fit_generator()
fit()方法直接对数据集进行迭代,fit_generator()批次生成的数据按照批次迭代训练( Python 生成器或 Sequence 实例)

两个方法的选择上fit()适合数量较小、比较简单的数据集,fit_generator()在数据较大时较为合适
本案例采用fit()方法,fit_generator()可搭配ImageDataGenerator图像生成器进行数据增强

# fit()方法 训练模型,返回一个History对象,记录了loss及其他指标随epoch的变化
history = cnn_model.fit(
    X_tarin, y_tarin,  # 训练集
    epochs=50,  # 迭代轮次
    validation_data=(X_test, y_test)  # 指定验证集
)

4.模型保存

# 保存模型
cnn_model.save('model/my_dog_cnn.h5')

三、绘制loss函数

loss和val_loss分别代表训练集和验证集的损失值,acc和val_acc同理
参数可通过history获得

# 绘制图像
print(history.history)
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))

plt.plot(epochs, acc, 'b', label='Training accuracy')
plt.plot(epochs, val_acc, 'r', label='validation accuracy')
plt.title('Training and validation accuracy')
plt.legend(loc='lower right')
plt.figure()

plt.plot(epochs, loss, 'r', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()

四、最后

如有错误,欢迎指正

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值