【深度学习】卷积神经网络

讲卷积神经网络之前说说为什么能够进行分类识别?按照传统的SIFT,HOG算法都是先进行特征的提取过程,那么卷积神经网络怎么进行特征的提取呢?

下面,我们就开始吧!

先提一个小问题:“你是通过什么了解这个世界的?”

当一辆汽车从你身边疾驰而过,你是通过哪些信息知道那是一辆汽车?

“它的材质,速度,发动机的声响,还是什么?”

你可能说不清所以然,但是当你看到下图时,你会第一时间反应出来,“噢,车!

以下图片来源于:HTTPS://mp.weixin.qq.com/s/x6NIkzQSgvl0_rfGe7Cjqg

为什么你能猜对它?

“轮廓”!

- 对,我给你看了它的轮廓(相当于车的特征)

再给你一些七七八八,大小不一的图片,你总能猜对一些。

你是怎样做到的?

很简单

你读一张了图片  →交通交通找到了图片的特征  →交通交通  进而对图片做出了分类照片照片什么 


其实,CNN的工作原理也是这样。

先不考虑那些复杂的专有名词:什么卷积卷积),池化(),过滤器(过滤器)等等......统统抛到一边。

神经细胞网络做的就是下面3件事:

读取图片;

2.提取特征;

3.图片分类。

下面,我们逐一来看各步骤的细节。

1读取图片--2特征提取--3图片分类

如果是一张黑白图片,我们看到的,是这个样子的:

而在计算机的眼里,它看到的,是这个样子的:


好没有情趣......




这些数字是哪里来的?

因为图片是由一个又一个的像素点构成。(当你将图片无限放大,你能看到那些像素点)



而每一个像素点,都是由一个0〜255的数字组成。


所以,在计算机“看”来,一张图片,就是一个又一个的数字。


所以,我们第一步的工作,是将左上图的那只小狗,转换成右上图的那一行行数字。

幸运的是,目前在中,很多第三方库,如PIL / Matplotlib等,都可以实现这种转换,我们需要了解的是,后面的所有运算过程,基于都是右上图产品来完成的,至于具体的转换过程,不需要我们费心来做。

在文章开篇的例子中,我们知道,在识别一辆汽车的时候,可以将它的轮廓提取出来,从而判断出那是一辆车。

同样的,CNN 在识别图片时,也需要提取图像的特征。

