本文是Deep Learning Specialization系列课程的第4课《Convolutional Neural Networks》中Convolutional Neural Networks部分的学习笔记。
本文是以计算机视觉为应用来对卷积神经网络做了一个全面的剖析,内容包括:
- 边缘检测
- 滤波器
- 填充
- 步长
- 池化
- 卷积运算中的参数
- 完整的卷积神经网络
计算机视觉
计算机视觉 + 深度学习:
- 使得计算机视觉飞速发展以产生更多直接拿来用的全新的应用
- 计算机视觉方面的研究也可以借用到其他方向,比如语音识别
计算机视觉主要是为解决以下4个问题:
- 图像识别,比如识别图像上的动物是不是猫
- 目标检测,比如识别图像中的对象是什么、在哪里
- 图像风格转移:通过两张图片来合成一张图片
- 描述图像:将图像中呈现出来的内容以文字形式表达出来
那么,为什么要在计算机视觉中引入卷积神经网络呢?
因为计算机视觉主要是处理图像,当将其转换为像素后,输入数据会非常的大,导致参数的维度也很大,通过传统的神经网络不能很好的处理。比如,当输入的是一个很小的64x64的图像,总共有3个通道,那么输入层的维度就为12288。
边缘检测
关于边缘检测,之前这篇《卷积神经网络与图像边缘检测》文章也做了一些描述,这里再来复习一下。
计算机视觉的处理是从简单到复杂,第一步一般都是对图像进行边缘检测。在边缘检测阶段,需要用到不同的边缘检测算子(滤波器,Filter),比如垂直滤波器(Vertical Filter),水平滤波器(Horizontal Filter)。
以垂直滤波器为例,其滤波器为3x3的一个矩阵,第一列为1,第二列为0,第三列为-1。通过滤波器的形状就能知道,其能将垂直方向的特征提取出来。其计算则是将滤波器放置在输入层,依次相乘后求和,得到输出层的值。
具体可以参考下图中的例子。
水平滤波器与垂直滤波器类似,即把垂直滤波器转了90度,以识别出水平方向的特征。
此外,将滤波器的值稍做修改,能得到Sobel等其他滤波器。
上面讲述的都是传统的计算机视觉进行边缘检测的方式,其所使用的滤波器都是提前定义好的。那么引入深度学习的计算机视觉,是将滤波器的参数作为训练时的参数来进行学习的。
下面来重点讲讲卷积运算的一些基本概念。
填充(Padding)
从上面的例子可以看到,在通过卷积计算后,输出的数据尺寸比输入数据变小了。这样,在继续往下计算时,会导致数据越来越小。
另外,在上面的计算中,我们也发现,在边缘的像素参与计算的次数要少于中间的像素,这就会导致卷积计算没有充分利用已有的数据。
基于上述两个原因,我们在卷积计算中需要引入填充(Padding),即在原始输入数据外围填充值为0的像素。
包含填充的卷积计算公式为:
n
+
2
p
−
f
+
1
n+2p-f + 1
n+2p−f+1,其中n为输入层的维度,p为填充数,f为滤波器的大小。
具体如下图所示。
在卷积计算中,包含两个概念:Valid卷积和Same卷积
- Valid卷积是指在卷积计算中没有应用填充,即 p = 0 p=0 p=0。比如,输入数据大小为6,滤波器大小为3,那么输出数据大小为4。
- Same卷积则是指在经过卷积计算后,要保证输出于输入的尺寸相同,即 n + 2 p − f + 1 = n n+2p-f+1=n n+2p−f+1=n -> p = f − 1 2 p=\frac{f-1}{2} p=2f−1。比如,输入数据为6,滤波器大小为3,此时需要保证计算后输出数据的大小不变,则需要保证 p = 1 p=1 p=1。
步长(Stride)
在上面的卷积计算中,我们在水平方向和垂直方向采用的都是一个像素一个像素的移动滤波器,其中移动的间隔就是步长(Stride)。
将填充与步长结合起来,我们就能得到这样的计算公式:
n
+
2
p
−
f
s
+
1
\frac{n+2p-f}{s} + 1
sn+2p−f+1
互相关运算与卷积运算
在机器学习或深度学习领域,是把「互相关运算」都称为「卷积运算」。关于这部分内容,在后续文章中再来详细做一个说明。
Volumes的卷积计算
上面的例子中,都是以二维的矩阵来说明。但我们在处理计算机视觉的问题时,使用的图像一般都是三维(RGB)的体,下面就来继续进行扩充。
这里的第三维,我们可以将其称为通道(Channel),这样,我们的输入数据的维度为
(
n
h
,
n
w
,
n
c
)
(n_h,n_ w, n_c)
(nh,nw,nc)。
在计算时,输入数据和滤波器的通道数是需要相同的,在下面的例子中,都为3。在最后的输出数据中,则需要将各通道的计算结果相加,得到通道数为1的图层。
这里要注意,滤波器也可以有多层,那么不同层的滤波器的参数可以不一样,这需要根据具体的需要来。
在上面的例子中,是只包含一个滤波器,当有多个滤波器时,则最后的输出也是一个堆叠(stack),其数量与所使用的滤波器的数量一致。
卷积神经网络的一个网络
下面以卷积计算中的一个层为例来进行详细的说明。
在前面的神经网络中,我们知道了输入数据
X
X
X,参数为
W
W
W和
b
b
b,此时需要通过线性函数来计算
Z
Z
Z,再通过激活函数计算
A
A
A,最后得到输出层。
那在卷积计算中也是一样,这里唯一的区别就是在神经网络中的参数
W
W
W是与输入层、隐藏层的节点数相关的,维度为
(
n
l
,
n
l
−
1
)
(n^l, n^{l-1})
(nl,nl−1)。而卷积计算中的参数只是与使用的滤波器相关。
具体的计算图如下所示:
这里, l l l层的参数个数为滤波器大小加上一个偏置,乘以滤波器的个数, ( f ∗ f ∗ n c + 1 ) ∗ m (f*f*n_c+1)*m (f∗f∗nc+1)∗m
根据上面的计算图,来总结一下第
l
l
l层的各个参数的维度。在计算时,可以将数据分为两部分:滤波器(参数)相关和输入输出数据。
滤波器(参数):
- 滤波器大小: f [ l ] f^{[l]} f[l]
- 填充: p [ l ] p^{[l]} p[l]
- 步长: s [ l ] s^{[l]} s[l]
- 滤波器数: n c [ l ] n_c^{[l]} nc[l],滤波器数与输出层的通道数相同
- 每个滤波器的维度为: ( f [ l ] , f [ l ] , n c [ l − 1 ] ) (f^{[l]}, f^{[l]}, n_c^{[l-1]}) (f[l],f[l],nc[l−1]),其中 n c [ l − 1 ] n_c^{[l-1]} nc[l−1]为滤波器的通道数,与输入层的通道数相同
- 激活函数维度: a [ l ] = ( n h [ l ] , n w [ l ] , n c [ l ] ) a^{[l]} = (n_h^{[l]}, n_w^{[l]}, n_c^{[l]}) a[l]=(nh[l],nw[l],nc[l])
- 权重维度: ( f [ l ] , f [ l ] , n c [ l − 1 ] ) ∗ n c [ l ] (f^{[l]}, f^{[l]}, n_c^{[l-1]}) * n_c^{[l]} (f[l],f[l],nc[l−1])∗nc[l]
- 偏置维度: n c [ l ] n_c^{[l]} nc[l]
输入和输出层:
- 输入层维度: ( n h [ l − 1 ] , n w [ l − 1 ] , n c [ l − 1 ] ) (n_h^{[l-1]}, n_w^{[l-1]}, n_c^{[l-1]}) (nh[l−1],nw[l−1],nc[l−1]),其中输入层的通道数与滤波器的通道数相同
- 输出层维度: ( n h [ l ] , n w [ l ] , n c [ l ] ) (n_h^{[l]}, n_w^{[l]}, n_c^{[l]}) (nh[l],nw[l],nc[l]),其中输出层的通道数与滤波器的数量相同
这里,输出层与输入层的关系是:
n
h
[
l
]
=
(
n
h
[
l
−
1
]
+
2
p
[
l
]
−
f
[
l
]
)
/
s
[
l
]
+
1
n_h^{[l]} = (n_h^{[l-1]} +2p^{[l]} -f^{[l]})/s^{[l]} + 1
nh[l]=(nh[l−1]+2p[l]−f[l])/s[l]+1
一个简单的卷积神经网络
根据上面的内容,我们将线性函数和激活函数封装在区块(block)中来进行图示说明:
这里在最后的输出层中,将卷积运算的结果转化为了全连接层,然后再应用前面神经网络中学习到的内容来计算最终的估计值
y
^
\hat y
y^。
池化(Pooling)
在卷积神经网络的计算中,一般是包含三种类型的网络层:卷积层、池化层和全连接层。其中,卷积层和全连接层(神经网络中将网络展开为1列的网络层)我们已经熟悉了,那么什么是池化层,又为什么需要池化层呢?
池化是缩短输入数据宽、高方向上的空间的运算。
- 它没有要学习的参数,只是从目标区域中取得最大值或平均值。
- 经过池化运算后,输入数据和输出数据的通道数不会发生变化。
从上面池化运算的特点可知,经过池化运算后,可以将输入数据的维度减少,以减少中间层的运算。
池化一般包含Max和Average两类,其参数有:
- 池化层的滤波器大小:f
- 步长:s
经过池化运算后,其输出层的大小计算公式为:
n
h
−
f
s
+
1
\frac{n_h - f}{s} + 1
snh−f+1
完整的卷积神经网络
下面把卷积神经网络中涉及到的不同的层进行拼接,来完成一个完成的卷积神经网络的计算,该网络的层次为Input0-(Conv1-Pool1)-(Conv2-Pool2)-FC3-FC4-Softmax-
y
^
\hat y
y^。
这里,一般会将(Conv-Pool)作为一个网络层(有的地方可能会只把有参数的conv层作为一层)。
根据上面的计算过程,可以得到每一步的维度及其涉及到的参数的数量,具体如下所示:
为什么卷积神经网络很有用呢?
再回到最开始提出的问题,为什么卷积神经网络对计算机视觉来说很有用呢?最主要的原因还是通过卷积神经网络,所需要的参数相比全连接层(神经网络)会大大的减少。
比如全连接层的参数数量是
n
[
l
]
∗
n
[
l
−
1
]
n^{[l]}*n^{[l-1]}
n[l]∗n[l−1],很大。而在卷积运算中,其=参数只与滤波器的大小和数量相关,其大小为
(
f
[
l
]
∗
f
[
l
]
∗
n
c
[
l
−
1
]
+
1
)
∗
n
c
[
l
]
(f^{[l]} * f^{[l]} * n_c^{[l-1]} + 1) * n_c^{[l]}
(f[l]∗f[l]∗nc[l−1]+1)∗nc[l]。
另外,对卷积神经网络,还有下面两个特点:
- 对图片中不同区域的要素,检测(滤波器)参数可以共享
- 每一次计算的输出都是输入数据中的很小一部分(滤波器的大小决定)
最后,是应用卷积神经网络的一个完整过程: