学习笔记
前言
本次案例是基于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()
四、最后
如有错误,欢迎指正