深度学习笔记(三 )Constitutional Neural Networks

时间:2023-03-09 15:54:46
深度学习笔记(三 )Constitutional Neural Networks

一. 预备知识

包括 Linear Regression, Logistic Regression和 Multi-Layer Neural Network。参考 http://ufldl.stanford.edu/tutorial/supervised/MultiLayerNeuralNetworks/

或者coursera看Andrew Ng 的机器学习课程。二者只是在某些公式表达上有细微的差距。

二. 卷积神经网络CONVNET

此部分来自 http://m.blog.csdn.net/article/details?id=50534376 这里只是个搬运工,作者写的很好。

1. 前言

卷积神经网络(Constitutional Neural Networks, CNN)是在多层神经网络的基础上发展起来的针对图像分类和识别而特别设计的一种深度学习方法。先回顾一下多层神经网络:

深度学习笔记(三 )Constitutional Neural Networks

多层神经网络包括一个输入层(input layer)和一个输出层(output layer),中间有多个隐藏层(hidden layers)。每一层有若干个神经元(neuron),相邻的两层之间的后一层的每一个神经元都分别与前一层的每一个神经元连接。在一般的识别问题中,输入层代表特征向量,输入层的每一个神经元代表一个特征值。

在图像识别问题中,输入层的每一个神经元可能代表一个像素的灰度值。但这种神经网络用于图像识别有几个问题,一是没有考虑图像的空间结构,识别性能会受到限制;二是每相邻两层的神经元都是全相连(Fully Connected),参数太多,训练速度受到限制。

而卷积神经网络就可以解决这些问题。卷积神经网络使用了针对图像识别的特殊结构,可以快速训练。因为速度快,使得采用多层神经网络变得容易,而多层结构在识别准确率上又很大优势。

2. 卷积神经网络的结构

卷积神经网络有三个基本概念:局部感知域(local receptive fields),共享权重(shared weights)和池化(pooling)。

局部感知域:

在上图中的神经网络中输入层是用一列的神经元来表示的,在CNN中,不妨将输入层当做二维矩阵排列的神经元。

与常规神经网络一样,输入层的神经元需要和隐藏层的神经元连接。但是这里不是将每一个输入神经元都与每一个隐藏神经元连接,而是仅仅在一个图像的局部区域创建连接。以大小为28X28的图像为例,假如第一个隐藏层的神经元与输入层的一个5X5的区域连接,如下图所示:

深度学习笔记(三 )Constitutional Neural Networks

这个5X5的区域就叫做局部感知域。该局部感知域的25个神经元与第一个隐藏层的同一个神经元连接,每个连接上有一个权重参数,因此局部感知域共有5X5个权重。如果将局部感知域沿着从左往右,从上往下的顺序滑动,就会得对应隐藏层中不同的神经元,如下图分别展示了第一个隐藏层的前两个神经元与输入层的连接情况。

深度学习笔记(三 )Constitutional Neural Networks          深度学习笔记(三 )Constitutional Neural Networks

如果输入层是尺寸为28X28的图像,局部感知域大小为5X5,那么得到的第一个隐藏层的大小是24X24。

共享权重:

上面得到的第一隐藏层中的24X24个神经元都使用同样的5X5个权重。第$j$个隐藏层中第$k$个神经元的输出为:

$\delta ({\rm{b}} + \sum\limits_{l = 1}^5 {\sum\limits_{m = 1}^5 {{W_{l,m}}{a_{j + l,k + m}}} } )$

这里 $\delta$ 是神经元的激励函数(可以是sigmoid函数、thanh函数或者rectified linear unit函数等)。$b$ 是该感知域连接的共享偏差, $W_{l,m}$ 是个5X5共享权重矩阵,因此这里有26个参数。

这就意味着第一个隐藏层中的所有神经元都检测在图像的不同位置处的同一个特征。因此也将从输入层到隐藏层的这种映射称为特征映射。该特征映射的权重称为共享权重,其偏差称为共享偏差。

为了做图像识别,通常需要不止一个的特征映射,因此一个完整的卷积层包含若干个不同的特征映射。下图中是个三个特征映射的例子。

深度学习笔记(三 )Constitutional Neural Networks

在实际应用中CNN可能使用更多的甚至几十个特征映射。以MNIST手写数字识别为例,学习到的一些特征如下:

深度学习笔记(三 )Constitutional Neural Networks

这20幅图像分别对应20个不同的特征映射(或称作filters, kernels)。每一个特征映射由5X5的图像表示,代表了局部感知域中的5X5个权重。亮的像素点代表小的权重,与之对应的图像中的像素产生的影响要小一些。暗的像素点代表的大的权重,也意味着对应的图像中的像素的影响要大一些。可以看出这些特征映射反应了某些特殊的空间结构,因此CNN学习到了一些与空间结构有关的信息用于识别。

