“CNN使我快乐”之CNN基础

本文基于coursera deeplearning.ai 第二课程《Convolutional Neural Networks》第一周,大概讲一下卷积是什么,为之后CNN的学习打一个基础。

所有非手绘图像均来自课程,侵删。

本人才疏学浅,如有问题欢迎礼貌指正。

谢绝任何不标注出处的转发以及百度百家号抄袭。

作者:李皮皮


在computer vision中,深度学习已经是一个重要的工具了,其中非常常用的就是卷积神经网络,CNN。

Computer Vision 常见的用法一个是做图像分类(image classification),一个是物体识别(object detection),还有神经模式转换(neural style transfer)。

1. 为什么需要CNN

对于普通的深度神经网络,我们需要存储的数据量过大过于繁杂。例如一张500*500像素的图像,我们就需要存250000个值;如果是100张图像,就是250m个值,令人害怕。这还不说各种参数的存储。所以我们需要一种更合理的方法来做神经网络进行图像处理。

在卷积神经网络中,参数是可以共享的(parameter sharing)。经过研究发现,如果一组参数对图像的一部分是有用的,那么它读另一部分也很可能有效果。

连接的稀疏性(sparsity of connections):在每一层中,每一个输出结果的值都取决于输入值的一小部分。这就使得每次只有一小部分会影响到某一个输出结果值,让整个结果更稳定。


2. 边缘检测(edge detection )与卷积运算

首先我们通过边缘检测来了解一下卷积是如何运作的。

2.1 边缘检测

给出一张图片,首先我们需要分横向和纵向对其边缘进行检测,如下图所示。

2.2 二维卷积计算

然后我们来展示一下纵向边缘检测的计算。假设第一张图是一个5*5*1的灰度图像(RGB图像则为5*5*3),那么我们就有如下卷积计算。从左往右依次是图像的矩阵,过滤器也在一些科研中被称作核。

为什么需要过滤器呢?如下图所示,最左边是6*6的灰度图像,中间是一个垂直过滤器(水平过滤器是第二行是0),右边是我们得到的矩阵。每个矩阵下面对应着其成色。过滤器可以帮我们弱化不重要的部分,强化重点部分(由亮到暗还是由暗到亮)。如果我们不需要强调其亮度的变化过程,就可以用矩阵绝对值代替。

具体的步骤如下。先在左边选取3*3大小的小矩阵,然后将过滤器的值对应进小矩阵中,如下图右边所示。然后进行加权计算,得出结果为7,则输出结构矩阵第一行第一列的值则为7.

然后将小矩阵的框向右平移一个单位,得到新的矩阵,并计算出第二个值-2:

当行挪动被遍历一遍,就开始以1格为单位向第二行挪动。最终我们会得到一个3*3的矩阵。输出矩阵的维度计算公式如下:

(n-f+1)*(n-f+1), 其中n是图像矩阵的边长,f是过滤器的边长。

在python中当然不是这么手算的,有很多不同的计算卷积的method。比如TensorFlow的就是tf.nn.conv2d(),Keras的是Conv2D()。

这里需要说明一下在一些数学课本中,卷积的符号表示不太一样。通常数学课本中,卷积之前会把过滤器进行一个逆时针两次旋转,如下图所示。数学概念中这样做了旋转其实才是真正的卷积,CS深度学习中的运算其实是叫做cross-correlation交叉相关的东西,只不过在深度学习文献中,大家约定俗成将其称为“卷积”。

2.3 三维/多维卷积计算

上面说的是对二维矩阵的卷积运算,但是现实中除了灰度图像,更多的是RGB图像,那么RGB该如何表示呢?——其实很简单,就是6*6*1的数据集变成了6*6*3。相应地,过滤器也从3*3*1变为了3*3*3。看起来就像这样:

那么在运算的时候呢,可以把3*3*3的过滤器考虑成一个立方体结构。这个结构中,有27个值,这27个值每次都分别要与RGB图像的对应区域做卷积,然后27个值和对应位置相乘产生的和就是输出矩阵的第一个值。

在做完第一次过滤之后(假设它是垂直过滤),我们可能还想进行另一种过滤(假设为水平过滤)。此时我们已经得到了一个4*4*1的输出矩阵(如上图所示),那么再对原矩阵进行一次运算,就会得到第二个4*4*1的矩阵。就像神经网络一样,我们可以把这两个输出矩阵拼在一起,这样又得到了一个4*4*2的矩阵,2代表我们使用了两个过滤器。

对于多维,我们就有:(height*width*channels)卷 (f*f*channels) = (n-f+1) * (n-f+1) * filters。filters是过滤器的数量。不同的过滤器可以直接检测RGB图像不同的特征(不需要做灰度处理等),这就是深度学习图像处理的强大之处。

2.4 过滤器的种类

目前在计算机视觉中,采用什么大小的过滤器,过滤器如何取值还存在很大争议。所以不需要拘泥于上述的(-1,0,1)的3*3组合。除了上文提到的过滤器,还有如下过滤器(sobel让我想到了saber)。可以看到他们的权重比上文提到的过滤器要大一些。

可以看到不管怎么说,3*3都是一个过滤器常用的组合,而且一个好处就是无论图片的分辨率多高,都可以使用3*3来解决,这也使得卷积神经网络不太容易过拟合。

2.5 过滤器参数

