手写体数字识别课程报告

卷积神经网络简介

卷积神经网络总体总结

卷积神经网络（Convolutional Neural Networks，CNN）是由纽约大学的 Yann Lecun 于 1998 年提出的，其本质是一个多层感知机。它是一类包含卷积计算且具有深度结构的前馈神经网络（Feedforward Neural Networks），是深度学习（Deep Learning）的代表算法之一。卷积神经网络是一种特殊的多层神经网络，像其它的神经网络一样，卷积神经网络也使用一种反向传播算法来进行训练，不同之处在于网络的结构。

卷积神经网络的基本特征

具有多层层次网络结构

卷积神经网络（CNN）被认为是第一个真正成功的、采用多层层次结构网络的、具有鲁棒性的深度学习方法，它通过挖掘数据在空间上的相关性，来减少网络中的可训练参数的数量，从而改进了前向传播网络的反向传播算法效率。
在 CNN 中，图像中的小块区域（也叫做 “局部感知区域”）被当做层次结构中的底层的输入数据，信息通过前向传播经过网络中的各个层，在每一层中都由过滤器构成，以便能够获得观测数据的一些显著特征。因为局部感知区域能够获得一些基础的特征，比如图像中的边界和角落等，这种方法能够提供一定程度对位移、拉伸和旋转的相对不变性。
CNN 中层次之间的紧密联系和空间信息，使得其特别适用于图像的处理和理解，并且能够自动的从图像抽取出丰富的相关特性。

不需要对样本进行复杂预处理

卷积神经网络（CNN）的分类模型，与传统模型的不同点在于其可以直接将一幅二维图像输入模型中，并在输出端给出分类结果。好处显而易见，不需复杂的预处理，将特征抽取、模式分类完全放入一个黑匣子中，通过不断的优化来获得网络所需参数，在输出层给出我们需要的分类结果。CNN 的特征提取层参数是通过训练数据学习得到的，所以其避免了人工特征提取，而是从训练数据中进行学习。

局部连接，具有很强的泛化能力

卷积神经网络（CNN）的泛化能力要显著优于其它方法，已经被广泛应用于模式分类、物体检测、物体识别等方面。利用卷积神经网络建立模式分类器，将卷积神经网络作为通用的模式分类器，直接用于灰度图像。
卷积神经网络（CNN）通过结合局部感知区域、共享权重、空间或者时间上的降采样来充分利用数据本身包含的局部性等特征，优化网络结构，并且能够保证一定程度上的位移和变形的不变性。所以，CNN 可以用来识别位移、缩放及其它形式扭曲不变性的二维或三维图像。
卷积神经网络（CNN）是一种深度的监督学习下的机器学习模型，具有极强的适应性，善于挖掘数据局部特征，提取全局训练特征和分类，它的权值共享结构网络使之更类似于生物神经网络，在模式识别各个领域都取得了很好的成果。

共享权值，减少了网络参数

卷积神经网络（CNN）的权值共享特性，可以减少需要求解的参数数量。在卷积层中每个神经元连接数据窗的权重是固定的，每个神经元只关注一个特性。使用多种滤波器（卷积核）去卷积图像，就会得到多种特征映射（Feature Map），同一特征映射的神经元共享权值，减少了网络参数，这也是卷积网络相对于全连接网络的一大优势。
另一方面，权值共享同时降低了网络的复杂性，且多维输入信号（语音、图像）可以直接输入网络的特点避免了特征提取和分类过程中数据重排的过程。
隐藏层的参数个数和隐藏层的神经元个数无关，只和滤波器的大小和滤波器种类的多少有关。隐藏层的神经元个数，与原图像（也就是输入的大小，即神经元个数）、滤波器的大小和滤波器在图像中的滑动步长都有关。

CNN 网络结构与基本原理

典型的 CNN 由 3 个主要部分构成（卷积层、池化层、全连接层），总共有五个层级。

输入层

卷积层

激活层

池化层

全连接层

如果简单来描述的话：

卷积层负责提取图像中的局部特征；池化层用来大幅降低参数量级 (降维)；全连接层类似传统神经网络的部分，用来输出想要的结果。

典型的 CNN 并非只是下面提到的三层结构，而是将其排列组合形成多层结构，例如 LeNet-5 的结构就为卷积层 – 池化层 - 卷积层 – 池化层 – 卷积层 – 全连接层

输入层 -------- 预处理

与传统神经网络 / 机器学习一样，模型需要输入的进行预处理操作，常见的 3 中预处理方式有：去均值、归一化、PCA/SVD 降维等。

