卷积神经网络(CNN)简介

卷积神经网络(CNN)简介

微信公众号:幼儿园的学霸
个人的学习笔记,关于OpenCV,关于机器学习, …。问题或建议,请公众号留言;

目录

入门

回顾上一篇文章,以及之前的2篇关于神经网络的介绍,我们想想为什么DNN在训练后能够正确地分类?那肯定是它学到了东西,学到什么东西呢?它学到了图片中的某些空间结构,不同数字它们的空间结构肯定是不一样的,而这样的空间结构就是由像素点与像素点之间的关系形成。我们再仔细看DNN输入层和第一个隐藏层,发现它对我们输入的784个像素点是同等对待的,也就是说它此时并没有考虑像素点与像素点之间的关系。有没有一个好点的模型能够考虑到这点呢?那就是CNN(卷积神经网络Convolutional Neural Networks, CNN)

CNN有三个基本思想,局部感受野(local receptive fields)、 权值共享(shared weights) 、池化(pooling)

局部感受野

刚刚我们在DNN中是把输入层784个神经元排成了一条长线,这里我们还原图片原来的样子(28*28), 如下图所示:

DNN中,我们会把输入层的每个神经元都与第一个隐藏层的每个神经元连接(看上图)。而在CNN中我们这样做的:第一个隐藏层的神经元只与局部区域输入层的神经元相连。下图就是第一个隐藏层的某个神经元与局部区域输入层的神经元相连的情况。


这里的局部区域就是局部感受野,它像一个架在输入层上的窗口。你可以认为某一个隐藏层的神经元学习分析了它”视野范围“(局部感受野)里的特征。图中一个隐藏层的神经元有5*5个权值参数与之对应。

我们移动这样一个窗口使它能够扫描整张图,每次移动它都会有一个不同的节点与之对应。我们从输入层左上角开始,如下

然后,我们一个像素往右滑动一个像素,如下

以此类推可以形成第一个隐藏层,注意我们的图片是28*28的,窗口是5*5的,可以得到一个(28-5+1) * (28-5+1) =24*24个神经元的隐藏层.

这里我们的窗口指滑动了一个像素,通常说成一步(stride),也可以滑动多步,这里的stride也是一个超参,训练是可以根据效果调整,同样,窗口大小也是一个超参。

权值共享

上一节中提到一个隐藏层的神经元有5*5个权值参数与之对应。这里要补充下,这24*24个隐藏层的神经元它们的权值和偏移值是共享的 用公式描述下:
σ ( b + ∑ l = 0 4 ∑ m = 0 4 w l , m a j + l , k + m ) \sigma(b+\sum_{l=0}^4\sum_{m=0}^4 w_{l,m}a_{j+l,k+m}) σ(b+l=04m=04wl,maj+l,k+m)
σ表示的是激活函数,如sigmod函数等,b表示偏置(bias),w就是5*5个共享权值矩阵,我们用矩阵a表示输入层的神经元,ax,y表示第x+1行第y+1列那个神经元(注意,这里的下标默认都是从0开始计的,a0,0表示第一行第一列那个神经元)所以通过矩阵w线性mapping后再加上偏移值就得到公式中括号里的式子,表示的是隐藏层中第j+1k+1列那个神经元的输入。有点晕的话就参照上面的图,分别表示j=k=0的情况,j=0,k=1. 最后加上激活函数就表示该隐藏神经元的输出了。这部分原理和DNN是一样的,如果把w改成28 *28的矩阵就变成了全连接,就是DNN了。

如果对上面公式进行简化,可以如下表示:
a 1 = σ ( w ∗ a 0 + b ) a^1 = \sigma(w∗a^0+b) a1=σ(wa0+b)
a1表示隐藏层的输出,a0表示隐藏层的输入,而表示卷积操作(convolution operation) 这也正是卷积神经网络名字的由来

权值共享的理解:

神经网络处理图像的参数很多,例如一幅100*100的图片有100个神经元,则共有参数(100*100*100)个参数,太多了,假如一个神经元的感受野是10x10,每个神经元只需要和10*10的局部图像连接,则每个神经元对于局部图像的参数是10*10+1(包括偏置项b),但是全局图像是100*100,10*10的只是局部图像,如果全局图像中各个局部图像之间权值共享的话,即10*10+1个参数在不同局部图像上参数应用相同的话,则在全局图像上通过全局共享则全局只需要10*10+1个参数;然而如果有1000个神经元,那么参数数量是1000*(10*10+1),还是很多,所以要是所有的神经元都共享这(10*10+1)个参数的话,神经元再多参数还是(10*10+1),所以通过权值共享之后,无论图像再大,神经元个数再多参数都是(感受野大小+1)个参数。

由于权值共享,窗口移来移去还是同一个窗口,也就意味着第一个隐藏层所有的神经元从输入层探测(detect)到的是同一种特征(feature),只是从输入层的不同位置探测到(图片的中间,左上角,右下角等等),必须强调下,一个窗口只能学到一种特征!另外,窗口还有其他叫法:卷积核(kernal),过滤器(filter)。我们在做图像识别时,神经网络仅学习一个特征肯定是不够的,我们想要学习更多的特征,就需要更多的窗口。如果用三个窗口的话如下图:

窗口与窗口间的w和b是不共享的,三个窗口就表示有三个w矩阵和三个偏移值b,结果是从整张图片的各个位置学到三种不同的特征。

通过权值共享,可以减少参数数量,使得CNN可以依靠更少的参数来获得和DNN相同的效果,更少的参数就意味着更快的训练速度,这可是谁都想要的。

池化

CNN还有一个重要思想就是池化(Pooling),池化层通常接在卷积层后面。池化这个词听着就很有学问,其实引入它的目的就是为了简化卷积层的输出。通俗地理解,池化层也在卷积层上架了一个窗口,但这个窗口比卷积层的窗口简单许多,不需要w,b这些参数,它只是对窗口范围内的神经元做简单的操作,如求和,求最大值,把求得的值作为池化层神经元的输入值,如下图,这是一个2*2的窗口

值得注意的是,我们此时的窗口每次移动两步,采用的是求最大值的方法,所有称之为max-pooling,刚刚卷积层含有24*24个神经元,经过池化后到池化层就是12*12个神经元。通常卷积层的窗口是多个的,池化层的窗口也是多个的。简单来说,卷积层用一个窗口去对输入层做卷积操作,池化层也用一个窗口去对卷积层做池化操作。但是注意这两个操作的本质区别。下面来看一个用三个卷积窗口和跟随其后的池化窗口长啥样。

怎么理解max-pooling呢?由于经过了卷积操作,模型从输入层学到的特征反映在卷积层上,max-pooling做的事就是去检测这个特征是否在窗口覆盖范围的区域内。这也导致了,它会丢失这种特征所在的精准位置信息,所幸的是池化层可以保留相对位置信息。而后者相比而言比前者更重要。不理解上面的话也没关系,但是需要记住池化层一个最大的好处:经过池化后,大大减少了我们学到的特征值,也就大大减少了后面网络层的参数(上图可以看出池化层的神经元数明显少于卷积层神经元数)。

max-pooling技术只是池化技术的一种,还有一种比较常用的是L2-pooling,与max-pooling唯一的区别就是在池化窗口扫过的区域里做的操作不是求最大值,而是所有神经元平方后求和再开根号,这和我们L2正则对权值参数的操作是一样的。实际操作中,这两种方式都是比较常用的。池化操作方式的选择也是我们调参工作的一部分,我们可以根据validation data集来调节,选择更好的池化操作。

总览

介绍完CNN的三个几本思想概念后我们把它串起来看下。

从左往右依次是输入层,卷积层,池化层,输出层。输入层到卷积层,卷积层到池化层已经详细介绍过了。池化层到输出层是全连接,这和DNN是一样的。

整体上CNN的网络架构,其实和DNN很相似,都是一层一层组合起来的,层与层之间的行为也是有对应的权值w和偏移值b决定的,并且它们的目的也是一致的:通过training data来学习网络结构中的w和b,从而能把输入的图片正确分类。很简单吧。

到此为之,CNN的基本原理大致介绍完毕了,如果只需对CNN做大致了解的话上面的内容我想应该足够了。

CNN基本模块

CNN由输入和输出层以及多个隐藏层组成,隐藏层可分为卷积层,池化层、激活层和全连接层。

输入层

CNN的输入一般是二维向量,可以有高度,比如,RGB图像

卷积层

卷积层是CNN的核心,层的参数由一组可学习的滤波器(filter)或内核(kernels)组成,它们具有小的感受野,延伸到输入容积的整个深度。 在前馈期间,每个滤波器对输入进行卷积,计算滤波器和输入之间的点积,并产生该滤波器的二维激活图(输入一般二维向量,但可能有高度(即RGB))。 简单来说,卷积层是用来对输入层进行卷积,提取更高层次的特征。
卷积过程
卷积过程

现在停下来好好理解下上面的计算是怎么完成的。我们用橙色的矩阵在原始图像(绿色)上滑动,每次滑动一个像素(也叫做“步长”(stride)),在每个位置上,我们计算对应元素的乘积(两个矩阵间),并把乘积的和作为最后的结果,得到输出矩阵(粉色)中的每一个元素的值。注意,3x3 的矩阵每次步长中仅可以“看到”输入图像的一部分。
在CNN的术语中,3x3 的矩阵叫做“滤波器(filter)”或者“核(kernel)”或者“特征检测器(feature detector)”,通过在图像上滑动滤波器并计算点乘得到矩阵叫做“卷积特征(Convolved Feature)”或者“激活图(Activation Map)”或者“特征图(Feature Map)”。记住滤波器在原始输入图像上的作用是特征检测器。

从上面图中的动画可以看出,对于同样的输入图像,不同值的滤波器将会生成不同的特征图。或者,不同的步长时,特征图的大小也不相同。

下表中,我们可以看到不同滤波器对上图卷积的效果。正如表中所示,通过在卷积操作前修改滤波矩阵的数值,我们可以进行诸如边缘检测、锐化和模糊等操作 —— 这表明不同的滤波器可以从图中检测到不同的特征,比如边缘、曲线等。
不同特征提取

另一个理解卷积操作的好方法是看下面这张图的动画:
提取不同特征
滤波器(红色框)在输入图像滑过(卷积操作),生成一个特征图。另一个滤波器(绿色框)在同一张图像上卷积可以得到一个不同的特征图。注意卷积操作可以从原图上获取局部依赖信息。同时注意这两个不同的滤波器是如何从同一张图像上生成不同的特征图。记住上面的图像和两个滤波器仅仅是我们上面讨论的数值矩阵。
在实践中,CNN 会在训练过程中学习到这些滤波器的值(尽管我们依然需要在训练前指定诸如滤波器的个数、滤波器的大小、网络架构等参数)。我们使用的滤波器越多,提取到的图像特征就越多,网络所能在未知图像上识别的模式也就越好。


卷积过程,和OpenCV中的滤波(filter2D)函数过程是不是相当一致啊。


在进行卷积运算时,输入矩阵的边缘会比矩阵内部的元素计算次数少,且输出矩阵的大小会在卷积运算中相比较于输入变小。因此,可在输入矩阵的四周补零,称为padding,其大小为P。比如当P=1时,原5*5的矩阵如下,蓝色框中为原矩阵,周围使用0作为padding。
填充-padding
如下为对图片进行0扩充后的卷积过程:
0扩充卷积结果

特征图的大小(卷积特征)由下面三个参数控制,我们需要在卷积前确定它们:

  • 深度(Depth):深度对应的是卷积操作所需的滤波器个数。在下图的网络中,我们使用三个不同的滤波器对原始图像进行卷积操作,这样就可以生成三个不同的特征图。你可以把这三个特征图看作是堆叠的 2d 矩阵,那么,特征图的“深度”就是三。
  • 步长(Stride):步长是我们在输入矩阵上滑动滤波矩阵的像素数。当步长为 1 时,我们每次移动滤波器一个像素的位置。当步长为 2 时,我们每次移动滤波器会跳过 2 个像素。步长越大,将会得到更小的特征图。
  • 零填充(Zero-padding):有时,在输入矩阵的边缘使用零值进行填充,这样我们就可以对输入图像矩阵的边缘进行滤波。零填充的一大好处是可以让我们控制特征图的大小。使用零填充的也叫做泛卷积,不适用零填充的叫做严格卷积。

非线性简介(ReLLU)

