有监督学习的过程可以简单分为以下步骤: 项目设计, 数据预处理, 模型训练, 参数调整, 模型评估. 我们需要综合目的, 数据形式, 模型特性等因素来考虑选择什么模型建模, 并且在已有模型上做出结构优化, 或者选择更好的训练算法做出训练上的优化. 比如在时序的建模上, 我们通常选择RNN, LSTM; 在数据能够表示为grid-like形式时, 我们可以选择CNN来提取特征; 为了优化训练, 我们可以选择更优的训练算法, 比如Adam; 为了防止过拟合, 我们需要用测试集进行拟合对比, 适当加入正则化, dropout等等...所以深度学习目前很大程度上也是一个很考经验的学科. 当然, 全靠经验是只能成为热门方向的追逐者, 深入理解原理和坚持自己的学术主张才有可能做出更卓越的东西.
卷积神经网络(CNN)大概是深度学习目前应用最广的一种网络. 由于CNN能够应用在非时序模型以及时序模型等多种场合, 它在图像识别, 语音识别等等领域都得到广泛应用. 本文将讲解CNN的原理, 以及其tensorflow的MNIST手写数字识别的实现.
本系列文章分为以下四篇:
- 初识CNN
- 卷积与池化
- 局部感知与权值共享
- CNN的MNIST手写数字识别实现
初识CNN
LeNet-5
在85年, Hinton提出了Back Propagation算法, 使得训练深层神经网络变得可能.
下图为LeNet. LeNet是Lecun等人在86年提出的结构, 是CNN的开山之作.
LeNet5包含三个卷积层C1和C3和C5, 两个池化层S2和S4(即Subsampling), 一个全连接层F6.
PS: LeNet5是个很好的训练简单计算参数个数的例子, 可以深入学习一下怎么算.
讲解:
(1) 输入层: 为输入size = (width=32, height=32, channel=1)的图片; 通常图片会有三个通道, 分别为:R, G, B. 由于LeNet当时用于识别手写数字, 使用灰度图, 故通 道数为1. 值得注意的是, LeNet用的是MNIST数据集, 图片大小为28*28, 但输入时进行了padding, 即在周围填充了0, 使得边边也能在kernel的卷积范围内.
(2) 卷积层C1: 通过卷积的操作提取特征. 其kernel = 5*5 ; stride = 1 ( stride 步长,即kernel每次在图片上移动时, 移动步数为1);卷积后, 特征图(feature map)的width, height可以很容易计算得到: (32-5)/1 +1= 28, 即C1的feature map为size = (width=28, height=28, depth=6).这里的depth=6的意思是我们用了6个filter, 即最后我们将 得到6个28*28的特征图.可训练参数个数为: (5*5+1)*6 = 156(加1为偏置bias, 6个filter分别有一个bias). 连接数为: 156*28*28 = 122304.
理解CNN可以类比图像处理, 例如对图像进行边缘检测时, 我们可以用高斯拉普拉斯算子(可以看做一个filter)对图像进行卷积, 得到边缘特征. 在图像识别的任务中, 我们也希望得到某种特征, 来将图像区别开来, 但是这个filter我们很难自己定义. 神经网络和普通的图像处理不同之处就在于, 其filter的权值是可以自己训练的. (至于每一层卷积网络的具体意义, 我会在<深入理解CNN>一文中详细解释)
(3) 池化层S2: 通过池化(Pooling, 也称为降采样)降低维度. 池化的意义稍后会进行讲解.此处可直观理解为由于参数过多, 我们需要降低卷积得到的特征向量的维度, 防止过拟合.池化层S2得到feature map的size = (width=14, height=14, depth=6). 和C1对比可以看出, C1的每四个格子通过某种运算变成了S2的一个格子.
可训练参数: 6(池化时每个filter都有一个coefficient) + 6(bias) = 12.
(4) 全连接层F6: 全连接层可以看做为了格式化输出, 比如在LeNet中识别0-9的10个数字, 我们需要将前面得到的C5的feature map输出成10个数字对应的数值,这可以通过一个简单的线性变化得到. 这里用了84个神经元.
了解CNN最基本结构后, 我们可以看一下近年来其他CNN结构.
AlexNet
虽然LeNet在86年就提出了, 并且用了参数共享和局部感知, 但是对于90年代的计算能力来看, CNN的参数还是过多, 难以训练.
下图为著名的Alex Net网络, 该网络在2012年ILSVRC大赛中取得的第一, 奠定了深度学习在机器视觉领域的地位. ILSVRC比赛使用百万量级的ImageNet数据集, 远超Lecun用的MNIST. 如果说LeNet在MNIST的表现只是在学术以及学习,
在Alex Net中有一个输入层, 接着是五个卷积层, 最后有三个全连接层(图中没有画出池化层). 可以看出AlexNet在基本结构上看上去与LeNet相差无几, 但其参数多于LeNet, 层数也多与LeNet. 我们在使用BP算法训练深层神经网络时, 经常会面临梯度消失或梯度爆炸的问题. 梯度消失是指后向传播的梯度由于过小, 逐渐变为0, 这使得网络参数无法更新. 相反地, 梯度爆炸将会使训练无法收敛. Hinton团队为了训练这样深层的网络, 提出了多种优化: (1)Dropout (2)多GPU并行运算(3)ReLu.
Dropout是指为了防止过拟合, 在训练过程中让神经元有0.5的概率清零, 减少神经元之间的连续性, 增大鲁棒性.
自AlexNet之后, 相似的GoogLeNet, VGG都在ILSVRC完虐其他机器学习算法, 但它们和AlexNet都大同小异. 2015年ILSVRC, 深度残差学习应用在CNN, 构造了一个150多层的CNN网络(此前VGG只到20层), 改变了CNN难以学习更深层特征的窘境. 在<Deep Residual Networks(1) - 深度残差的基本原理>一文中我将简要介绍深度残差学习, 而后会有相应实现.
CNN的训练过程:
理解了CNN如何提取图片特征后, 其主要训练过程就很容易理解了:
(1) 输入图片
(2) 构建网络并初始化参数
(3) 根据网络每一层的W和b, 通过卷积和池化等运算, 计算出最后输出Y'
(4) 定义一个损失函数, 来衡量Y' 和 正确输出标签Y的差距
(5) 使用梯度下降法降低损失函数, 并通过BP算法(详见Back Propagation(BP)一文)后向传播更新每一层网络的filter的权值和偏置
以上是CNN的初步理解.