需要说明的一点是,参数共享这个策略并不是每个场景下都合适的。有一些特定的场合,我们不能把图片上的这些窗口数据都视作作用等同的。一个很典型的例子就是人脸识别,一般人的面部都集中在图像的*,因此我们希望,数据窗口滑过这块区域的时候,权重和其他边缘区域是不同的。我们有一种特殊的层对应这种功能,叫做局部连接层/Locally-Connected Layer

池化层(pooling layers)

池化层通常紧随卷积层之后使用,其作用是简化卷积层的输出。例如,池化层中的每一个神经元可能将前一层的一个2X2区域内的神经元求和。而另一个经常使用的max-pooling,该池化单元简单地将一个2X2的输入域中的最大激励输出,如下图所示:

深度学习笔记(三 )Constitutional Neural Networks

如果卷积层的输出包含24X24个神经元,那么在池化后可得到12X12个神经元。每一个特征映射后分别有一个池化处理,前面所述的卷积层池化后的结构为:

深度学习笔记(三 )Constitutional Neural Networks

Max-pooling并不是唯一的池化方法,另一种池化方法是$L2−pooling$该方法是将卷积层2X2区域中的神经元的输出求平方和的平方根。尽管细节与Max-pooling不一样,但其效果也是简化卷积层输出的信息。

将上述结构连接在一起,再加上一个输出层,得到一个完整的卷积神经网络。在手写数字识别的例子中输出层有十个神经元,分别对应0,1, … ,9的输出。

深度学习笔记(三 )Constitutional Neural Networks

网络中的最后一层是一个全连接层,即该层的每个神经元都与最后一个Max-pooling层的每个神经元连接。这个结构这是一个特殊的例子,实际CNN中也可在卷积层和池化层之后可再加上一个或多个全连接层。

局部关联细节

从输入的数据到输出数据,有三个超参数会决定输出数据的维度,分别是深度/depth,步长/stride 和 填充值/zero-padding:

  1. 所谓通道/channels,简单说来指的就是卷积层中和上一层同一个输入区域连接的神经元个数。这部分神经元会在遇到输入中的不同feature时呈现activate状态,举个例子,如果这是第一个卷积层,那输入到它的数据实际上是像素值,不同的神经元可能对图像的边缘。轮廓或者颜色会敏感。
  2. 所谓步长/stride,是指的窗口从当前位置到下一个位置,『跳过』的中间数据个数。比如从图像数据层输入到卷积层的情况下,也许窗口初始位置在第1个像素,第二个位置在第5个像素,那么stride=5-1=4.
  3. 所谓zero-padding是在原始数据的周边补上0值的圈数。(下面第2张图中的样子)

这么解释可能理解起来还是会有困难,我们找两张图来对应一下这三个量:

深度学习笔记(三 )Constitutional Neural Networks

这是解决ImageNet分类问题用到的卷积神经网络的一部分,我们看到卷积层直接和最前面的图像层连接。图像层的维度为[227*227*3],而receptive field设为11*11,图上未标明,但是滑动窗口的步长stride设为4,通道channels为48+48=96(这是双GPU并行设置),边缘没有补0,因此zero_padding为0,因此窗口滑完一行,总共停留次数为(data_len+2*zero_padding-receptive_field_len)/stride+1=(227+2*0-11)/4+1=55,因为图像的长宽相等,因此纵向窗口数也是55,最后得到的输出数据维度为55*55*96维。

深度学习笔记(三 )Constitutional Neural Networks

这是一张动态的卷积层计算图,图上的zero_padding为1,所以大家可以看到数据左右各补了一行0,窗口的长宽为3,滑动步长stride为2。

关于zero-padding:补0这个操作产生的根本原因是,为了保证窗口的滑动能从头刚好到尾。举个例子说,上2图中的上面一幅图,因为(data_len-receptive_field_len+2*zero-padding)/stride刚好能够整除,所以窗口左侧贴着数据开始位置,滑到尾部刚好窗口右侧能够贴着数据尾部位置,因此是不需要补0的。而在下面那幅图中,如果滑动步长设为4,你会发现第一次计算之后,窗口就无法『滑动』了,而尾部的数据,是没有被窗口『看到过』的,因此补0能够解决这个问题。

关于窗口滑动步长:大家可以发现一点,窗口滑动步长设定越小,两次滑动取得的数据,重叠部分越多,但是窗口停留的次数也会越多,运算律大一些;窗口滑动步长设定越长,两次滑动取得的数据,重叠部分越少,窗口停留次数也越少,运算量小,但是从一定程度上说数据信息不如上面丰富了。