细胞神经网络中,完成这一工作的小伙叫“ 卷积 ”。(希望你不要纠结这个极具个性的名字,它懂得原理的就

“卷积”在每次工作时,手里都会握着几把“ 过滤器 ”。


过滤器的作用是:寻找图片的特征

仍以小狗为例,过滤器会在图片上从头到尾“ 滑过 ”一遍

每滑到一个地方,就将该地方的图像特征提取出来。

那它是怎样提取的呢?

别忘了,在计算机的眼里,世界是这个样子的:


(为了简化问题,这里将像素值仅用01表示)

假设过滤器是这个样子的:


当橘色的过滤器在绿色矩形框中,缓慢滑过时,

我们用橘色过滤器中的每一个值,与绿色矩形框中的对应值相乘,再相加

有点儿拗口,直接看图:


结果“ 4 ”,就是我们从第一个橘色方框中,提取出的特征。

如果我们每次将橘色过滤器,向右,向下移动1格,则提取出的特征为:


你可能会问:

我知道绿色矩阵代表一张图片,是计算机“眼中”图片的样子。

但是,

经过橘色过滤器提取特征后,得到的粉色矩阵,那是什么?


我们从人类的视角,再重新审视一遍。

这次,我们回到之前的例子中。

仍以这张萌狗为例,它经过“过滤器”提取特征后,得到的是一张......哦,好吧......看起来有点儿模糊的图。


虽然图片模糊了,但是图片中的主要特征,已经被过滤器全部提取出来,单凭这么一张模糊的图,作为人类的我们,足以对它做出判断了。(谁敢说它是一只猫?!)

下面,我们再换几个过滤器试试。

这些就是经过过滤器提取后,得到的不同“ 特征图片 ”。

由此我们可以看出,采用不同的“过滤器”,能够提取出不同的图片特征。

那过滤器里的数值,该如何确定呢?


这就涉及到CNNs要做的工作了。每一个过滤器中的数值,都是算法自己学习来的,不需要我们费心去设置。


需要我们做的有:

① 设置过滤器的大小(用字母“F”表示)

上例中,我们的过滤器大小是3×3,即F=3

当然,你还可以设置成5×5,都是可以的。

只不过,需要注意的是:过滤器的尺寸越大,得到的图像细节就越少,最终得到的特征图的尺寸也更小。


② 设置过滤器滑动的步幅数(用字母“S”表示)

上例中,过滤器滑动的步幅是1,即每次过滤器向右或向下滑动1个像素单位。

当然,你也可以将步幅设置为2或更多,但是通常情况下,我们会使用S=1S=2


③ 设置过滤器的个数(用字母“K”表示)

上例中,我们分别给大家展示了4种过滤器。所以你可以理解为K=4,如下图:


当然,你可以设置任意个数。

再次强调:不要在意过滤器里面的数值,那是算法自己学习来的,不需要我们操心,我们只要把过滤器的个数设置好,就可以了。


所以,一张图片,在经过4种过滤器的提取后,会得到4种不同的特征图片:


实际上,这就是“卷积”小伙儿所做的工作。


从上面的例子我们能够看到,“卷积”输出的结果,是包含“宽、高、深3个维度的:


实际上,在CNNs中,所有图片都是包含有“宽、高、深”。

像输入的图片——萌狗,它也是包含3个维度,只不过,它的深度是1,所以在我们的图片中没有明显地体现出来:


所以,我们要记住,经过“卷积”层的处理后,图片含有深度,这个“深度”,等于过滤器的个数

例如,上面我们采用了4种过滤器,那么,输出的结果,深度就为4


④ 设置是否补零(用字母“P”表示)

何为“补零”?

上面的例子中,我们采用了3×3大小的过滤器,直接在原始图片滑过。

从结果中可以看到,最终得到的“特征图片”比“原始图片”小了一圈:

为什么会出现这种情况?

原因很简单:过滤器将原始图片中,每3*3=9个像素点,提取为1个像素点

所以,当过滤器遍历整个图片后,得到的特征图片会比原始图片更小。


当然,你也可以得到一个和原始图片大小一样的特征图,这就需要采用“在原始图片外围补零”的方法:


下面,我们来看看“补零”后的效果:


从图中可以看到,当我们在原始图片外围补上1圈零后,得到的特征图大小和原始图一样,都是5*5


你可能会问:


如何确定“补零”的圈数,才能保证图片大小一致?


假设你的过滤器大小为F,滑动步幅S=1,想要实现这一目标,补零的个数应为:

举个例子:

在上图中,因为我们使用的是3*3大小的过滤器,而且每次滑动时,都是向右或向下移动1格。

所以,为了使特征图片与原始图片保持一致,需要补零P=(3-1)/2=1,即在原始图片外围,补1圈零。


如果你使用的过滤器大小为5*5,那么补零P=(5-1)/2=2,即在原始图片外围,补2圈零。


当然,是否需要“补零”,由你自己来决定,“补零”并不是硬性规定。


 温馨提示:

假设原始图片的大小为W,当我们设置了

过滤器的大小(F)、滑动的步幅数(S)、以及补零的圈数(P)

实际上,得到的特征图片大小为:

所以,当我们设置这些超参数时,需要遵循一个原则,即“上面公式得到的结果,必须为一个整数”:


看懂了卷积神经网络的大概提取特征的过程吧,那现在就接着讲卷积神经网络的理论部分吧,看看这里面有什么技巧以及参数个数,连接数都是怎么计算的?

卷积神经网络是一个多层的神经网络,每层由多个二维平面组成,而每个平面由多个独立神经元组成。

       图:卷积神经网络的概念示范:输入图像通过和三个可训练的滤波器和可加偏置进行卷积,滤波过程如图一,卷积后在C1层产生三个特征映射图,然后特征映射图中每组的四个像素再进行求和,加权值,加偏置,通过一个小号型函数得到三个S2层的特征映射图。这些映射图再进过滤波得到C3层。这个层级结构再和S2一样产生S4。最终,这些像素值被光栅化,并连接成一个向量输入到传统的神经网络,得到输出。

       一般地,C层为特征提取层,每个神经元的输入与前一层的局部感受野相连,并提取该局部的特征,一旦该局部特征被提取后,它与其他特征间的位置关系也随之确定下来; 小号层是特征映射层,网络的每个计算层由多个特征映射组成,每个特征映射为一个平面,平面上所有神经元的权值相等特征映射结构采用影响函数核小的小号形函数作为卷积网络的激活函数,使得特征映射具有位移不变性。

       此外,由于一个映射面上的神经元共享权值,因而减少了网络自由参数的个数,降低了网络参数选择的复杂度。卷积神经网络中的每一个特征提取层(C-层)都紧跟着一个用来求局部平均与二次提取的计算层(S-层),这种特有的两次特征提取结构使网络在识别时对输入样本有较高的畸变容忍能力。

关于参数减少与权值共享

      上面聊到,好像CNN一个牛逼的地方就在于通过感受野和权值共享减少了神经网络需要训练的参数的个数。那究竟是啥的呢?

       下图左:如果我们有1000×1000像素的图像,有1百万个隐层神经元,那么他们全连接的话(每个隐层神经元都连接图像的每一个像素点),就有1000x1000x1000000 = 10 ^ 12个连接,也就是10 ^ 12个权值参数。然而图像的空间联系是局部的,就像人是通过一个局部的感受野去感受外界图像一样,每一个神经元都不需要对全局图像做感受,每个神经元只感受局部的图像区域,然后在更高层,将这些感受不同局部的神经元综合起来就可以得到全局的信息了局部感受野是有科学依据的,是科学家研究脑科学所得出的结论)这样,我们就可以减少连接的数目,也就是减少神经网络需要训练的权值参数的个数了如下图右:假如局部感受野是10×10,隐层每个感受野只需要和这10×10的局部图像相连接,所以1百万个隐层神经元就只有一亿个连接,即10 ^ 8个参数。比原来减少了四个0 数量级),这样训练起来就没那么费力了,但还是感觉很多的啊,那还有啥办法没?

 

       我们知道,隐含层的每一个神经元都连接10×10个图像区域,也就是说每一个神经元存在10×10 = 100个连接权值参数。那如果我们每个神经元这100个参数是相同的呢?也就是说每个神经元用的是同一个卷积核去卷积图像。这样我们就只有多少个参数?只有100个参数啊!!!亲!不管你隐层的神经元个数有多少,两层间的连接我只有100个参数啊!亲!这就是权值共享啊!同时有相同程度的位移,不变性旋转亲!这就是卷积神经网络的主打卖点啊!亲!(有点烦了,呵呵),也许你会问,这样做靠谱吗?为什么可行呢?这个......共同学习。注意这里权值共享不是局部连接的神经元权值相同,而是同一平面层的神经元型态权值相同(所以目前为止还只是提取了一个特征图,好戏在后面)

       好了,你就会想,这样提取特征也忒不靠谱吧,这样你只提取了一种特征啊?对了,真聪明,我们需要提取多种特征对不?假如一种滤波器,也就是一种卷积核就是提出图像的一种特征,例如某个方向的边缘。那么我们需要提取不同的特征,怎么办,加多几种滤波器不就行了吗?对了。所以假设我们加到100种滤波器,每种滤波器的参数不一样,表示它提出输入图像的不同特征,例如不同的边缘。这样每种滤波器去卷积图像就得到对图像的不同特征的放映,我们称之为特征图。所以100种卷积核就有100个特征图(这里的特征图的个数就相当于卷积层的深度)。这100个特征图就组成了一层神经元。到这个时候明了了吧。我们这一层有多少个参数了?100种卷积核X每种卷积核共享100个参数= 100×100 = 10K,也就是1万个参数。才1万个参数啊!亲!(又来了,受 !不了了),见下图右:不同的颜色表达不同的滤波器。

 

       嘿哟,遗漏一个问题了。刚才说隐层的参数个数和隐层的神经元个数无关,只和滤波器的大小和滤波器种类的多少有关。那么隐层的神经元个数怎么确定呢?它和原图像,也就是输入的大小(神经元个数),滤波器的大小和滤波器在图像中的滑动步长都有关!例如,我的图像是1000×1000像素,而滤波器大小是10x10,假设滤波器没有重叠,也就是步长为10,这样隐层的神经元个数就是(1000x1000)/(10x10)= 100x100个神经元了,假设步长是8,也就是卷积核会重叠两个像素,那么......我就不算了,思想懂了就好。注意了,这只是一种滤波器,也就是一个Feature Map的神经元个数哦,如果100个Feature Map就是100倍了。由此可见,图像越大,神经元个数和需要训练的权值参数个数的贫富差距就越大。

 

      需要注意的一点是,上面的讨论都没有考虑每个神经元的偏置部分。所以权值个数需要加1。这个也是同一种滤波器共享的。

      总之,卷积网络的核心思想是将:局部感受野,权值共享(或者权值复制)以及时间或空间亚采样这三种结构思想结合起来获得了某种程度的位移,尺度,形变不变性。