卷积层 —— 提取特征

卷积层是用一个卷积核扫完整张图片，这个过程我们可以理解为我们使用一个过滤器（卷积核）来过滤图像的各个小区域，从而得到这些小区域的特征值。

总结：卷积层的通过卷积核的过滤提取出图片中局部的特征，跟上面提到的人类视觉的特征提取类似。

激活层

所谓激活，实际上是对卷积层的输出结果做一次非线性映射。

如果不用激活函数（其实就相当于激活函数是 f (x)=x），这种情况下，每一层的输出都是上一层输入的线性函数。容易得出，无论有多少神经网络层，输出都是输入的线性组合，与没有隐层的效果是一样的，就成了最原始的感知机。

常用的激活函数有：

Sigmoid 函数 （慢）

Tanh 函数（文本和音频处理有比较好的效果）

ReLU （快，但效果不佳）

Leaky ReLU

ELU

Maxout

本次使用了 ReLU 函数。

池化层（下采样）—— 数据降维，避免过拟合

池化层简单说就是下采样或欠采样，主要用于特征降维，压缩数据和参数的数量，减小过拟合，同时提高模型的容错性。主要有：

Max Pooling：最大池化

Average Pooling：平均池化

全连接层 —— 输出结果

经过前面若干次卷积 + 激励 + 池化后最后到输出结果，模型会将学到的一个高质量的特征图片全连接层。其实在全连接层之前，如果神经元数目过大，学习能力强，有可能出现过拟合。因此，可以引入 dropout 操作，来随机删除神经网络中的部分神经元，来解决此问题。还可以进行局部归一化（LRN）、数据增强等操作，来增加鲁棒性。

当来到了全连接层之后，可以理解为一个简单的多分类神经网络（如：BP 神经网络），通过 softmax 函数得到最终的输出，整个模型训练完毕。

手写体识别过程简介

获取数据集

训练数据集

运行一个带 GUI 程序

在 GUI 程序中用鼠标手写输入

使用 CNN 用全连接层输出识别结果

训练环境，训练结果与 GUI 界面展示（包括测试集随机抽取与鼠标手写输入）

训练环境

系统环境

选择了 wsl（Windows Subsystem for Linux）

在 linux 下，python 存在的小 bug 相对较小，而日常使用中 Windows 相对方便，故选择了 wsl （Windows Subsystem for Linux）。且之前就在 wsl 中安装了 conda 环境，不必重新配置。

python 环境

选择了 Miniconda

Anaconda 太臃肿了，它的安装大小超过 2 GB，还安装了一堆通常不会使用的软件，例如 Python IDE：Spyder，因为大多数情况下我们都使用了更加现代化的编辑器，比如 VS code 。因此，课前我电脑上的 python 环境就是 Miniconda。

python 依赖安装

既然我们已经安装了 conda 环境，那就没有必要再用 pip 来管理依赖了，可以直接使用 conda 进行管理。我创建了一个这样的虚拟环境配置文件environment.yml 并且通过 conda env create --file environment.yml 完成了所有需要的依赖的安装。具体我当年是参考了别人的blog (1).

Copy
name: aiclass_handwriting
channels:
- defaults
dependencies:
- python=3.6 # 选择了 python 3.6 版本
- tensorflow
- numpy
- matplotlib
- pylint
- autopep8
- notebook
- PyQt
- PyQtGraph

编辑器

选择了 VS code

编辑器也和教程不同，也是主要因为之前的开发环境如此。

具体我当年是参考了教程(2).

电脑硬件

联想 R9000P 2021 版本

训练结果

下图为此次实验 loss 曲线

最后的测试精度为 98.7%

GUI 界面展示

初始界面

随机抽取

手写识别

过程中的问题与体会

问题

测试集与训练集可能存在重合

该实验似乎没有区分测试集与训练集，造成了一定的 leak，使鼠标手写输入的 Softmax 显著低于 MNIST 集中随机抽中的集（也有可能是我的训练未达理想目标，或者对代码理解不足）

wsl 下字体显示一开始存在问题

默认配置为 Windows 下环境，默认字体在 linux 中缺失中文字符，通过替换字体解决

训练过慢

使用更小的数据集处理训练

体会

数据集的大小对精度影响远远没有训练层数影响大。

coding 是个很有趣的过程。

参考资料链接

[1] Don’t use Anaconda: How to setup a decent machine learning environment? https://blog.spencerwoo.com/2020/02/dont-use-anaconda

[2] wsl 使用 Visual Studio Code https://dowww.spencerwoo.com/3-vscode/3-0-intro.html