除去给定过滤器,我们也可以将整个矩阵的值设为参数,通过反向传播进行求解,从而得到一个很好的过滤器。如下图所示。这样的得到的过滤器可能不仅仅可以探测垂直、水平边缘,甚至可以检测带角度的边缘。

3. Padding

padding是构建深度学习神经网络一个非常基础和重要的技术。什么是padding呢?如下图示,本来我们要计算的是一个4*4的矩阵乘一个3*3的过滤器。使用padding,给图像矩阵的四周加一圈(padding),让它变成一个6*6的矩阵,这样6*6卷3*3出来就是(6-3+1)*(6-3+1)还是4*4的矩阵啦~设padding的层数为p(下图就是p=1),那么就有新的卷积生成的矩阵维度公式:

(n+2p-f+1)*(n+2p-f+1)

为什么需要padding呢?

(1)用来控制维度。前面提到了普通卷积计算出来的维度是(n-f+1)*(n-f+1),这意味着每次进行卷积计算,输出矩阵的结果都会变小,几轮下来它基本就快没了。所以我们需要padding来控制输出矩阵的维度。

(2)让边缘的像素不被浪费。对于普通的卷积计算,图像矩阵边上的像素只被利用了一次,而padding可以让其被多次利用,让边缘信息不至于丢失的太厉害。

那么我们到底需要padding多少才是合理呢?有两种卷积方式:

(1)valid convolutions: no padding,正常卷即可

(2)same convolutions:通过padding让input 维度和 output维度相同。那么有:

\\n = (n + 2p -f +1) \\p = \frac{f-1}{2}

通常我们会让f是奇数,这样p出来就是整数,好思考一些。但这只是一个约定俗成的东西,并没有铁则。


4. Strided convolution

在前面卷积计算的过程时,我们是一次向右挪动一格,被称为一格步长。其实也可以自己确定步长。这个步长就被称为stride。例如当stride=2时,下面的计算就变成了红圈的步骤。下移也是,s=1只下移一行,s=2就是下移两行再进行卷积计算。

在使用strided convolution时,得出的矩阵维度就变成了:

(\frac{n+2p-f}{s}+1) * (\frac{n+2p-f}{s}+1)

如果分式不能得到整数,就进行下取整。


5. 简单的卷积神经网络

5.1 卷积神经网络的一个卷积层

在2.3章节提到了多维RGB图像矩阵的卷及计算以及多个过滤器的卷积,这就是一层进行的工作。除此之外,在产生输出巨震后,还要添加一个bias,形成线性的模式。在此基础上,可以选取激活函数对新生成的矩阵进行计算。

下图详细过程如下:首先得到一张RGB图片的信息,假设它是6*6*3的矩阵,然后我们使用两个3*3*3的过滤器。得到了两个4*4*1的矩阵,分别给两个矩阵赋予bias。bias通过python的broadcasting被加入矩阵。这里就得到了普通神经网络中z=wa+b的结构。然后使用激活函数,这里用的是ReLu,得到激活矩阵a=g(z)。输出的结果是两个矩阵,这两个矩阵被看做一个4*4*2的输入进入下一层神经网络的计算。然后来看一下参数情况。首先两个filters,每个27个值,我们有54个参数,然后加上两个bias,56个参数。

5.2 简单的例子

假设我们有39*49像素的RGB图片m张,那么数据就是 m*39*49*3。然后用图来表示单个图片的神经网络:

第一层使用了10个3*3的过滤器,步长为2,没有padding,得到了一个37*38*10的输出值。然后第二层使用了40个4*4的过滤器,步长为2,padding为1,产生一个18*19*40的结果。第三层使用45个5*5的过滤器,步长为2,没有padding,得到7*8*45的结果。然后将这个结果中7*8*45=2520个值平铺成一个很长的向量,使用逻辑回归或者softmax(主要看你要干啥)进行分类处理,得到最终结果。

在这样一个例子中,使用到的超参数就巨多了。。我发现我对深度学习并不是真爱,我只是爱吴恩达。

5.3 卷积神经网络(convnext)中层的种类

(1)卷积层(Conv),就是上面提到的

(2)pooling layer(Pool)池化层,使用这种层是为了减少展示量。

池化的方式有很多,这里拿min pooling举例(但其实好像不太常用min, 一般都是max抓取特征)。我们的目标是从下面4*4的矩阵中得出一个2*2的池化矩阵(差点打成痴汉矩阵。。。),min pooling就是在2*2的域里寻找最小值,然后结果就是那个最小值。

除了min pooling,还有max pooling,average pooling。max pooling是最常用的。吴恩达说目前没有很好地理论说明为什么它很好用。max pooling没有需要做调解的超参(超参包括过滤器大小,步长,哪种pooling,padding在池化层很少用),这也是它的一个优势。常见的超参组合是f=2,s=2/f=3,s=2.

在池化层,上面提到的公式依然适用。

因为池化层没有实际需要调节的参数,所以一般池化层会前一个卷积层合称为一层。

(3)Fully connected layer(FC层)

在得到的三维矩阵被打成一个扁平的长向量后,我们依然可以继续做处理。如下图所示,将一个400*1的向量继续用神经网络变为200*1,而这一个200*1的层被称为FC层,其权重矩阵大小为200*400,bias为200个。

在一个CNN中,FC层可以被多次使用,一般是用在临近输出结果的地方,最后使用逻辑回归或者softmax得出最终结果。

猜你喜欢

转载自blog.csdn.net/weixin_39965890/article/details/81177564
CNN