在上面图中,在每次的卷积操作后都使用了一个叫做ReLU的操作。ReLU 表示修正线性单元(Rectified Linear Unit),是一个非线性操作。它的定义如下所示:
ReLU定义
ReLU 是一个元素级别的操作(应用到各个像素),并将特征图中的所有小于 0 的像素值设置为零。ReLU 的目的是在 ConvNet 中引入非线性,因为在大部分的我们希望 ConvNet 学习的实际数据是非线性的(卷积是一个线性操作——元素级别的矩阵相乘和相加,所以我们需要通过使用非线性函数 ReLU 来引入非线性。
其他非线性函数,比如 tanh 或者 sigmoid 也可以用来替代 ReLU,但 ReLU 在大部分情况下表现是更好的。

池化层

在卷积层之后,通常在CNN层之间添加池化层。池化的功能是不断降低维数,以减少网络中的参数和计算次数。这缩短了训练时间并控制过度拟合。
最常见的池类型是max pooling(最大值池化),它在每个窗口中占用最大值。需要事先指定这些窗口大小。这会降低特征图的大小,同时保留重要信息。
Max Pooling主要的好处是当图片整个平移几个Pixel的话对判断上完全不会造成影响,以及有很好的抗杂讯功能。
池化层示意图一
池化层示意图二
池化函数可以逐渐降低输入表示的空间尺度。特别地,池化:

  • 使输入表示(特征维度)变得更小,并且网络中的参数和计算的数量更加可控的减小,因此,可以控制过拟合
  • 使网络对于输入图像中更小的变化、冗余和变换变得不变性(输入的微小冗余将不会改变池化的输出——因为我们在局部邻域中使用了最大化/平均值的操作。
  • 帮助我们获取图像最大程度上的尺度不变性(准确的词是“不变性”)。它非常的强大,因为我们可以检测图像中的物体,无论它们位置在哪里。

NOTE:最大值池化是不是有点类似于opencv中的图像形态学操作–膨胀操作呢,当然,膨胀操作后图像尺寸未变(膨胀时,图像进行了padding,池化时没有padding),但是算法流程是一致的,感兴趣的可以看下我之前关于图像形态学操作的文章。想一想,这些还是挺有意思的哈。
更进一步感兴趣的可以翻一下opencv图像膨胀的源码,看一下里面算法实现及如何加速算法运行减少时间消耗的,这个在自己编写代码时可能会用到。哎,有点遗憾,我用opencv写了一个实现池化操作的函数,但是运行时间明显比opencv要慢,有机会的话我要去好好看一下了。


全连接层

基本上全连接层的部分就是将之前的结果平坦化之后接到最基本的神经网络了。
全连接层是传统的多层感知器,在输出层使用的是 softmax 激活函数(也可以使用其他像 SVM 的分类器)。“全连接(FullyConnected)”这个词表明前面层的所有神经元都与下一层的所有神经元连接。
卷积和池化层的输出表示了输入图像的高级特征。全连接层的目的是为了使用这些特征把输入图像基于训练数据集进行分类。比如,在下面图中我们进行的图像分类有四个可能的输出结果(注意下图并没有显示全连接层的节点连接)。
全连接进行分类
除了分类,添加一个全连接层也(一般)是学习这些特征的非线性组合的简单方法。从卷积和池化层得到的大多数特征可能对分类任务有效,但这些特征的组合可能会更好。

从全连接层得到的输出概率和为1。这个可以在输出层使用softmax作为激活函数进行保证。softmax 函数输入一个任意大于0值的矢量,并把它们转换为零一之间的数值矢量,其和为一。

第一个全连接层的输入是由卷积层和子采样层进行特征提取得到的特征图像。最后一层输出层是一个分类器,可以采用逻辑回归,Softmax回归甚至是支持向量机(SVM)对输入图像进行分类。得到的激活值即卷积神经网络提取到的图片特征。

总结

CNN是一种特殊的深层的神经网络模型,它的特殊性体现在两个方面,一方面它的神经元的连接是非全连接的,另一方面同一层中某些神经元之间的连接的权重是共享的(即相同的)。它的非全连接和权值共享的网络结构使之更类似于生物神经网络,降低了网络模型的复杂度(对于很难学习的深层结构来说,这是非常重要的),减少了权值的数量。

CNN是一种深度的监督学习下的机器学习模型,具有极强的适应性,善于挖掘数据局部特征,提取全局训练特征和分类,它的权值共享结构网络使之更类似于生物神经网络,在模式识别各个领域都取得了很好的成果。

在文章中,我简单的对CNN进行了介绍,跳过了一些细节(主要是我也处于学习过程),但希望本篇文章可以让你对它们有一定的了解

参考链接

  1. http://blog.jobbole.com/113819/
  2. https://mlnotebook.github.io/post/CNN1/


下面的是我的公众号二维码图片,欢迎关注。
图注:幼儿园的学霸

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值