4)一个典型的例子说明

       一种典型的用来识别数字的卷积网络是LeNet-5(效果和纸张等见这)。当年美国大多数银行就是用它来识别支票上面的手写数字的。能够达到这种商用的地步,它的准确性可想而知。毕竟目前学术界和工业界的结合是最受争议的

      那下面咱们也用这个例子来说明下。

        LeNet-5共有7层,不包含输入,每层都包含可训练参数(连接权重)。输入图像为32×32大小。这要比MNIST数据库(一个公认的手写数据库)中最大的字母还大。这样做的原因是希望潜在的明显特征如笔画断电或角点能够出现在最高层特征监测子感受野的中心

        我们先要明确一点:每个层有多个Feature Map,每个Feature Map通过一种卷积滤波器提取输入的一种特征,然后每个Feature Map有多个神经元。

        C1层是一个卷积层(为什么是卷积?卷积运算一个重要的特点就是,通过卷积运算,可以使原信号特征增强,并且降低噪音),由6个特征图Feature Map构成。特征图中每个神经元与输入中5×5的邻域相连。特征图的大小为28 * 28,这样能防止输入的连接掉到边界之外(是为了BP反馈时的计算,不致梯度损失,个人见解).C1有156个可训练参数(每个滤波器5 * 5 = 25个单元参数和一个偏置参数,一共6个滤波器,共(5 * 5 + 1)×6 = 156个参数),共156 *(28 * 28)= 122304个连接。

       S2层是一个下采样层(为什么是下采样?利用图像局部相关性的原理,对图像进行子抽样,可以减少数据处理量同时保留有用信息),有6个14×14的特征图。特征图中的每个单元与C1中相对应特征图的2 * 2邻域相连接.S2层每个单元的4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。结果通过乙状结肠函数计算。可训练系数和偏置控制着乙状结肠函数的非线性程度。如果系数比较小,那么运算近似于线性运算,亚采样相当于模糊图像。如果系数比较大,根据偏置的大小亚采样可以被看成是有噪声的“或”运算或者有噪声的“与”运算。每个单元的2 * 2感受野并不重叠,因此S2中每个特征图的大小是C1中特征图大小的1/4(行和列各1/2).S2层有12个可训练参数和5880个连接。

图:卷积和子采样过程:卷积过程包括:用一个可训练的滤波器f x去卷积一个输入的图像(第一阶段是输入的图像,后面的阶段就是卷积特征map了),然后加一个偏置b x,得到卷积层C x。子采样过程包括:每邻域四个像素求和变为一个像素,然后通过标量W x + 1加权,再增加偏置b x + 1,然后通过一个sigmoid激活函数,产生一个大概缩小四倍的特征映射图S x + 1

       所以从一个平面到下一个平面的映射可以看作是作卷积运算,S-层可看作是模糊滤波器,起到二次特征提取的作用。隐层与隐层之间空间分辨率递减,而每层所含的平面数递增,这样可用于检测更多的特征信息。最后说说池化层的作用:1简化网络的计算的复杂度,2特征压缩特区主要特征(一般是取局部的最大值,相当于提取了重要信息,还有一种方式就是去局部平均值)。但是可能有人问,池化层压缩过程中可能影响网络的准确度,因此可以增加特征图的深度来弥补这里的深度一般通常取两倍。

       C3层也是一个卷积层,它同样通过5×5的卷积核去卷积层S2,然后得到的特征地图就只有10×10个神经元,但是它有16种不同的卷积核,所以就存在16个特征地图了这里需要注意的一点是:C3中的每个特征的地图是连接到S2中的所有6个或者几个特征地图的,表示本层的特征地图是上一层提取到的特征地图的不同组合(这个做法也并不是唯一的)。(看到没有,这里是组合,就像之前聊到的人的视觉系统一样,底层的结构构成上层更抽象的结构,例如边缘构成形状或者目标的部分)。

       刚才说C3中每个特征图由S2中所有6个或者几个特征映射组合而成。为什么不把S2中的每个特征图连接到每个C3的特征图呢?原因有2点。第一,不完全的连接机制将连接的数量保持在合理的范围内。第二,也是最重要的,其破坏了网络的对称性。由于不同的特征图有不同的输入,所以迫使他们抽取不同的特征(希望是互补的)。

