8-卷积神经网络
卷积神经网络
在之前的猫图片分类问题中,使用的图片是64x64的,有RGB三通道,所以特征向量维度为64x64x3=12288,维度并不算高,因为64x64是一张很小的图片。
而要操作更大的图片,例如一张1000x1000的图片,它的特征向量维度是1000x1000x3=300万,如果要将该图片输入到神经网络中,假设第一层有1000个隐藏单元,那么第一层的权重就会有30亿个参数,这是一个非常巨大的数字,在参数数量如此大的情况下,很难保证有足够的数据来防止神经网络发生过拟合,同时,巨大的内存需求也很难接受。
但是对于计算机视觉应用来说,需要处理小图片和大图片,因此需要进行卷积计算。
边缘检测示例
卷积运算是卷积神经网络中最基本的组成部分,以边缘检测(Edge detection)为例,说明卷积是如何计算的。
边缘检测就是检测一张图片中物体的边缘位置,例如:
给定这样一张图片,计算机可能会检测图片中的垂直边缘和水平边缘。
那么怎么通过卷积计算检测图像的垂直边缘呢。
一个例子,给一个6x6的灰度图像,因为是灰度图像,所以没有RGB三通道,只有一个通道,它是6x6x1的矩阵。
构造一个3x3的矩阵,称为过滤器filter(也称为滤波器或称为卷积核kernel)。
卷积运算使用*
来表示,也称为 互相关(cross-correlation)运算
关于运算符号,在数学中
*
就是卷积的标准符号,但是在一些编程语言例如Python中,常用来表示乘法或者元素乘法,因此*
具有多层含义,注意区分。
上面式子中:称为过滤器,用来检测垂直边缘。
两个矩阵的计算结果是一个4x4的矩阵。
运算方法如下,首先将过滤器放到灰度图像矩阵的左上角,与左上角的3x3矩阵进行元素相乘再求和运算,然后过滤器向右、向下移动依次进行计算。
首先将过滤器覆盖到灰度图像的左上角,进行元素乘法运算,然后每个元素相加得到4x4矩阵最左上角元素。
即:(3 × 1) + 1 + (2 × 1) + 0 + 0 + 0 + (1 × -1) + (8 × -1) + (2 × -1) = -5
然后将过滤器右移一位,进行输出矩阵中第一行第二列元素的计算。
即:
0 + (5×1) + (7×1) + 0 + 0 + 0 + (2× -1) + (9× -1) + (5× -1) = -4
然后将过滤器继续向右移动,以此计算,移到最右边后,将过滤器下移一位,继续放到最左边计算。
最终得到4x4的矩阵,这个矩阵可以被理解为另一张图片,这就是垂直边缘检测器。
下面来说明为什么这个过滤器可以实现垂直检测。
给出一个灰度图片,左边一半是10,较为明亮;右边一半是0,比较暗,这里使用0来表示灰度,当然0也可以表示成黑色。
图片中,中间部分有一个很明显的边缘线,从白色到灰色。
3x3的过滤器同样可以看成下面这个图片样子,左边是明亮像素,右边是黑色像素,中间是过渡的灰色。
经过卷积计算后,就得到右边4x4的矩阵,左右两边都是灰度图像,中间有一段亮色区域,这片亮色区域就对应到原图的垂直边缘。
当然这里检测到的边缘太粗了,这是因为原图太小的原因,如果使用一个分辨率较大的图像,那么就能很好的检测出图像的垂直边缘。
同样还可以区分正边和负边,也就是从亮到暗和从暗到亮的区别,即边缘的过渡。
上述例子中,是从暗到亮过渡,如果将原图水平翻转,那么就变成从亮到暗过渡。
因此这个过滤器可以区分出这两种明暗变化的区别,如果我们并不在乎这两者区别,可以 取矩阵的绝对值。
如果将上面的过滤器转置,变成,就可以用来检测水平边缘。
总而言之,通过使用不同的过滤器,可以找出垂直或者水平的边缘。
对于这个3x3的过滤器来说,可以使用各种不同的数字组合。
例如有一种叫做Sobel的过滤器:,它的优点在于增加了中间一行的权重,使得结果的鲁棒性更高。
同样还有一种叫做Scharr的过滤器:,同样是一种边缘检测。
随着深度学习的发展,当去检测复杂图像的边缘时,并一定要用研究者所选择的这九个数字,而是把矩阵中的9个数字当成参数,使用反向传播算法,来得到最优参数。
即:
将这九个数字当成参数的思想,已经成为计算机视觉中最为有效的思想之一。
注意:在一些数学书中,卷积运算的严格定义是将过滤器矩阵进行水平和垂直翻转,然后再进行计算;而在深度学习中,一般不将过滤器翻转,但是通常仍称为卷积运算
填充 Padding
在之前的卷积操作中,如果输入图像大小是n×n,过滤器的大小是f×f,那么输出的图片大小为:(n-f+1) × (n-f+1)。
这样的话,有两个缺点:
- 将输入图片和过滤器进行卷积运算后,输出的图片会变小,这种情况下,如果经过几次卷积运算后,图像就会变得很小
- 对于输入图片的角落边缘像素,过滤器与其重叠的次数很少,而对于图片中间位置的像素,过滤器重叠的次数很多。例如最左上角的像素,过滤器与该像素只有一次重叠,这意味着丢掉了图像边缘位置的许多信息
为了解决这一问题,可以在卷积操作之前填充图像。
例如在上个例子中,可以沿着图像边缘再填充一层像素,通常全填充为0。
如果p是填充的数量,即向外填充的层数,在上面这个图中,p = 1。
填充以后,输出的图像大小为:(n + 2p - f + 1) × (n + 2p - f + 1) = 6 × 6,正好和输入相等。
这样一来,丢失边缘信息这一缺点就被削弱了。
至于填充多少像素,通常由两个选择:
Valid
卷积:不填充,也就是p = 0Same
卷积:填充以后,输出大小和输入大小相同,那么根据公式n - f + 1,当填充p层,那么 ,即p = (f - 1) / 2,那么当f是一个奇数,可以直接计算出p;当f为偶数,可能要使用不对称填充
一般来说,在计算机视觉中,f通常是奇数,主要有两个原因:一是f为偶数的话,需要使用不对称填充,而f为奇数,Same
卷积才会有自然地填充;二是因为,在计算机视觉中,有一个中心像素点会更方便,便于指出过滤器位置。
卷积步长 Strided convolutions
卷积中的步长(或步幅 stride)是另一个构建卷积神经网络的基本操作。
在之前的卷积运算中,过滤器每运算完一个区域,就继续向右或向下移动一个步长。
但移动步幅可以不为1,而是作为一个参数进行设置。
例如一个7×7的输入图片,可以令步长 s = 2,则移动过程为:
注意:从第一列最右边到第二列最左边,中间是跳过了图片的一行的,也就是向右向下的步长都为2。
如果输入图片维度为,过滤器维度为,padding填充层数为p,步长为s。
那么输出的维度为:
为向下取整。
更一般情况下,输入的图片宽高,过滤器矩阵宽高,上下和左右填充层数,向右向下的步幅都可以不相同。
假设输入图片维度为,过滤器维度为,如果在高的两侧共填充行(注意,这里是上下两侧都算上了,不需要乘2),在宽的两侧共填充行(同样是左右两侧),当上下步幅为,左右步幅为,
那么输出的维度为:
如果使用Same
卷积,那么,那么输出维度为:
总的来说,当输入的高和宽两侧填充数分别为时,称填充为:,特别地,当时,填充为p。
当高和宽的步幅为时,称步幅为:,特别地,当时,步幅为s。
三维卷积
在之前说明了如何对二维图像进行卷积操作,下面来说明在三维立体图像上如何进行卷积。
一个彩色的图像有三个通道:R,G,B三原色。
如果分辨率为6×6,那么这个图像的维度为:6×6×3,最后的数字3被称为这个图像的通道数(channels)(一些文献里有时也称为深度depth)。
其中第一个6是图像高度,第二个6是图像宽度。
那么对应的过滤器也是三维的,有一个高、宽和通道数。
并且过滤器的通道数必须和图像的通道数相同。
如果过滤器的维度为3×3×3,那么输出会是一个4×4×1的图像。
将输入图片矩阵和过滤器都看成一个立方体。
在卷积计算过程中,过滤器立方体首先放到输入的最上角,一共27个元素,对应元素相乘然后相加,得到输出矩阵的第一行第一列元素。
然后将立方体向右移一位,进行同样计算,以此类推。
注意这里的填充p = 0,步幅s = 1。
可以理解为,过滤器的三层分别和输入矩阵的三层进行卷积运算,然后得到3个4×4的矩阵,再将这3个矩阵对应元素相加,得到一个4×4的矩阵。
如果只检测图像红色通道的边缘,那么可以将第一个过滤器(也就是红色对应的过滤器)设为,其余两个通道的过滤器全为0。
如果不关心垂直边缘在哪个通道,那么就可以将三个通道的过滤器都设为上面的矩阵值。
如果想要同时检测垂直边缘和水平边缘,那么需要使用两个过滤器:垂直边缘检测器和水平边缘检测器。
每个过滤器的输出都是一个二维矩阵,然后将两个二维矩阵放在一起成为一个三维的输出。
还以上面例子为例:
总结一下维度,如果有一个的输入图像(是通道数),过滤器为,两个数值相同,然后会得到一个,其中就是使用的过滤器个数,也是下一层的通道数。
注意这里没有用填充padding,步幅是1,如果使用了不同的步幅或者padding,维度要相应修改。
单层卷积网络
上面已经讲了如果使用两个过滤器来处理一个三维图像,并输出两个4×4的矩阵。
以这个例子来说明如何构建单层卷积网络。
在输出的两个4×4矩阵后加上各自的偏置,然后使用Relu激活函数。
在前向传播中一层的运算过程是
那么这里的输入图片就是,过滤器的所有权重就是,偏置就是,得到的矩阵通过Relu激活函数输出两个4×4×1的矩阵,放到一起得到一个4×4×2维度的矩阵。
在这里例子中,参数的个数为:3×3×3×2 + 1×2 = 56,其中的2表示有两个过滤器。
注意:在这个例子中,不论输入的图片有多大,1000×1000也好,5000×5000也好,参数始终都是56个,这是卷积神经网络的一个特征,叫做“避免过拟合”。
最后总结一下描述卷积神经网络中的一层(以l
层为例)。
使用表示过滤器大小,;表示padding数量(一边,计算维度需乘2);表示步幅。
该层的输入维度为:,其中是上一层的输出通道数。
该层的输出维度为:,其中是本层的过滤器数量。
并有:
关于通道数量,通过上一个例子,可以知道,如果有2个过滤器,输出图像维度就是4×4×2,如果有10个过滤器,输出维度就是4×4×10。
输出图像的通道数就是本层网络所使用的的过滤器数量,并且过滤器中的通道数必须和输入中通道的数量一致。
所以一个过滤器的维度是。
应用偏差和非线性激活函数后,输出是,维度就是,如果执行批量梯度下降时,有m个样本,那么输出为
关于权重参数,一个过滤器的维度已知,是,过滤器的数量是,那么权重就是过滤器集合再乘以过滤器数量,即。
最后是偏置参数,每个过滤器都有一个偏差参数,是一个实数。
偏差的维度是:。
卷积有很多标记方法,关于高度,宽度和通道数量并没有完全统一的标准,有时在查看其他资料时,可能会发现作者把通道数放在首位,只要保持一致,这两种标记方法都可以。
简单卷积网络示例
以一个39×39×3的输入图片为例,经过三个卷积层。
最后可以将7×7×40的输出矩阵展开成一个向量,经过逻辑回归或者softmax回归层,得到最终的预测输出。
一个典型的卷积神经网络通常有三层:卷积层(Conv),池化层(POOL),全连接层。
池化层
卷积神经网络使用池化层来缩减模型大小,提高计算速度,同时也提高所提取特征的鲁棒性。
池化层分为最大池化(max pooling)和平均池化(average pooling)。
最大池化(max pooling)
假如输入是一个4×4的矩阵,使用的池化类型是最大池化。
执行最大池化的树池是一个2×2矩阵。那么执行过程很简单,把4×4的输入拆分成不同区域,对于每一个区域,取最大值,得到输出。
即输出的每个元素都是对应颜色区域的最大值。
左上区域的最大值是9,那么输出矩阵的左上角元素就是9,以此类推。
为了计算出右侧的四个元素值,需要对输入矩阵的2×2区域做最大值运算,这相当于应用了一个2×2的过滤器,并且步幅是2,填充为0。
这些就是最大池化的超参数。
最大池化功能的理解:可以把4×4的输入看作是某些特征的集合,也就是神经网络某层的非激活值集合,数字大意味着可能探测到了某些特定特征,在上面例子中,左上区域存在该特征,而右上区域不存在。
所以最大化操作的功能就是只要在任何区域提取到某个特征,都会保留在最大化的池化输出里。
池化层还有一个特点是:它有一组超参数,但是没有参数需要学习,梯度下降也不需要更新池化层。一旦确定了,它就是一个固定的计算。
来看一个有若干个超级参数的示例,输入是一个5×5的矩阵,采用最大池化法,超参数为,输出矩阵是3×3。
之前计算卷积层输出大小的公式同样适用于池化层,即:
最终的输出如上图。
以上是一个二维输入的最大池化,如果输入是三维的,那么输出也是三维的。
对于三维输入,计算最大池化的方法就是分别对每个通道执行刚刚的计算过程。
例如上面例子,如果输入是5×5×2,那么输出是3×3×2的矩阵。
平均池化(average pooling)
还有一种类型的池化,叫做平均池化:取的是整个区域的平均值。
总的来说,最大池化要比平均池化更常用。
总结来说,池化层的超参数包括过滤器大小和步幅。
常用的参数值是。应用的频率非常高,效果相当于高度和宽度缩减一半。
一般来说,很少使用超参数padding,即。
所以假设没有padding,池化层输入为,则输出维度为:。输入通道与输出通道个数相同。
需要注意的是:正如上面已经提到的,池化过程中没有需要学习的参数,执行反向传播时,也没有参数适用于池化层。池化过程就是计算神经网络某一层的静态属性。
卷积神经网络示例
构建全卷积神经网络的构建模块已经讲完了,接下来使用这些构建模块来搭建一个全卷积神经网络,一个典型的神经网络一般包括:卷积层,池化层和全连接层。
假设有一张大小为32×32×3的输入图片,想要进行手写数字识别。
第一层使用的过滤器大小为5×5,步幅为1,padding为0,过滤器个数为6,那么输出为28×28×6,这层标记为CONV1,卷积后,添加偏差,然后应用非线性函数,最后得到该层的输出结果。
然后构建一个池化层,这里选择最大池化,参数,padding为0,该层的输出会比输入的高度和宽度减少一半,通道数不变,因此输出为14×14×6,该层标记为POOL1。
在卷积神经网络文献中,卷积层有两种分类:一种是将一个卷积层和池化层合起来作为一层,就是下图的Layer1;另一种是把卷积层和池化层都单独看做一层。
因为在计算神经网络层数时,通常只统计具有权重和参数的层,而池化层没有权重和参数,所以这里使用第一种分类,把卷积层和池化层作为一层,即Conv1和Pool1为一层Layer1。
然后再构建一个卷积层和池化层,使用16个过滤器,过滤器大小和步幅都与第一层一样,然后将CONV2和POOL2看做Layer2。
Layer2的输出为5×5×16,包含400个元素,接下来将该输出矩阵化为一个大小为400的一维列向量,然后将该向量作为第一个全连接层的输入。
第一个全连接层有120个隐藏单元,权重矩阵为,维度为,这就是“全连接”,因为这400个单元与120个单元的每一项都连接,输出120个维度,该层称为FC3(full connected);
然后再添加一个全连接层,有84个隐藏单元,标记为FC4;
最后用这84个单元填充一个softmax单元,在本例的手写数字识别中,sofmax会有10个输出。
本例中的卷积神经网络很典型,有很多超参数,而关于选定参数的一个建议是:不要自己设置超参数,而是查看文献中别人采用了哪些超参数。
随着神经网络深度的加深,每一层的输出高度和宽度都会减少,而通道数量会增加。
在神经网络中,一个常见的模式就是一个或多个卷积后面跟一个池化层,然后一个或多个卷积后面再跟一个池化层,然后是几个全连接层,最后一个是softmax。
为什么使用卷积
卷积层相比全连接层的主要优势有两个:
- 参数共享(Parameter Sharing):一个适用于图片某些部分的特征提取器也适用于这个图片的其他部分
- 稀疏连接:在每一层中,每个输出值仅仅依赖于输入中的几个数字
具体来说:
参数共享,观察发现,特征检测例如垂直特征检测如果适用于图片的某个区域,那么它也可能适用于图片的其他区域。因此每个特征检测器都可以在输入图片的不同区域使用相同的参数,从而达到了共享参数的效果。减少了参数的个数。
稀疏连接,输出矩阵中的每一个输出值都仅依赖于 输入矩阵中与过滤器重叠的那部分像素值,其他像素值不会对该输出值产生影响。
矩阵维度理解
卷积神经网络的输入图片矩阵一般是三维的,如果有多个图片样本,那么整个输入是四维的,较难想象,因此在这里进行说明,便于理解。
如果有m个样本,那么整个输入维度是。
首先可以把每个图片想象成一个立方体,其中的每一个小立方体都代表一个元素,其中正向面对的是维度为的一个二维矩阵。而多个图片就是将多个立方体排列起来。
例如有一个维度为的四维张量X,即有4个立方体,每个立方体的维度都为。
那么X[0]为第一个立方体,维度为,依次类推:
X[1,0]为第二个立方体的第一层,维度为:
X[1,0,1]为第二个立方体第一层的第二列,维度为,是一个向量:
可以把四维张量的每个轴称为axis_0,axis_1,axis_2和axis_3,那么每个轴对应的元素顺序为:
axis_0:
axis_1:
axis_2:
axis_3:
可以将元素赋上实际数值,使用Python代码X = np.arange(1,37).reshape(2,3,3,2)
可以得到:
使用Python
的切片操作,有以下式子:
依照上述说明可知,假设有m个图片样本,每个图片样本的维度为,那么整个样本集维度为:。
如果取第一张图片,表达式为,一般来说,取第i张图片,表达式为;
取第一张图片的第一个(R层)通道层,使用,一般来说,取第i张图片的第j个通道层,表达式为。