c4w1_卷积神经网络
卷积神经网络
计算机视觉问题
计算机视觉(computer vision)是因深度学习而快速发展的领域之一,它存进了如自动驾驶、人脸识别等应用的发展,同时计算机视觉领域的发展还可以给其他领域提供思路。
计算机视觉应用的实例:图片分类(识别是不是一只猫)、目标检测(检测途中汽车行人等)、图片风格转移等等。
同时,计算机视觉领域也面临着一个挑战:图片数据转换为特征向量太大了。比如一张像素为1000*1000的图,转换成向量后有3百万的输入的特征,这就导致了
- 神经网络的结构非常复杂,参数非常多。在参数如此多的情况下,没有办法获得足够的数据来防止过度拟合。
- 庞大的计算量,没有足够的性能来计算这么多的参数。
因此为了处理这样大的数据量,需要进行卷积运算。卷积运算是卷积神经网络(convolutional neural network, CNN)中非常重要的一块。
卷积运算
边缘检测 Edge detection example
卷积运算是卷积神经网络的重要基石之一。
当给到你一个图片,希望让电脑搞清楚这张图片里有什么物体,可能首先需要做的是对图片进行边缘检测(Edge detection)。
边缘检测分为:垂直边缘(vertical edges)、水平边缘(horizontal edges)
实现垂直边缘检测,需要通过卷积运算来实现。比如检测一张6x6像素的灰度图片的垂直边缘,需要通过一个3x3的矩阵称之为过滤器(filter)或卷积核(kernel)。将原始图片与过滤器(filter)矩阵做卷积运算(convolution),得到一个4x4的图图片。具体的做法是,将filter矩阵贴在原始图片上移动(从左到右,从上到下),每次贴好后逐元素相乘之后求和,得到的结果为4x4矩阵对应的元素。
下面是一个gif展示了卷积运算的操作
、
下图是一个比较好理解的例子,通过卷积运算,原始图片中左右两侧为不同颜色的垂直边缘线,变成了4x4图像中间的空白,代表边缘所在的位置。(在比较大的图片中,边缘会比较明显而不是这种小图中空白柱子)
比较简单的理解,卷积核(filter)矩阵的两边的左右数字是相反的,如果图片中存在像素值相差比较大的两边(垂直边缘),那么原始图片上这两部分和卷积核的内积,差值就会比较大,那么在得到的新图片上颜色差距就会很明显,从而检验出来边缘。比较简单的理解,卷积核(filter)矩阵的两边的左右数字是相反的,如果图片中存在像素值相差比较大的两边(垂直边缘),那么原始图片上这两部分和卷积核的内积,差值就会比较大,那么在得到的新图片上颜色差距就会很明显,从而检验出来边缘。
更多边缘检测的例子
正边和负边检测(positive and negative edges),也就是从亮到暗和暗到亮的区别。
从亮到暗,检测后中间就是亮的;从暗到亮,检测后中间就是暗的。如果不在明暗变化的区别,可以输出矩阵的绝对值。
垂直边缘检测,就是用左右两边互为相反数。水平边缘检测就是上下互为相反数(矩阵转置了一下)
当然,filter的选择并不是固定的,还有Sobel滤波器、Scharr滤波器,其值在下面的途中。他们加强了中心点的权重,使算法更健壮(robust)。
滤波器中的值还可以设置为参数,通过模型训练来得到。这样,神经网络使用反向传播算法可以学习到一些低级特征,从而实现对图片所有边缘特征的检测,而不仅限于垂直边缘和水平边缘。
填充 Padding
为了构建深度神经网络,需要通过Padding对基本的卷积运算进行改进。那么为什么要填充呢?
- 原图片在于卷积filter进行卷积运算的时候变小了,比如上面例子中6x6的图片经过卷积运算后变成了4x4的图片。那么每经过一次卷积运算,图片就会缩小一次,最后可能缩小到1x1。
- 图片中边界像素的运算次数要小于中心像素,比如左上角的像素只参加了一次卷积运算,那么在一次又一次的卷积运算中,会丢图片边缘的信息。
为了解决上面的两个问题,就需要进行图像的填充(Padding)操作。具体的做法就是在图像周围填充一圈为0的像素。填充后的图片再进行卷积运算后其维度就会保持原始图片的大小。如下图所示,此时padding,p=1。
上述的填充操作一方面在卷积运算后保持了图像的大小,另一方面也使得边界像素参加了更多次运算,缓解了边缘信息丢失的影响。
考虑到是否填充,卷积运算分为两种
- Valid convolutions:就是不填充
- Same convolutions:填充之后,保持输入输出图像大小不变
需要注意的是通常在计算机视觉领域,卷积filter的维度大小都是取奇数。一来不会导致填充不对称,二来奇数维度的过滤器会有一个中心点,在计算机视觉领域会方便点。
填充像素的层数可以不是1,要实现Same convolutions,那么填充应该为\(p=\frac{f-1}{2}\)。其中\(f\)代表卷积filter的维度(步长=1)。
卷积的步长
在前面的例子中,每次filter都是移动一个格,也就是步长(stride)为1。在卷积运算中,允许移动的举例大于1。
对于一个nxn的图像,fxf的filter,填充p层,和步长为s,进行卷积计算后,其维度应该是\((\biggl\lfloor \frac{n+2p-f}{s}+1 \biggr\rfloor \times \biggl\lfloor \frac{n+2p-f}{s}+1 \biggr\rfloor)\),计算结果不为整数的,向下取整就好了,因为我们不计算filter没有完全落在图像上的情况。就下图这种情形。
关于卷积和和互相关(cross-correlation)的说明:严格来说,前面介绍的卷积操作和数学上定义的卷积有所差别。数学上的卷积,在卷积进行前要线对fiter进行旋转操作,然后在进行互相关操作(就上面说的逐元素乘积求和)。旋转操作后,满足结合律。
但是在深度学中,对卷积的定义就是上面提到的filter贴合好后,逐元素乘积求和(尽管在数学上这成为互相关)。但这并不会影响在编程中要实现的东西。因为毕竟filter中的数据都是后面要在网络中进行加权求和中学习的参数,所以不旋转影响不大,而且简化代码。
三维卷积
上面介绍的卷积都是应用在二维的灰度图片上,现在将卷积应用于三维上(比如RGB图片上)
RBG图片卷积运算的例子
RGB图片是通过三个颜色通道叠加在一起,也就是三个矩阵叠加,所以原始图片的大小就是6x6x3。对应的,用来做卷积运算的filter也要扩充到三维。要注意的是,在进行卷积运算时,原始图片的通道数(channel)要和filter的通道数一致。
这种情况下,运算的规则是,将这个三维的filter的三个channel对应贴合到原始图片的三个channel上,在每个通道上对应做卷积运算,再把三个通道运算的和作为整体的运算结果,写入到结果矩阵对应位置。
如果仅关注一种颜色的边界,如红色,则可以考虑把filter上对应绿色和蓝色的通道上矩阵全部设为0矩阵。如果RGB三种颜色的边界都考虑,那就这是filter三个通道的矩阵都正常设置。
如果想有多个过滤器怎么办?(就是同时检测垂直、水平或其他方向的边界)。可以应用多个filter(Multi filters是构建CNN的重要思想。)
总结一下维度,原始图片维度是\(n * n *n\),过滤器维度是\(f*f*n_c\),那么得到的结果维度应该是$(n-f+1) (n-f+1)n'_c \(,\)n'_c$是使用filter的个数。
最后要简要说明\(n_c\)这个参数可以称为channel(通道)或者是深度(depth)。
单层卷积网络
一个单层卷积神经网络例子如下
把我们前面学到的神经网络和多过滤器结合起来。这里一个filter就像是一层神经网络中的一个神经单元,每一个filter是对一个特征的检测,进行卷积操作就像是加上权重参数W。进行卷积运算之后加上偏置b,并应用非线性函数RelU,就得到了这一神经单元的输出,把这一层每个filter(神经单元)的输出结合起来就得到了该层网络(卷积层)的输出。
在上图的例子中,使用了两个filter也就是检测了两个特征,最终得到了4x4x2的输出。如果使用10个过滤器,堆叠在一起就会得到4x4x10的输出。
如上图的例子,每个filter都是3x3x3,那么通过卷积计算检测一个特征就需要\(3*3*3+1\)个参数(1个bais);那么相应的,10个filter就有280个参数。
对于卷积计算参数的个数是固定不变的,也就是无论输入的图片是多大,参数都是固定的是比较少的。这是也是卷积神经网络的一个特性可以避免过拟合。
总结卷积神经网络的符号(第l层为卷积层):
-
$f^{[l]} $:filter 的大小,就是矩阵的列数或行数,一般是行列式。
-
\(p^{[l]}\):填充的层数
-
\(s^{[l]}\):卷积计算的步长
-
\(n_C^{[l]}\):filter的数量
-
\(n_H^{[l]}*n_W^{[l]}*n_C^{[l-1]}\):输入图形的维度,其通道数与上一层filter数相等
-
\(n_H^{[l]}*n_W^{[l]}*n_C^{[l]}\):输出图形的维度,通道数与本层filter相等
-
每层的filter的维度:\(f^{[l]}*f^{[l]}*n_C^{[l-1]}\),本层filter通道数应该与本层输入图片通道数一致
-
Activation:\(a^{[l]}\rightarrow n_H^{[l]}*n_W^{[l]}*n_c^{[l]}\),与本层输出图片维度一致,\(A^{[l]}\)的维度是\(m \times n_H^{[l]} \times n_W^{[l]} \times n_C^{[l]}\)
-
权重参数W个数:\(f^{[l]}*f^{[l]}*n_c^{[l-1]}*n_C^{[l]}\),本层filter个数再乘以每个filter中元素个数
-
偏置b个数:\(n_C^{[l]}-(1,1,1,n_C^{[l]})\)
-
其中$n_H^{[l]}=\biggl\lfloor \frac{n_H{[l-1]}+2p-f{[l]}}{s{[l]}}+1 \biggr\rfloor $ \(n_W^{[l]}=\biggl\lfloor \frac{n_W^{[l-1]}+2p^{[l]}-f^{[l]}}{s^{[l]}}+1 \biggr\rfloor\)
简单卷积网络示例
下图为一个简单的CNN
-
输入图片的维度是39x39x3
-
最后输出的图片,可以将其展开(flatten or unroll)成一个向量,再交给logistic单元或softmax单元处理,实现分类。
-
像上图示例,图片的高度\(n_H^{[l]}\)和图片宽度\(n_W^{[l]}\)随着层数的增加逐渐减低,但是通道数\(n_C^{[l]}\)不断增加。许多卷积网络也都可以看到这种趋势(为什么这样处理,看到弹幕这么说)
典型的卷积网络构成
通常由三层
-
卷积层,Convolution (CONV)
-
池化层,Pooling (POOL)
-
全连接层,Fully connected (FC)
全连接层,指的是每一个结点都与上一层的所有结点相连,用来把前面几层提取到的特征综合起来。由于其全连接的特性,一般全连接层的参数也是最多的。https://zhuanlan.zhihu.com/p/552186222
池化层 Pooling Layers
除了卷积层以外,卷积网络还经常用到池化层(Pooling layer)。池化,也叫Pooling,其本质其实就是采样,池化对于输入的图片,选择某种方式对其进行压缩,以加快神经网络的运算速度。这里说的某种方式,其实就是池化的算法,比如最大池化或平均池化。
池化层的示意图(Max pooling):
池化的过程类似于卷积。
上图表示的就是对一个图片领域内的值,采用2x2的池化核,步长为2进行扫描,选择最大值输出,称为最大池化(Max pooling)。
最大池化Max pool,常用的参数为filter=2,stride=2,这样的参数处理的效果就是输出图片的高度、宽度减半,通道数不变。因为我们会对每层通道都进行池化操作。池化操作一般padding=0,池化的目的就是缩小图片提取特征,这和填充的目的相悖。
还有一种平均池化,和最大池化类似,就是求区域内的平均值作为输出结果。一般来将,最大池化用得比较多。
因为在池化操作中,池化filter只负责划分出某次池化操作需要的图片上的范围,filter没有数据计算,在训练过程中也就没有权重参数需要学习。
在通道这个维度上,每次池化操作都是独立的。
池化层的优点是:
- 缩小了图片,但保留了图像的特征,加快计算的速度。
- 池化层没有要学习的参数,因此在训练的过程中,可以在一定程度上防止过拟合的发生。
卷积神经网络示例
下面是一个用来识别手写数字的卷积神经网络架构(LeNet-5):
- 一般把Conv Layer 和 Pooling Layer合在一起算一层,因为池化层没有参数训练。但是也有人分成两层
- 常见的网络结构Conv ==> Pool ==> Conv ==> Pool ==> FC ==> FC ==> softmax
- 在上图的例子中,把layer2得到的volume展开后,输入给全连接层。在FC3中,就像NN一样,有400个输入,120个神经单元。
- 卷积神经网络中,图片的高度和宽度是在不断递减的,通道数是在不断增加的
- 关于超参数的选择,尽量参考论文的经验。
整个例子的参数个数如下:
Activation shape | Activation Size | #parameters | |
---|---|---|---|
Input: | (32, 32, 3) | 3072 | 0 |
CONV1(f=5, s=1) | (28, 28, 6) | 4704 | 156 (=5x5x6+6) |
POOL1 | (14, 14, 6) | 1176 | 0 |
CONV2(f=5, s=1) | (10, 10, 16) | 1600 | 416 (=5x5x16+16) |
POOL2 | (5, 5, 16) | 400 | 0 |
FC3 | (120, 1) | 120 | 48120 (=120*400+120) |
FC4 | (84, 1) | 84 | 10164 (=84*120+84) |
Softmax | (10, 1) | 10 | 850 (=10*84+10) |
- 池化层没有要学习的参数,全连接层要学习的参数最多。
- 激活函数输出的值整体在下降
为什么要用卷积?
CONV Layer相比一般神经网络的全连接层的优势:
- 参数共享(parameter sharing) 以上一节的例子为例,如果在第一层就用FC的话,参数可达4704x3070 + 4704个,这个数字已经膨胀到了1400万,而这还仅是训练一个只有32x32像素的小图片。 而CONV Layer只有156个参数。 参数共享为什么可行呢?一个feature检测器,即filter(比如垂直边界检测)在图片的一个地方适用,也很可能在图片的其他地方适用(在这一点上很像transfering learning或multi-task learning)。这种共享不仅在底层feature有用,也在高层feature有用(比如检测眼睛)。
- 稀疏连接(sparsity of connections) 稀疏连接是指,输出中的每个单元仅和输入的一个小分区相关,比如输出的左上角的像素仅仅由输入左上角的9个像素决定(假设filter大小是3*3),而其他输入都不会影响。
卷积神经网络可以通过这两种机制减少参数,以便我们用更小的训练集来训练它,从而预防过度拟合。