组合方式如下:

         



      例如,存在的一个方式是:C3的前6个特征图以S2中3个相邻的特征图子集为输入接下来6个特征图以S2中4个相邻特征图子集为输入。然后的3个以不相邻的4个特征图子集为输入。最后一个将S2中所有特征图为输入。这样C3层有1516个可训练参数和151600个连接。

       S4层是一个下采样层,由16个5×5大小的特征图构成。特征图中的每个单元与C3中相应特征图的2 * 2邻域相连接,跟C1和S2之间的连接一样.S4层有32个可训练参数(每个特征图1个因子和一个偏置)和2000个连接。

       C5层是一个卷积层,有120个特征图。每个单元与S4层的全部16个单元的5×5邻域相连。由于S4层特征图的大小也为5 * 5(同滤波器一样),故C5特征图的大小为1 * 1:这构成了S4和C5之间的全连接之所以仍将C5标示为卷积层而非全相联层,是因为如果LeNet-5的输入变大,而其他的保持不变,那么此时特征图的维数就会比1 * 1大.C5层有48120个可训练连接。

        F6层有84个单元(之所以选这个数字的原因来自于输出层的设计),与C5层全相连。有10164个可训练参数。如同经典神经网络,F6层计算输入向量和权重向量之间的点积,再加上一个偏置。然后将其传递给S形函数产生单元我的一个状态。

      最后,输出层由欧式径向基函数(Euclidean Radial Basis Function)单元组成,每类一个单元,每个有84个输入。距离。输入离参数向量越远,RBF输出的越大。一个RBF输出可以被理解为衡量输入模式和与RBF相关联类的一个模型的匹配程度的惩罚项。用概率术语来说,RBF输出可以被理解为F6层配置空间的高斯分布的负对数似然。给定一个输入模式,损失函数应能使得F6的配置与RBF参数向量(即模式的期望分类)足够接近。这些单元的参数是人工选取并保持固定的(至少初始时候如此)。这些参数向量的成分被设为-1或1。虽然这些参数可以以-1和1等概率的方式任选,或者构成一个纠错码,但是被设计成一个相应字符类的7 * 12大小(即84)的格式化图片。这种表示对识别单独的数字不是很有用,但是对 别可打印的ASCII集中的字符串很有用。

      使用这种分布编码而非更常用的“N of 1”编码用于产生输出的另一个原因是,当类别比较大的时候,非分布编码的效果比较差。原因是大多数时间非分布编码的输出必须为0。这使得用乙状结肠单元很难实现。另一个原因是分类器不仅用于识别字母,也用于拒绝非字母。使用分布编码的RBF更适合该目标。因为与乙状结肠不同,他们在输入空间的较好限制的区域内兴奋,而非典型模式更容易落到外边。

        需要指出这些向量的成分是+1或-1,这正好在F6 sigmoid的范围内,因此可以防止sigmoid函数饱和。实际上,+ 1和-1是乙状结肠函数的最大弯曲的点处。这使得F6单元运行在最大非线性范围内。必须避免乙状结肠函数的饱和,因为这将会导致损失函数较慢的收敛和病态问题。

来自:HTTPS://blog.csdn.net/zouxy09/article/details/8781543

https://mp.weixin.qq.com/s/x6NIkzQSgvl0_rfGe7Cjqg