Keras实现基础卷积神经网络
1. 卷积神经网络基础
卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习的代表算法之一。卷积神经网络基础知识包括卷积运算、特征图与感受野,填充(padding)与步幅(stride)等,在我之前的博客:动手学深度学习(PyTorch实现)(六)–卷积神经网络基础中有详细的描述,在此不再赘述,本博客着重于利用TensorFlow中的tf.keras实现基础的卷积神经网络。
2. Keras实现卷积神经网络
本文以分类问题为例,通过keras来实现基出的卷积神经网络,数据集采用之前DNN使用的fashion_mnist 的数据集,里面是像素为28*28的黑白图像
2.1 导入相应的库
首先我们要导入要用到的python库
# matplotlib 用于绘图
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
# 处理数据的库
import numpy as np
import sklearn
import pandas as pd
# 系统库
import os
import sys
import time
# TensorFlow的库
import tensorflow as tf
from tensorflow import keras
2.2 数据集的加载与处理
加载数据集:
# 下载数据集
fashion_mnist = keras.datasets.fashion_mnist
# 拆分训练集与测试集
(x_train_all, y_train_all),(x_test, y_test) = fashion_mnist.load_data()
# 对训练集进行拆分,前5000个数据集作为验证集,其余的作为数据集
x_valid, x_train = x_train_all[:5000], x_train_all[5000:]
y_valid, y_train = y_train_all[:5000], y_train_all[5000:]
数据归一化可以减少模型的过拟合现象,从而可以提高模型的分类准确率,这里我们使用sklearn中的Standardscaler库对数据进行归一化处理:
from sklearn.preprocessing import StandardScaler
# 初始化scaler对象
scaler = StandardScaler()
# x_train: [None, 28, 28] -> [None, 784]
# 因为数据是int型,但是归一化要做除法,所以先转化为float32型
# 训练集数据使用的是 fit_transform,和验证集与测试集中使用的 transform 是不一样的
# fit_transform 可以计算数据的均值和方差并记录下来
# 验证集和测试集用到的均值和方差都是训练集数据的,所以二者的归一化使用 transform 即可
# 归一化只针对输入数据, 标签不变
x_train_scaled = scaler.fit_transform(
x_train.astype(np.float32).reshape(-1, 1)).reshape(-1, 28, 28, 1)
x_valid_scaled = scaler.transform(
x_valid.astype(np.float32).reshape(-1, 1)).reshape(-1, 28, 28, 1)
x_test_scaled = scaler.transform(
x_test.astype(np.float32).reshape(-1, 1)).reshape(-1, 28, 28, 1)
2.3 构建模型
本文构建一个简单的卷积神经网络,由三个基本单元组成,每个单元由两层卷积层和一层最大池化层组成,最后由两层全连接层结束。
# tf.keras.models.Sequential()用于将各个层连接起来
model = keras.models.Sequential()
# 第一层卷积层
model.add(keras.layers.Conv2D(filters = 32, # 卷积核数量
kernel_size = 3, # 卷积核尺寸
padding = 'same', # padding补齐,让卷积之前与之后的大小相同
activation = 'relu', # 激活函数relu
input_shape = (28, 28, 1))) # 输入维度是1通道的28*28
# 第二层卷积层
model.add(keras.layers.Conv2D(filters = 32, # 卷积核数量
kernel_size = 3, # 卷积核尺寸
padding = 'same', # padding补齐,让卷积之前与之后的大小相同
activation = 'relu')) # 激活函数relu
# 最大池化层
model.add(keras.layers.MaxPool2D(pool_size=2))
# 第三层卷积层
model.add(keras.layers.Conv2D(filters = 64, # 卷积核数量
kernel_size = 3, # 卷积核尺寸
padding = 'same', # padding补齐,让卷积之前与之后的大小相同
activation = 'relu')) # 激活函数relu
# 第四层卷积层
model.add(keras.layers.Conv2D(filters = 64, # 卷积核数量
kernel_size = 3, # 卷积核尺寸
padding = 'same', # padding补齐,让卷积之前与之后的大小相同
activation = 'relu')) # 激活函数relu
# 最大池化层
model.add(keras.layers.MaxPool2D(pool_size = 2))
# 第五层卷积层
model.add(keras.layers.Conv2D(filters=128, # 卷积核数量
kernel_size = 3, # 卷积核尺寸
padding = 'same', # padding补齐,让卷积之前与之后的大小相同
activation = 'relu')) # 激活函数relu
# 第六层卷积层
model.add(keras.layers.Conv2D(filters=128, # 卷积核数量
kernel_size = 3, # 卷积核尺寸
padding = 'same', # padding补齐,让卷积之前与之后的大小相同
activation = 'relu')) # 激活函数relu
# 最大池化层
model.add(keras.layers.MaxPool2D(pool_size = 2))
# 全连接层
model.add(keras.layers.Flatten()) # 展平输出
model.add(keras.layers.Dense(128, activation = 'relu'))
model.add(keras.layers.Dense(10, activation = "softmax")) # 输出为 10的全连接层
我们看看模型的结构:
model.summary()
2.4 模型的编译与训练
我们在构建好神经网络模型之后需要对模型进行编译:
model.compile(loss = "sparse_categorical_crossentropy", # 稀疏分类交叉熵损失函数
optimizer = keras.optimizers.SGD(0.01), # 优化函数为随机梯度下降 ,学习率为0.01
metrics = ["accuracy"]) # 优化指标为准确度
开始训练:
history = model.fit(x_train_scaled, y_train, # 训练数据
epochs = 10, # 训练周期,数据分为10次进行训练
validation_data = (x_valid_scaled, y_valid),) # 验证集
训练过程为:
2.5 学习曲线绘制
def plot_learning_curves(history):
pd.DataFrame(history.history).plot(figsize=(8, 5))
plt.grid(True)
plt.gca().set_ylim(0, 1)
plt.show()
plot_learning_curves(history)
2.6 模型验证
我们在验证集上看看模型的表现:
model.evaluate(x_test_scaled, y_test, verbose = 0)
输出结果为:
我们训练了十次的CNN在验证集上能够达到89.82%的准确率。