keras 入门:卷积神经网络实现 MNIST 手写数字识别
手写数字识别问题作为机器学习领域中的一个经典问题,本文介绍如何使用 keras 构建卷积神经网络模型实现 MNIST 手写数字识别。文本代码只需更换训练集目录,修改图片输入尺寸和类别数量等少量参数,即可直接应用到其他图像分类的问题中。
一、数据准备
关于如何解析 MNIST 数据集,可以参看另一片文章:python 读取 MNIST 数据集,并解析为图片文件。解析出的数据集具有如下目录结构:
mnist_data/
|----train/
|----0/
|----0.png
|----1/
|----1.png
...
|----test/
...
二、keras 搭建卷积神经网络
1. 卷积神经网络简介
卷积神经网络的概念最早出自 19 世纪 60 年代提出的感受野 ( Receptive Field [1]),到了 20 世纪 80 年代,日本科学家提出神经认知机 ( Neocognitron [2] ) 的概念,是卷积神经网络的实现原型。卷积神经网络可以利用空间结构关系减少需要学习的参数量,提高反向传播算法的训练效率。一般的 CNN 有多个卷积层构成,每个卷积层会进行如下操作:
- 图像通过多个不同的卷积核的滤波,并加偏置 ( bias ),提取出局部特征,每一个卷积核会映射出一个新的 2D 图像。
- 将前面卷积核的滤波输出结果进行非线性的激活函数处理。
- 对激活函数的结果再进行池化操作 ( 即降采样),目前一般是使用最大池化,保留最显著的特征,并提升模型的畸变容忍能力。
这几个步骤就构成最常见的卷积层,当然也可以在加上一个 LRN [3] ( Local Response Normalization,局部响应归一化层) 层。
CNN 的要点是卷积核的权值共享 ( Weight Sharing )、局部连接模式 ( Local Connection )和池化层 ( Pooling ) 中的降采样 ( Down-Sampling )。局部连接和权值共享降低了参数量,使训练复杂度大大下降,减轻过拟合并降低计算量。同时权值共享还赋予了 CNN 对平移的容忍性,而池化层降采样则进一步降低了输出层参数,并赋予模型轻度形变的容忍性,提高模型的泛化能力。
LeNet5 [4] 提出于1994 年,是最早的深层卷积神经网络之一。LeNet5 当时的特性有如下几点: - 每个卷基层包含三个部分:卷积、池化和非线性激活函数
- 使用卷积提取空间特征
- 降采样的平均池化层
- 双曲正切或 S 型的激活函数
- MLP 作为最后的分类器
- 层与层之间的稀疏连接减少计算复杂度
2. 卷积神经网络搭建
使用 keras API 可以很容易搭建一个卷积神经网络,在此我们搭建的网络结构具有 重复三重的 3 * 3 卷积核加 2 * 2 最大池化层,最后加两个全连接层。
第一层卷积输入图像尺寸,设置64个卷积核,经过 2 * 2 最大池化层后,第二层卷积层需要 128 个卷积核,同理第三层卷积是 256 个卷积核。然后将矩阵平整为一维,接一层 256 输出的全链接层,最后一层输出为类别标签数的全连接层,并且该层使用 ‘softmax’ 作为激活函数。
def build_model(self):