3. 卷积神经网络的应用

手写数字识别

Michael Nielsen提供了一个关于深度学习和CNN的在线电子书,并且提供了手写数字识别的例子程序,可以在GitHub上下载到。该程序使用Python和Numpy, 可以很方便地设计不同结构的CNN用于手写数字识别,并且使用了一个叫做Theano的机器学习库来实现后向传播算法和随机梯度下降法,以求解CNN的各个参数。Theano可以在GPU上运行,因此可大大缩短训练过程所需要的时间。CNN的代码在network3.py文件中。

作为一个开始的例子,可以试着创建一个仅包含一个隐藏层的神经网络,代码如下:

import network3
from network3 import Network
from network3 import ConvPoolLayer, FullyConnectedLayer, SoftmaxLayer
training_data, validation_data, test_data = network3.load_data_shared()
mini_batch_size = 10
net = Network([FullyConnectedLayer(n_in=784,n_out=100),SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
net.SGD(training_data, 60, mini_batch_size, 0.1, validation_data, test_data)

该网络有784个输入神经元,隐藏层有100个神经元,输出层有10个神经元。在测试数据上达到了97.80%的准确率。

如果使用卷积神经网络会不会比它效果好呢?可以试一下包含一个卷积层,一个池化层,和一个额外全连接层的结构,如下图

深度学习笔记(三 )Constitutional Neural Networks

在这个结构中,这样理解:卷积层和池化层学习输入图像中的局部空间结构,而后面的全连接层的作用是在一个更加抽象的层次上学习,包含了整个图像中的更多的全局的信息。

net = Network([ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),  filter_shape=(20, 1, 5, 5), poolsize=(2, 2)), FullyConnectedLayer(n_in=20*12*12, n_out=100), SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
net.SGD(training_data, 60, mini_batch_size, 0.1, validation_data, test_data)   

这种CNN的结构达到的识别准确率为98.78%。如果想进一步提高准确率,还可以从以下几方面考虑:

再添加一个或多个卷积-池化层

再添加一个或多个全连接层

使用别的激励函数替代sigmoid函数。比如Rectifed Linear Units函数:f(z)=max(0,z).Rectified Linear Units函数相比于sigmoid函数的优势主要是使训练过程更加快速。

使用更多的训练数据。Deep Learning因为参数多而需要大量的训练数据,如果训练数据少可能无法训练出有效的神经网络。通常可以通过一些算法在已有的训练数据的基础上产生大量的相似的数据用于训练。例如可以将每一个图像平移一个像素,向上平移,向下平移,向左平移和向右平移都可以。

使用若干个网络的组合。创建若干个相同结构的神经网络,参数随机初始化,训练以后测试时通过他们的输出做一个投票以决定最佳的分类。其实这种Ensemble的方法并不是神经网络特有,其他的机器学习算法也用这种方法以提高算法的鲁棒性,比如Random Forests。

ImageNet图像分类

Alex Krizhevsky等人2012年的文章“ImageNet classification with deep convolutional neural networks”对ImageNet的一个子数据集进行了分类。ImageNet一共包含1500万张有标记的高分辨率图像,包含22,000个种类。这些图像是从网络上搜集的并且由人工进行标记。从2010年开始,有一个ImageNet的图像识别竞赛叫做ILSVRC(ImageNet Large-Scale Visual Recognition Challenge)。 ILSVRC使用了ImageNet中的1000种图像,每一种大约包含1000个图像。总共有120万张训练图像,5万张验证图像(validation images)和15万张测试图像(testing images)。该文章的方法达到了15.3%的错误率,而第二好的方法错误率是26.2%。

深度学习笔记(三 )Constitutional Neural Networks

这篇文章中使用了7个隐藏层,前5个是卷积层(有些使用了max-pooling),后2个是全连接层。输出层是有1000个单元的softmax层,分别对应1000个图像类别。

该CNN使用了GPU进行计算,但由于单个GPU的容量限制,需要使用2个GPU (GTX 580,分别有3GB显存)才能完成训练。

该文章中为了防止过度拟合,采用了两个方法。一是人工生成更多的训练图像。比如将已有的训练图像进行平移或者水平翻转,根据主成分分析改变其RGB通道的值等。通过这种方法是训练数据扩大了2048倍。二是采用Dropout技术。Dropout将隐藏层中随机选取的一半的神经元的输出设置为0。通过这种方法可以加快训练速度,也可以使结果更稳定。

深度学习笔记(三 )Constitutional Neural Networks

输入图像的大小是224X224X3,感知域的大小是11X11X3。第一层中训练得到的96个卷积核如上图所示。前48个是在第一个GPU上学习到的,后48个是在第二个GPU上学习到的。