卷积神经网络是一种特殊的多层神经网络,它是deep learning中的一个算法,现在主要应用在图像处理领域中。
既然说它是deep learning中的一个算法,那么就需要有大量的数据来支持,作为一个深度的神经网络,参数动辄百万以上,如果样本数过小很容易造成overfitting。卷积神经网络可以自主的从原始的输入图像中学习到有用的(利于分类的,利于预测的) features,这样可以将它应用到很多不知道如何设计feature的场景中。
在普通的全连接神经网络下,假设我们现在有一个100*100的图像作为输入。在计算中我们将这个图像表示为一个100*100 = 10000大小的向量(数组),假如我们只有一个hidden layer,并且神经元数量与input layer数目相同,那么光从input layer到hidden layer就有10000*10000 = 10^8个参数。正如前面所说,要想训练出一个好的网络,这么多的参数很容易造成overfitting,减少参数势在必行,于是卷积神经网络应运而生。
卷积神经网络有两大杀器:
1. Local Connectivity Pattern(局部感知野)
所谓局部感知野,如果不好理解野字,你可以理解成局部感知模块或者把整个局部感知野理解成,稀疏连接网络。
2. Shared Weights(权值共享)
这两种方法都为减少神经网络参数做出了大贡献,下面我会详细介绍这两种方法。
计算机神经网络科学的初衷就是模拟人的神经网络,期望通过构建的计算机神经网络可以让计算机像人类一样思考,那么自然,对传统神经网络的改进也少不了进一步对人类神经网络的模仿。我们对外界事物的观察都是由局部到全局,但并不是每个像素每个像素的去认知,而是一块区域一块区域的去认识,通过这些区域得到局部信息,然后对这些局部信息的汇总,然后才得到整个全局的信息。
1. 这个也就是说,图像的像素之间也是局部的相关性较强,距离较远的像素之间相关性较弱。
2. 另一个启发来自于人类的视觉接收系统,视觉神经元只是接收局部信息的,也就是说每个神经元并不对全局进行响应。
左上图全连接神经网络,为了表示清晰,我只画了隐含层一个神经元与输入层的连接关系,其他的隐含层神经元都是与其一样的连接方式。而上面中间的和右边的是局部连接网络,一个是overlapping的局部感知,一个是无overlapping的局部感知。我假设每个隐含层神经元只感知两个输入的神经元构建而成的。也可以是3个,4个等等,这个参数后面我将详细叙说,主要和图片大小有一定的关系,和你想获得的feature的大小也有关系。现在为了更方便的画图与描述做了这个假设。
好,我们现在回到开始的那个假设,有一个100*100大小的图像作为输入,假如每个隐含层神经元只与其中10*10 = 100个像素相连在无overlapping的局部感知情况下,现在只需要(10000/(10*10) ) * (10*10) = 100*100 = 10^4个参数。
虽然我们已经大幅的减小的参数的数目,但对于一个庞大的神经网络里,这样数量级的参数还是太大了,我们需要进一步减少参数。
在刚刚构建的局部感知神经网络结构中,假设隐含层的所有神经元对应的100个像素这样的所有连接的权值都相同,那么就相当于只需要10*10 = 100个参数,简而言之就是隐含层不同的神经元拥有相同的权重。如果你还没有理解,那么下面两幅图应该就能很好的说明何为共享权值了。(不同颜色代表不同的权重,相同的颜色代表权重相同)
到这儿你应该已经知道什么是权值共享了,那么你可能要问了,我们这么做的理由是什么?
前面我们有说过深度学习可以自主的从原始图片中获得有用的feature。卷积神经网络中权值共享这个操作,可以看做是一种与位置无关的特征提取方法。也就是可以对原始的输入图像应用一个相同的特征。“这其中隐含的原理是:图像一部分的统计特性与其他部分是一样的。” 这个权值共享的操作其实就是将一个卷积核(滤波器)在图像上做卷积的过程,这个卷积核就是去筛选特征的。(绿色是原始图像,黄色是卷积核,红色是得到的是特征我们称之为卷积特征)
在说到权值共享的时候,我们说到一个卷积核(滤波器)肯定是无法充分的提取图像中的特征。那么怎么办呢?一个卷积核可以提取一种特征,我们可以很自然的想到多个卷积核就可以提取多种特征了吧。没错,使用多少个卷积核就可以学习到多少种卷积特征。右下图显示了使用两个卷积核对输入进行特征提取的过程。
因为我们的输入是幅图片,所以我们将经过卷积核提取出来的特征称之为“卷积特征图”,我们添加多少个卷积核,就会在卷积层产生多少个“卷积特征图”。理论上,我们可以用这些提取出来的特征去做分类或者回归了。但往往为了避免overfitting,提高模型的泛化能力,会在卷积层后,加一个叫做Pooling层的东西。什么是Pooling层?下面请听我详细道来。
所谓Pooling(池化)就是对不同位置的特征进行聚合的一种操作。聚合方法主要有两种:
1. 取一块区域的平均值
2. 取一块区域的最大值
通过这两种不同的聚合原则进行的操作我们区分为:
1. 平均池化(mean pooling)
2. 最大池化(max pooling)
与卷积核对图像的卷积操作相同,池化也可分为有overlapping的和无overlapping,在有overlapping的当中又可以通过规定每次移动的步长,确定了overlapping的大小。上图是无overlapping的pooling的表示。假如你已经从一张人脸图片中提取到鼻子这个特征,你其实并不关心这个特征位于图片的中心,偏左,或偏右,或者这个人比较调皮倒立着拍这张照片(旋转)。这些都不重要,重要的是我们已经可以提取出到这个特征。这就是引入pooling的另外一个好处,使得卷积神经网络具有局部区域内的平移或者旋转的一些不变性。
卷积特征经过池化,我们已然可以将这个“池化特征”作为从原始图片中学习到的特征输入到模型中进行分类了。但有人又要站出来说,这个特征还不够好,我们是否可以运用多个这样类似的结构去进行特征提取呢?下篇我们会讨论多层卷积。
小小的总结一下:原始图像经过多个卷积核卷积得到多个卷积特征,再经过池化层池化,得到池化特征,通常我们还会把池化特征经过一个激活函数进行非线性变化再输入到我们的分类器中。现在deep learning中大多都使用Relu这个激活函数,关于Relu我们稍后再谈。下面这个流程图就是卷积神经网络的基本结构了。
今天我们将会介绍 多层卷积。
在实际建模中,往往我们会使用多层卷积,也就是多次使用上面的这种流程,再输入到分类器(这个分类器可以是一个全链接的神经网络,也可以是maxsoft这种分类器,等等)中去训练。为什么我们要使用多层卷积结构呢? 记得有位大拿说过,一个不够深的神经网络对于深度学习是有害的。为尽可能的增加网络的深度,显而易见的方法就是应用多层卷积。大拿说的就是对的么?那我们来从问题本质来分析。对于我们图像识别领域而言,输入的图像,它的特征的层次结构是与生俱来的。从原始输入的 像素 开始,到由像素构成的简单的 线条 和 纹理 ,再到由线条与纹理构成了 图案 ,最后是由各个图案构成图像中的 物体 。
整个过程通过原始输入找到浅层特征,在对浅层特征进一步挖掘找到中层特征,最后一步步获得高层特征。但想要从原始输入直接找到高层特征无疑是行不通的。简而言之,单层的卷积学习到的往往是浅层的特征,增加卷积的层数才有可能学习到更高层的特征。对于图像的识别,往往是需要的是高层特征。引用一段别人的话来形象的解释:
“如果有一幅图片,一个像素有一个人那么大,当你距离图片50cm去看图片,你只能看到几个像素,所以你是看不出来这个图片是个什么鬼的。站到很远很远地方再看它,反而能看得清全貌了。神经网络的层数多起来,就像你站得更远去看这个图片一样,是观察粒度上的改变。而更宏观的粒度层面是需要底下更微观的粒度层面一层一层传递和堆砌出来的。”
现在我们已经构建了一个多层卷积神经网络了。理论上它已经可以work了,但还有一些细节我们需要补充,下篇将介绍 激活函数 和 Dropout Layer。
ReLu的全称是Rectified layer units,它是一层使用非饱和激活函数的神经元。神经网络通常使用sigmoid 和 tanh 作为非线性激活函数,它确实比早期的线性激活函数有好的多的效果。但在深度神经网络中,如果不使用pre-traning,会导致gradient vanishing problem (梯度消失,无法收敛)。后来,两位神经学家从脑神经元接收信号的角度考虑,模拟出了更精确的激活函数模型,就是ReLu激活函数:
还有一种ReLu的平滑版本,叫做SoftPlus:
这个是不是很眼熟啊? 对了!这个softplus的导数就是我们熟悉的sigmoid函数。
Relu激活函数主要有以下两个特点:
1.单侧抑制
2.稀疏激活性 (x负轴完全没有激活)
“
在神经科学方面,除了新的激活频率函数之外,神经科学家还发现了神经元的稀疏激活性。
2001年,Attwell等人基于大脑能量消耗的观察学习上,推测神经元编码工作方式具有稀疏性和分布性。
2003年,Lennie等人估测大脑同时被激活的神经元只有1~4%,进一步表明神经元工作的稀疏性。
从信号方面来看,即神经元同时只对输入信号的少部分选择性响应,大量信号被刻意的屏蔽了,这样可以提高学习的精度,更好更快地提取稀疏特征。
从这个角度来看,在经验规则的初始化W之后,传统的Sigmoid系函数同时近乎有一半的神经元被激活,这不符合神经科学的研究,而且会给深度网络训练带来巨大问题。
Softplus照顾到了新模型的前两点,却没有稀疏激活性。因而,校正函数
”
深度神经网络的致命问题就是gradient vanishing。上面说到在多层神经网络中使用sigmoid函数会导致梯度消失,无法收敛。原因就是,当神经网络进行误差反向传播梯度时,各层都要乘以激活函数的一阶导数
Grad = Error*Sigmoid’(x)*x,显而易见,经过每一层,Error都是成指数衰减,一旦神经网络层数太多的时候,梯度就会不停衰减直至消失,高层(靠近输出层)训练的比较好,而低层(靠近输入层)几乎由于梯度消失无法训练。神经网络的正向传播又是从低层开始的,高层再怎么训练也会被低层搞乱,使得低层学不动,高层在乱学,导致整个网络退化。
而ReLu激活函数的梯度为1,而且只有在x右半轴才饱和,这样使梯度可以很好的反向传播中传递,不但提高了网络的训练速度也避免了因为梯度消失导致的网络退化。
ReLu的使用,使网络引入了稀疏性并且大大缩短了学习周期,Deep Learning中大部分激活函数都应该选择ReLu。在Theano中,可以直接使用T.maximum(0,x)来实现( 用T.max(0,x)不能求导)。
其实Dropout是一种特殊的正则化方法,不像L1和L2(两种通用正则化方法),它不用依靠修正cost function来实现,它直接修正神经网络本身。Dropout的工作原理,简而言之就是随机的不让神经网络中某些神经元激活,可以理解成这些神经元暂时(临时)不属于网络结构中的一部分,但是该神经元的参数依旧要保存下来,因为下一次该神经元有可能是激活状态。下图形象对比了有无Dropout的情况。
我们可以自由的去选择禁止激活神经元的数量,70%,50%,30%等等,上图的Dropout禁止的数量是当前层神经元数目的1/3。Dropout可以看作是平均模型的一种(一种in place平均,当取50%时),它在深度神经网络中有很好的泛化能力,可以有效的减少overfitting。
加入了ReLu激活函数和Dropout,相信我们的卷积神经网络将会由更好的效果。下一篇让我们来做一下总结吧。
1. Deep Learning是全部深度学习算法的总称,卷积神经网络是深度学习算法在图像处理领域的一个应用。
2. Fully Connection神经网络最大的缺陷在于很难提取到有用的特征而Deep Neural Networks能够自主地从数据上学到有用的feature。特别适合在一些不知道如何设计feature的场合。
3. Deep Learning强大的地方就是可以利用网络中间某一层的输出当做是数据的另一种表达,从而可以将其认为是经过网络学习到的特征。基于该特征,可以进行进一步的操作。
4. 卷积神经网络的局部感知野网络结构降低了网络的复杂度,减少了权值的数量。
5. 卷积神经网络的权值共享结构,由于同一特征映射面上的神经元权值相同,所以网络可以并行学习。
6. 卷积神经网络是为识别图像而特殊设计的一个多层感知器,这种网络结构对平移、比例缩放、倾斜或者其他形式的变形具有高度不变性。
7. ReLu的使用,使得网络可以自行引入稀疏性。这一做法,等效于无监督学习的预训练。
8. 所有的权重都应该用一些不同的小随机数进行初始化。
9. 多层神经网络初始化隐含层不能简单置零。这样会很容易找到局部最小值。
10. 每个DL都有众多的参数,少量数据无法将参数训练充分。
1. 池化矩阵一般为2*2,对于非常大的图像可以使用4*4。如果取值过大,可能会损失掉太多的信息。
2. 如果网络的最后一层是softmax分类器的话似乎其前一层就不能用ReLU。
3. 无需在cost function里加入正则项,因为CNN的权重共享相同于自带某种正则化。(此点道理上说的通,还需详细考究)
4. Deep Learning中大部分激活函数应该选择ReLu。
5. 使用带momentum的Nesterov's Accelerated Gradient Descent方法可以更快的收敛。
6. Dropout一定要用!
7. 图片的augmentation一定要做, 这是你与别人拉开差距的方式之一。
8. 有些时候可以对图片进行适当的手动裁剪。
9. 参数的继承可以让你有更多的时间去调整模型。(参数继承也可理解是监督式的pre-training)
初窥卷积神经网络,只会使用Theano, Lasagne, Nolearn, Caffe, 这些库构建卷积神经网络。有机会自己写遍整个流程会对卷积神经网络有更清晰的认知吧
CNN中主要有三种层,分别是:卷积层、池化层和激活层。
卷积层使用卷积核和图片窗口相乘,并使用梯度下降法去优化卷积核。
池化层使用最大值或者均值来描述一个图形窗口。
激活层使用一个激活函数将输入压缩到一个范围中,典型的[0,1][-1,1]。