前言
卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层、全连接层组成,即INPUT(输入层)-CONV(卷积层)-RELU(激活函数)-POOL(池化层)-FC(全连接层)
输入层
在CNN中一般输入的是图像数据,如图中的最左边的图片假设就是我们需要输入的,假设其是‘28×28×3’(三维矩阵),分别对应‘h×w× d’(‘height× width× depth’),其中对于图片输入来说通常是以RGB三通道的形式输入,所以d通常是3,如下图中的第二张图片就是后面三个通道图片相叠加而来。
卷积层
卷积层是CNN的核心部分之一,也是实现卷积运算的重要组成部分。我们可以将卷积层看作是一个滤波器,它将输入数据进行卷积运算,提取出其中的特征信息。卷积层中的每一个神经元都只与输入数据的一小部分相连,这个小部分称为卷积核或者滤波器。卷积核的大小通常比输入数据小,但是它可以在数据上滑动,从而覆盖到整个数据上,这样就可以提取出数据中的局部特征。卷积层中需要学习的参数就是卷积核的权重。
作用:用它来进行特征提取,如下:
输入图像是32×32×3,3是它的深度(即R、G、B),卷积层是一个5×5×3的filter。
这里注意:
1、感受野的深度必须和输入图像的深度相同。通过一个filter与输入图像的卷积可以得到一个28×28×1的特征图(具体计算公式会在下文讲解),
2、上图出现了一蓝一绿的特征图,代表是用了两个不同的filter得到了两个特征图;
我们通常会使用多层卷积层来得到更深层次的特征图。如下:
卷积过程详细图解
卷积层是如何工作的呢?我们先给定一个简单的例子,如下图所示:
假设我们输入的是5×5×1的图像(蓝色部分),图像中深色部分右下角那个3×3×1部分是我们定义的一个卷积核(简单来说可以看做一个矩阵形式运算器),通过原始输入图像和卷积核做运算可以得到绿色部分的结果(即特征图),怎么样的运算呢?实际很简单就是我们看左图中深色部分,处于中间的数字是图像的像素,处于右下角的数字是我们卷积核的数字,只要对应相乘再相加就可以得到结果。例如图中‘3×0+1×1+2×2+2×2+0×2+0×0+2×0+0×1+0×2=9’
当输入图像的depth > 1时,计算如下动图:
图中输入可以认为是一个7×7×3的图像,划分成三个通道图(对应R、G、B),每个通道图都有一个属于自己通道的卷积核,在计算前先介绍一下概念。
步幅(步长/stride )
在动图中我们可以看到每个通道图的深蓝色框(局部感受野)在与积核做完一次运算之后会按一定的采样间隔移动,然后继续进行卷积运算,我们称该采样间隔为步幅。
通俗来讲就是我们的filter在数据上每次移动的距离,此处stride =2,即深蓝色框卷与积核做完一次运算之后会移动2列或2行。
设置步幅的目的是希望减小输入参数的数目,减少计算量。
填充(padding)
padding:在输入特征图的高和宽的两侧填充元素(通常是0元素,动图中表现为输入矩阵的灰色部分),使得输出和输入的特征图的尺寸相同。
为什么要设置padding:
1、如果没有padding,每次进行卷积后,原始图像的尺寸就会越来越小,导致没有办法设计层数足够多的深度神经网络。
2、在动图中浅蓝色部分是输入图像数据,灰色部分是填充,在卷积过程中我们可以看到有些部分被多次进行卷积运算,如动图中第一个通道图中第一次深蓝色框与第二次深蓝色框的重叠部分[0,1,1],而我们希望每个输入特征图的每一块都能作为卷积窗口的中心,防止丢失图像边缘信息,因此对输入特征图进行填充。
一般有
Filter=3 => zero pad with 1
Filter=5 => zero pad with 2
Filter=7=> zero pad with 3,边界宽度是一个经验值
depth > 1时卷积运算:
①图中最左边有三个7×7的输入矩阵(depth=3时的三个通道图),分别在这三个通道图中进行采样,采样大小与filter一致,表现为动图中深蓝色框部分,然后与filter进行卷积运算
②将三个深蓝色框部分与filter进行卷积运算后的结果进行求和,最后再加上偏置项b,得到特征图。如图中所示,filter w0的第一层深度(即W0下方第一个矩阵)和输入图像的第一次蓝色方框中对应元素相乘再求和得到0,其他两个深度(第二、第三个举着)分别得到2,0,则有0+2+0+1=3即图中右边特征图的第一个元素3.,卷积过后输入图像的蓝色方框再滑动,stride(步长)=2
③如上图,完成卷积,得到一个332的特征图,输出(output)侧有两个特征图意味着我们设置输出的depth=2,(即有depth层卷积核,比如图中就有FilterW0和FilterW1,这意味着我们的卷积核数量就是输入depth的个数乘以输出depth的个数(图中就是3*2=6个))。
注:
在tensorflow中:
padding = 'same’表示进行填充,填充的值由算法内部根据卷积核大小计算,目的是让输出尺寸和输入相等。
padding = 'valid’表示不进行填充,即是 padding=0,只使用有效的窗口位置,这是默认的选项。
注意padding='same’目的是让输出尺寸和输入尺寸相等,但前提是步幅=1,步幅若不是1,那么输出尺寸跟输入尺寸肯定是不一样
一般来说,如果在高的两侧一共填充Ph行,在宽的两侧一共填充Pw列,也就是说,输出的高和宽会分别增加
Ph和Pw。
在很多情况下,我们会设置Ph = filter_size - 1 和Pw = filter_size - 1,如上述动图中filter_size =3 ,那么我们可以看到在左右两列或者上下两列共填充了两层进去,来使输入和输出具有相同的高和宽。这样会方便在构造网络时推测每个层的输出形状。假设这里filter_size 是奇数,我们会在高的两侧分别填充Ph /2行,如果filter_size 是偶数,一种可能是在输入的顶端一侧填充Ph /2行,而在底端一侧填充Ph /2 - 1 行。在宽的两侧填充同理。
卷积神经网络经常使用奇数高宽的卷积核,如1、3、5和7,所以两端上的填充个数相等。对任意的二维数组X,设它的第i行第j列的元素为X[i,j]。当两端上的填充个数相等,并使输入和输出具有相同的高和宽时,我们就知道输出Y[i,j]是由输入以X[i,j]为中心的窗口同卷积核进行互相关计算得到的。
卷积运算后特征图的大小计算方法
输入为5×5×3,filter为3×3×3,在zero pad 为1,则加上zero pad后的输入图像为7×7×3,则卷积后的特征图大小为3×3×1((5-3+2)/2+1),与输入图像一样;
计算公式
假设输入大小为W1×H1×D1 、卷积核大小为F×F 、卷积核个数为 K 、步长为S 、边界填充为P
则输出特征图大小为
注:①这里的除法为向下取整,这个原则实现的方式是,只在蓝框完全包括在图像或填充完的图像内部时,才对它进行运算。如果有任意一个蓝框移动到了外面,就不进行相乘操作
②若无填充则去掉公式中的”2P“
③计算机视觉中 f 通常是奇数,一般有两个原因:
如果是一个偶数,那么你只能使用一些不对称填充。只有f是奇数的情况下,Same卷积才会有自然的填充
第二个原因对于一个奇数维过滤器,比如3×3或者5×5的,它就有一个中心点。有时在计算机视觉里,如果有一个中心像素点会更方便,便于指出过滤器的位置
④卷积层的输出形状由输入形状和卷积核窗口形状决定。填充和步幅。它们可以对给定形状的输入和卷积核改变输出形状。
卷积运算参数量计算
在深度学习中,卷积层的参数量计算公式为:params = channels_{out} * (kernel_{w} * kernel_{h} * channels_{in}) + bias。其中,channels_{out}表示输出通道数,kernel_{w}和kernel_{h}表示卷积核的宽度和高度,channels_{in}表示输入通道数,bias表示偏置项。
池化层(pooling )
对输入的特征图进行压缩,一方面使特征图变小,降低卷积层输出的特征向量,简化网络计算复杂度;一方面进行特征压缩,提取一定区域的主要特征,并减少参数数量,防止模型过拟合
池化操作一般有两种,一种是平均池化(Avy Pooling),一种是最大池化(max Pooling),这里主要讲诉max Pooling
如图采用一个2×2的filter,max pooling是在每一个区域中寻找最大值,这里的stride=2,最终在原特征图中提取主要特征得到右图。
(Avy pooling现在不怎么用了,方法是对每一个2×2的区域元素求和,再除以4,得到主要特征),而一般的filter取2×2,最大取3×3,stride取2,压缩为原来的1/4.
注意:这里的pooling操作是特征图缩小,有可能影响网络的准确度,因此可以通过增加特征图的深度来弥补(这里的深度变为原来的2倍)。
空间金字塔池化(Spatial Pyramid Pooling)
空间金字塔池化可以把任何尺度的图像的卷积特征转化成相同维度,这不仅可以让CNN处理任意尺度的图像,还能避免cropping和warping操作,导致一些信息的丢失,具有非常重要的意义。
一般的CNN都需要输入图像的大小是固定的,这是因为全连接层的输入需要固定输入维度,但在卷积操作是没有对图像尺度有限制,所有作者提出了空间金字塔池化,先让图像进行卷积操作,然后转化成维度相同的特征输入到全连接层,这个可以把CNN扩展到任意大小的图像
空间金字塔池化的思想来自于Spatial Pyramid Model,它一个pooling变成了多个scale的pooling。用不同大小池化窗口作用于卷积特征,我们可以得到1X1,2X2,4X4的池化结果,由于conv5中共有256个过滤器,所以得到1个256维的特征,4个256个特征,以及16个256维的特征,然后把这21个256维特征链接起来输入全连接层,通过这种方式把不同大小的图像转化成相同维度的特征。
池化输出特征图大小计算
假设输入大小为W1×H1×D1 、池化窗口大小为F×F 、卷积核个数为 K 、步长为S
则有池化输出特征图大小:
注意:池化层的输出深度与输入的深度相同。另外池化操作是分别应用到每一个深度切片层
全连接层(FC)
全连接层的理解就是相当于在最后面加一层或多层传统神经网络(NN)层,我们在连接全连接层前,需要把我们的CNN的三维矩阵进行展平成二维,比如说从池化层出来的是‘553’的图像,在输入到全连接层展平成1*75以满足全连接层的输入模式。
全连接层作用:
第一:链接卷积层的输出
第二:去除空间信息(通道数),是一种将三维矩阵转变成向量的过程(一种全卷积操作)
激活函数
如果输入变化很小,导致输出结构发生截然不同的结果,这种情况是我们不希望看到的,为了模拟更细微的变化,输入和输出数值不只是0到1,可以是0和1之间的任何数,
激活函数是用来加入非线性因素的,因为线性模型的表达力不够
这句话字面的意思很容易理解,但是在具体处理图像的时候是什么情况呢?我们知道在神经网络中,对于图像,我们主要采用了卷积的方式来处理,也就是对每个像素点赋予一个权值,这个操作显然就是线性的。但是对于我们样本来说,不一定是线性可分的,为了解决这个问题,我们可以进行线性变化,或者我们引入非线性因素,解决线性模型所不能解决的问题。
这里插一句,来比较一下上面的那些激活函数,因为神经网络的数学基础是处处可微的,所以选取的激活函数要能保证数据输入与输出也是可微的,运算特征是不断进行循环计算,所以在每代循环过程中,每个神经元的值也是在不断变化的。
这就导致了tanh特征相差明显时的效果会很好,在循环过程中会不断扩大特征效果显示出来,但有是,在特征相差比较复杂或是相差不是特别大时,需要更细微的分类判断的时候,sigmoid效果就好了。
还有一个东西要注意,sigmoid 和 tanh作为激活函数的话,一定要注意一定要对 input 进行归一话,否则激活后的值都会进入平坦区,使隐层的输出全部趋同,但是 ReLU 并不需要输入归一化来防止它们达到饱和。
构建稀疏矩阵,也就是稀疏性,这个特性可以去除数据中的冗余,最大可能保留数据的特征,也就是大多数为0的稀疏矩阵来表示。其实这个特性主要是对于Relu,它就是取的max(0,x),因为神经网络是不断反复计算,实际上变成了它在尝试不断试探如何用一个大多数为0的矩阵来尝试表达数据特征,结果因为稀疏特性的存在,反而这种方法变得运算得又快效果又好了。所以我们可以看到目前大部分的卷积神经网络中,基本上都是采用了ReLU 函数。
常用的激活函数
激活函数应该具有的性质:
(1)非线性。线性激活层对于深层神经网络没有作用,因为其作用以后仍然是输入的各种线性变换。。
(2)连续可微。梯度下降法的要求。
(3)范围最好不饱和,当有饱和的区间段时,若系统优化进入到该段,梯度近似为0,网络的学习就会停止。
(4)单调性,当激活函数是单调时,单层神经网络的误差函数是凸的,好优化。
(5)在原点处近似线性,这样当权值初始化为接近0的随机值时,网络可以学习的较快,不用可以调节网络的初始值。
目前常用的激活函数都只拥有上述性质的部分,没有一个拥有全部的~~
Sigmoid函数
目前已被淘汰
缺点:
∙ 饱和时梯度值非常小。由于BP算法反向传播的时候后层的梯度是以乘性方式传递到前层,因此当层数比较多的时候,传到前层的梯度就会非常小,网络权值得不到有效的更新,即梯度耗散。如果该层的权值初始化使得f(x) 处于饱和状态时,网络基本上权值无法更新。
∙ 输出值不是以0为中心值。
Tanh函数
其中σ(x) 为sigmoid函数,仍然具有饱和的问题。
ReLU函数
Alex在2012年提出的一种新的激活函数。该函数的提出很大程度的解决了BP算法在优化深层神经网络时的梯度耗散问题
优点:
∙ x>0 时,梯度恒为1,无梯度耗散问题,收敛快;
∙ 增大了网络的稀疏性。当x<0 时,该层的输出为0,训练完成后为0的神经元越多,稀疏性越大,提取出来的特征就约具有代表性,泛化能力越强。即得到同样的效果,真正起作用的神经元越少,网络的泛化性能越好
∙ 运算量很小;
缺点:
如果后层的某一个梯度特别大,导致W更新以后变得特别大,导致该层的输入<0,输出为0,这时该层就会‘die’,没有更新。当学习率比较大时可能会有40%的神经元都会在训练开始就‘die’,因此需要对学习率进行一个好的设置。
由优缺点可知max(0,x) 函数为一个双刃剑,既可以形成网络的稀疏性,也可能造成有很多永远处于‘die’的神经元,需要tradeoff。
Leaky ReLU函数
改善了ReLU的死亡特性,但是也同时损失了一部分稀疏性,且增加了一个超参数,目前来说其好处不太明确
Maxout函数
泛化了ReLU和Leaky ReLU,改善了死亡特性,但是同样损失了部分稀疏性,每个非线性函数增加了两倍的参数
真实使用的时候最常用的还是ReLU函数,注意学习率的设置以及死亡节点所占的比例即可
CNN vs FNN
那么CNN卷积神经网络相比于普通的全连接的前馈神经网络的优势是什么呢?
局部连接
相比于前馈神经网络的全连接,CNN实现了局部连接。这样,我们所需要的训练的参数就大大减少了,降低了模型的过拟合。同时,最后的输出的一部分可能只和之前的数据的局部相关联,而不是所有的数据都会影响,这样也提高了最后结果的准确性。
权重共享
可以看到,当我们在反复用卷积核取卷积数据时,我们的卷积核上的参数是重复使用的。共享参数帮我们更少地减少参数数量,同样也是合理的。举例说,判断一个图形的局部形状和这个形状在图形的哪个位置并不相关,所以相同参数就ok了。
加深理解:
https://blog.csdn.net/v_july_v/article/details/51812459