深度学习根底入门篇[9.1]:卷积之规范卷积:卷积核/特色图/卷积计算、填充、感触视线、多通道输入输出、卷积劣势和利用案例解说
1.卷积提出背景
在全连贯网络[1]中,一张图片上的所有像素点会被开展成一个1维向量输出网络,如 图1 所示,28 x 28的输出数据被开展成为784 x 1 的数据作为输出。
图1 全连贯网络图
这样往往会存在如下两个问题:
1. 输出数据的空间信息被失落。 空间上相邻的像素点往往具备类似的RGB值,RGB的各个通道之间的数据通常密切相关,然而转化成1维向量时,这些信息被失落。如 图2 所示,空间地位相邻的两个点A和B,转化成1维向量后并没有体现出他们之间的空间关联性。
图2 图片转换为1维向量
2. 模型参数过多,容易产生过拟合。 因为每个像素点都要跟所有输入的神经元相连接。当图片尺寸变大时,输出神经元的个数会按图片尺寸的平方增大,导致模型参数过多,容易产生过拟合。例如:对于一幅$1000\times 1000$ 的输出图像而言,如果下一个隐含层的神经元数目为$10^6$ 个,那么将会有$1000\times 1000\times 10^6=10^{12}$ 个权重参数,能够设想,如此大规模的参数量使得网络很难训练。
为了解决上述问题,引入卷积(Convolution)来对输出的图像进行特征提取。卷积的计算范畴是在像素点的空间邻域内进行的,因而能够利用输出图像的空间信息;此外,因为卷积具备部分连贯、权重共享等个性,卷积核参数的数目也远小于全连贯层。
2.卷积核 / 特色图 / 卷积计算
卷积核(kernel):也被叫做滤波器(filter),假如卷积核的高和宽别离为$k_h$和$k_w$,则将称为$k_h\times k_w$卷积,比方$3\times5$卷积,就是指卷积核的高为3, 宽为5。卷积核中数值为对图像中与卷积核同样大小的子块像素点进行卷积计算时所采纳的权重。
卷积计算(convolution):图像中像素点具备很强的空间依赖性,卷积(convolution)就是针对像素点的空间依赖性来对图像进行解决的一种技术。
特色图(feature map):卷积滤波后果在卷积神经网络中被称为特色图(feature map)。
2.1 卷积计算利用示例
在卷积神经网络中,卷积层的实现形式实际上是数学中定义的相互关 (cross-correlation)运算,具体的计算过程如 图3 所示,每张图的左图示意输出数据是一个维度为3 x 3的二维数组;两头的图示意卷积核是一个维度为2 x 2的二维数组。
图3 卷积计算过程
- 如图3(a)所示:右边的图大小是$3\times3$,示意输出数据是一个维度为$3\times3$的二维数组;两头的图大小是$2\times2$,示意一个维度为$2\times2$的二维数组,咱们将这个二维数组称为卷积核。先将卷积核的左上角与输出数据的左上角(即:输出数据的(0, 0)地位)对齐,把卷积核的每个元素跟其地位对应的输出数据中的元素相乘,再把所有乘积相加,失去卷积输入的第一个后果:
$$0\times1 + 1\times2 + 2\times4 + 3\times5 = 25 \ \ \ \ \ \ \ (a)$$
- 如图3(b)所示:将卷积核向右滑动,让卷积核左上角与输出数据中的(0,1)地位对齐,同样将卷积核的每个元素跟其地位对应的输出数据中的元素相乘,再把这4个乘积相加,失去卷积输入的第二个后果:
$$0\times2 + 1\times3 + 2\times5 + 3\times6 = 31 \ \ \ \ \ \ \ (b)$$
- 如图3(c)所示:将卷积核向下滑动,让卷积核左上角与输出数据中的(1, 0)地位对齐,能够计算失去卷积输入的第三个后果:
$$0\times4 + 1\times5 + 2\times7 + 3\times8 = 43 \ \ \ \ \ \ \ (c)$$
- 如图3(d)所示:将卷积核向右滑动,让卷积核左上角与输出数据中的(1, 1)地位对齐,能够计算失去卷积输入的第四个后果:
$$0\times5 + 1\times6 + 2\times8 + 3\times9 = 49 \ \ \ \ \ \ \ (d)$$
最终能够失去图3(d)右侧所示的特色图。
卷积核的计算过程能够用上面的数学公式示意,其中 $a$ 代表输出图片, $b$ 代表输入特色图,$w$ 是卷积核参数,它们都是二维数组, $\sum{u,v}{\ }$ 示意对卷积核参数进行遍历并求和。
$$b[i, j] = \sum_{u,v}{a[i+u, j+v]\cdot w[u, v]}$$
举例说明,如果上图中卷积核大小是$2\times 2$,则$u$能够取0和1,$v$也能够取0和1,也就是说:
$$b[i, j] = a[i+0, j+0]\cdot w[0, 0] + a[i+0, j+1]\cdot w[0, 1] + a[i+1, j+0]\cdot w[1, 0] + a[i+1, j+1]\cdot w[1, 1]$$
读者能够自行验证,当$[i, j]$取不同值时,依据此公式计算的后果与上图中的例子是否统一。
思考:
为了可能更好地拟合数据,在卷积神经网络中,一个卷积算子除了下面形容的卷积过程之外,还包含加上偏置项的操作。例如假如偏置为1,则下面卷积计算的后果为:
$$0\times1 + 1\times2 + 2\times4 + 3\times5 \mathbf{\ + 1} = 26$$
$$0\times2 + 1\times3 + 2\times5 + 3\times6 \mathbf{\ + 1} = 32$$
$$0\times4 + 1\times5 + 2\times7 + 3\times8 \mathbf{\ + 1} = 44$$
$$0\times5 + 1\times6 + 2\times8 + 3\times9 \mathbf{\ + 1} = 50$$
阐明:
- 输出图像的边缘像素因其处于边缘地位,因而无奈参加卷积计算;
- 图像卷积计算本质上是对图像进行了下采样 (down sampling)操作。对卷积失去的图像后果一直卷积滤波,则原始图像就会被“层层形象、层层约减”,从而使得蕴涵在图像中的重要信息“显山露水”;
- 卷积核中的权重系数$w_i$是通过数据驱动机制学习失去,其用来捕捉图像中某像素点及其邻域像素点所形成的特有空间模式。一旦从数据中学习失去权重系数,这些权重系数就刻画了图像中像素点形成的空间散布不同模式。
3.填充(Padding)
输出图像边缘地位的像素点无奈进行卷积滤波,为了使边缘像素也参加卷积滤波,填充技术应运而生。填充是指在边缘像素点四周填充“0”(即0填充),使得输出图像的边缘像素也能够参加卷积计算。留神,在这种填充机制下,卷积后的图像分辨率将与卷积前图像分辨率统一,不存在下采样。
3.1填充利用示例
在下面的例子中,输出图片尺寸为$3\times3$,输入图片尺寸为$2\times2$,通过一次卷积之后,图片尺寸变小。卷积输入特色图的尺寸计算方法如下(卷积核的高和宽别离为$k_h$和$k_w$):
$$H_{out} = H - k_h + 1$$
$$W_{out} = W - k_w + 1$$
如果输出尺寸为4,卷积核大小为3时,输入尺寸为$4-3+1=2$。读者能够自行查看当输出图片和卷积核为其余尺寸时,上述计算式是否成立。当卷积核尺寸大于1时,输入特色图的尺寸会小于输出图片尺寸。如果通过屡次卷积,输入图片尺寸会一直减小。为了防止卷积之后图片尺寸变小,通常会在图片的外围进行填充(padding),如 图4 所示。
图4 图形填充
- 如图4(a)所示:填充的大小为1,填充值为0。填充之后,输出图片尺寸从$4\times4$变成了$6\times6$,应用$3\times3$的卷积核,输入图片尺寸为$4\times4$。
- 如图4(b)所示:填充的大小为2,填充值为0。填充之后,输出图片尺寸从$4\times4$变成了$8\times8$,应用$3\times3$的卷积核,输入图片尺寸为$6\times6$。
如果在输出图片第一行之前填充$p_{h1}$行,在最初一行之后填充$p_{h2}$行;在图片第1列之前填充$p_{w1}$列,在最初1列之后填充$p_{w2}$列;则填充之后的图片尺寸为$(H + p_{h1} + p_{h2})\times(W + p_{w1} + p_{w2})$。通过大小为$k_h\times k_w$的卷积核操作之后,输入图片的尺寸为:
$$H_{out} = H + p_{h1} + p_{h2} - k_h + 1$$
$$W_{out} = W + p_{w1} + p_{w2} - k_w + 1$$
在卷积计算过程中,通常会在高度或者宽度的两侧采取等量填充,即$p_{h1} = p_{h2} = p_h,\ \ p_{w1} = p_{w2} = p_w$,下面计算公式也就变为:
$$H_{out} = H + 2p_h - k_h + 1$$
$$W_{out} = W + 2p_w - k_w + 1$$
为了便于padding,卷积核大小通常应用1,3,5,7这样的奇数,这样如果应用的填充大小为$p_h=(k_h-1)/2 ,p_w=(k_w-1)/2$,则能够使得卷积之后图像尺寸不变。例如当卷积核大小为3时,padding大小为1,卷积之后图像尺寸不变;同理,如果卷积核大小为5,padding大小为2,也能放弃图像尺寸不变。
4.步长(Stride)
在卷积操作时,通常心愿输入图像分辨率与输出图像分辨率相比会逐步缩小,即图像被约减。因而,能够通过扭转卷积核在输出图像中挪动步长大小来跳过一些像素,进行卷积滤波。当Stride=1时,卷积核滑动跳过1个像素,这是最根本的单步滑动,也是规范的卷积模式。Stride=k示意卷积核挪动跳过的步长是k。
- 利用示例
图3 中卷积核每次滑动一个像素点,这是步长为1的状况。图5 是步长为2的卷积过程,卷积核在图片上挪动时,每次挪动大小为2个像素点。
图5 步幅为2的卷积过程
当高和宽方向的步幅别离为$s_h$和$s_w$时,输入特色图尺寸的计算公式是:
$$H_{out} = \frac{H + 2p_h - k_h}{s_h} + 1$$
$$W_{out} = \frac{W + 2p_w - k_w}{s_w} + 1$$
思考:
假如输出图片尺寸是$H\times W = 100 \times 100$,卷积核大小$k_h \times k_w = 3 \times 3$,填充$p_h = p_w = 1$,步长为$s_h = s_w = 2$,则输入特色图的尺寸为:
$$H_{out} = \frac{100 + 2 - 3}{2} + 1 = 50$$
$$W_{out} = \frac{100 + 2 - 3}{2} + 1 = 50$$
5.感触野(Receptive Field)
卷积所得后果中,每个特色图像素点取值依赖于输出图像中的某个区域,该区域被称为感触野(receptive field),正所谓“管中窥豹、见微知著”。那么这个区域在哪呢,在卷积神经网络中,感触野是特色图(feature map)上的点对应输出图像上的区域。感触野内每个元素数值的变动,都会影响输入点的数值变动。
利用示例
比方$3\times3$卷积对应的感触野大小就是$3\times3$,如 图6 所示。
图6 感触野为3×3的卷积
而当通过两层$3\times3$的卷积之后,感触野的大小将会减少到$5\times5$,如 图7 所示。
图7 感触野为5×5的卷积
因而,当减少卷积网络深度的同时,感触野将会增大,输入特色图中的一个像素点将会蕴含更多的图像语义信息。
6.多输出通道、多输入通道和批量操作
后面介绍的卷积计算过程比较简单,理论利用时,解决的问题要简单的多。例如:对于彩色图片有RGB三个通道,须要解决多输出通道的场景,相应的输入特色图往往也会具备多个通道。而且在神经网络的计算中经常是把一个批次的样本放在一起计算,所以卷积算子须要具备批量解决多输出和多输入通道数据的性能。
6.1多输出通道场景
当输出含有多个通道时,对应的卷积核也应该有雷同的通道数。假如输出图片的通道数为$C_{in}$,输出数据的形态是$C_{in}\times{H_{in}}\times{W_{in}}$。
- 对每个通道别离设计一个2维数组作为卷积核,卷积核数组的形态是$C_{in}\times{k_h}\times{k_w}$。
- 对任一通道$C_{in} \in [0, C_{in})$,别离用大小为$k_h\times{k_w}$的卷积核在大小为$H_{in}\times{W_{in}}$的二维数组上做卷积。
- 将这$C_{in}$个通道的计算结果相加,失去的是一个形态为$H_{out}\times{W_{out}}$的二维数组。
下面的例子中,卷积层的数据是一个2维数组,但实际上一张图片往往含有RGB三个通道,要计算卷积的输入后果,卷积核的模式也会发生变化。假如输出图片的通道数为$3$,输出数据的形态是$3\times{H_{in}}\times{W_{in}}$,计算过程如 图8 所示。
- 对每个通道别离设计一个2维数组作为卷积核,卷积核数组的形态是$3\times{k_h}\times{k_w}$。
- 对任一通道$c_{in} \in [0, 3)$,别离用大小为$k_h\times{k_w}$的卷积核在大小为$H_{in}\times{W_{in}}$的二维数组上做卷积。
- 将这$3$个通道的计算结果相加,失去的是一个形态为$H_{out}\times{W_{out}}$的二维数组。
图8 多输出通道计算过程
6.2 多输入通道场景
如果咱们心愿检测多种类型的特色,实际上咱们能够应用多个卷积核进行计算。所以一般来说,卷积操作的输入特色图也会具备多个通道$C_{out}$,这时咱们须要设计$C_{out}$个维度为$C_{in}\times{k_h}\times{k_w}$的卷积核,卷积核数组的维度是$C_{out}\times C_{in}\times{k_h}\times{k_w}$。
- 对任一输入通道$c_{out} \in [0, C_{out})$,别离应用下面形容的形态为$C_{in}\times{k_h}\times{k_w}$的卷积核查输出图片做卷积。
- 将这$C_{out}$个形态为$H_{out}\times{W_{out}}$的二维数组拼接在一起,造成维度为$C_{out}\times{H_{out}}\times{W_{out}}$的三维数组。
利用示例¶
假如输出图片的通道数为3,咱们心愿检测2种类型的特色,这时咱们须要设计$2$个维度为$3\times{k_h}\times{k_w}$的卷积核,卷积核数组的维度是$2\times 3\times{k_h}\times{k_w}$,如 图9 所示。
- 对任一输入通道$c_{out} \in [0, 2)$,别离应用下面形容的形态为$3\times{k_h}\times{k_w}$的卷积核查输出图片做卷积。
- 将这$2$个形态为$H_{out}\times{W_{out}}$的二维数组拼接在一起,造成维度为$2\times{H_{out}}\times{W_{out}}$的三维数组。
图9 多输入通道计算过程
6.2 批量操作
在卷积神经网络的计算中,通常将多个样本放在一起造成一个mini-batch进行批量操作,即输出数据的维度是$N\times{C_{in}}\times{H_{in}}\times{W_{in}}$。因为会对每张图片应用同样的卷积核进行卷积操作,卷积核的维度是$C_{out}\times C_{in}\times{k_h}\times{k_w}$,那么,输入特色图的维度就是$N\times{C_{out}}\times{H_{out}}\times{W_{out}}$。
- 利用示例
假如咱们输出数据的维度是$2\times{3}\times{H_{in}}\times{W_{in}}$,卷积核的维度与下面多输入通道的状况一样,依然是$2\times 3\times{k_h}\times{k_w}$,输入特色图的维度是$2\times{2}\times{H_{out}}\times{W_{out}}$。如 图10 所示。
图10 批量操作
7. 卷积劣势
- 保留空间信息
在卷积运算中,计算范畴是在像素点的空间邻域内进行的,它代表了对空间邻域内某种特色模式的提取。比照全连贯层将输出开展成一维的计算形式,卷积运算能够无效学习到输出数据的空间信息。
- 部分连贯
在上文中,咱们介绍了感触野的概念,能够想像,在卷积操作中,每个神经元只与部分的一块区域进行连贯。对于二维图像,部分像素关联性较强,这种部分连贯保障了训练后的滤波器可能对部分特色有最强的响应,使神经网络能够提取数据的部分特色。全连贯与部分连贯的对比方 图11 所示。
图11 全连贯与部分连贯
同时,因为应用了部分连贯,隐含层的每个神经元仅与局部图像相连,思考本文开篇提到的例子,对于一幅$1000\times 1000$ 的输出图像而言,下一个隐含层的神经元数目同样为$10^6$ 个,假如每个神经元只与大小为$10\times 10$ 的部分区域相连,那么此时的权重参数量仅为$10\times 10\times 10^6=10^{8}$ ,相交密集链接的全连贯层少了4个数量级。
- 权重共享
卷积计算实际上是应用一组卷积核在图片上进行滑动,计算乘加和。因而,对于同一个卷积核的计算过程而言,在与图像计算的过程中,它的权重是共享的。这其实就大大降低了网络的训练难度, 图12 为权重共享的示意图。这里还应用上边的例子,对于一幅$1000\times 1000$ 的输出图像,下一个隐含层的神经元数目为$10^6$ 个,隐含层中的每个神经元与大小为$10\times 10$ 的部分区域相连,因而有$10\times 10$ 个权重参数。将这$10\times 10$ 个权重参数共享给其余地位对应的神经元,也就是$10^6$ 个神经元的权重参数保持一致,那么最终须要训练的参数就只有这$10\times 10$个权重参数了。
图12 权重共享示意图
- 不同层级卷积提取不同特色
在CNN网络中,通常应用多层卷积进行重叠,从而达到提取不同类型特色的作用。比方:浅层卷积提取的是图像中的边缘等信息;中层卷积提取的是图像中的部分信息;深层卷积提取的则是图像中的全局信息。这样,通过加深网络层数,CNN就能够无效地学习到图像从细节到全局的所有特色了。对一个简略的5层CNN进行特色图可视化后的后果如 图13所示 ^[1]^。
图13 特色图可视化示意图
通过上图能够看到,Layer1和Layer2种,网络学到的基本上是边缘、色彩等底层特色;Layer3开始变的略微简单,学习到的是纹理特色;Layer4中,学习到了更高维的特色,比方:狗头、鸡脚等;Layer5则学习到了更加具备辨识性的全局特色。
8.卷积利用示例
8.1 案例1:简略的黑白边界检测
上面是应用Conv2D算子实现一个图像边界检测的工作。图像右边为光洁局部,左边为光明局部,如 图14 所示,须要检测出光洁跟光明的分界处。
设置宽度方向的卷积核为$[1, 0, -1]$,如 图15 所示。此卷积核会将宽度方向距离为1的两个像素点的数值相减。当卷积核在图片上滑动时,如果它所笼罩的像素点位于亮度雷同的区域,则左右距离为1的两个像素点数值的差为0。只有当卷积核笼罩的像素点有的处于光洁区域,有的处在光明区域时,左右距离为1的两个点像素值的差才不为0。将此卷积核作用到图片上,输入特色图上只有对应黑白分界线的中央像素值才不为0。具体代码如下所示,输入图像如 图16 所示。
图14 输出图像
图15 卷积核
import matplotlib.pyplot as pltimport numpy as npimport paddlefrom paddle.nn import Conv2Dfrom paddle.nn.initializer import Assign%matplotlib inline# 创立初始化权重参数ww = np.array([1, 0, -1], dtype='float32')# 将权重参数调整成维度为[cout, cin, kh, kw]的四维张量w = w.reshape([1, 1, 1, 3])# 创立卷积算子,设置输入通道数,卷积核大小,和初始化权重参数# kernel_size = [1, 3]示意kh = 1, kw=3# 创立卷积算子的时候,通过参数属性weight_attr指定参数初始化形式# 这里的初始化形式时,从numpy.ndarray初始化卷积参数conv = Conv2D(in_channels=1, out_channels=1, kernel_size=[1, 3], weight_attr=paddle.ParamAttr( initializer=Assign(value=w)))# 创立输出图片,图片右边的像素点取值为1,左边的像素点取值为0img = np.ones([50,50], dtype='float32')img[:, 30:] = 0.# 将图片形态调整为[N, C, H, W]的模式x = img.reshape([1,1,50,50])# 将numpy.ndarray转化成paddle中的tensorx = paddle.to_tensor(x)# 应用卷积算子作用在输出图片上y = conv(x)# 将输入tensor转化为numpy.ndarrayout = y.numpy()f = plt.subplot(121)f.set_title('input image', fontsize=15)plt.imshow(img, cmap='gray')f = plt.subplot(122)f.set_title('output featuremap', fontsize=15)# 卷积算子Conv2D输入数据形态为[N, C, H, W]模式# 此处N, C=1,输入数据形态为[1, 1, H, W],是4维数组# 然而画图函数plt.imshow画灰度图时,只承受2维数组# 通过numpy.squeeze函数将大小为1的维度打消plt.imshow(out.squeeze(), cmap='gray')plt.show()
# 查看卷积层的权重参数名字和数值print(conv.weight)# 参看卷积层的偏置参数名字和数值print(conv.bias)
图16 输入图像
8.2案例2:图像中物体边缘检测¶
下面展现的是一个人为结构进去的简略图片,应用卷积网络检测图片明暗分界处的示例。对于实在的图片,如 图17 所示,也能够应用适合的卷积核,如 图18 所示。(3 x 3卷积核的两头值是8,四周一圈的值是8个-1)对其进行操作,用来检测物体的形状轮廓,察看输入特色图跟原图之间的对应关系,如下代码所示,输入图像如 图19 所示。
图17 输出图像
图18 卷积核
import matplotlib.pyplot as pltfrom PIL import Imageimport numpy as npimport paddlefrom paddle.nn import Conv2Dfrom paddle.nn.initializer import Assignimg = Image.open('./img/example1.jpg')# 设置卷积核参数w = np.array([[-1,-1,-1], [-1,8,-1], [-1,-1,-1]], dtype='float32')/8w = w.reshape([1, 1, 3, 3])# 因为输出通道数是3,将卷积核的形态从[1,1,3,3]调整为[1,3,3,3]w = np.repeat(w, 3, axis=1)# 创立卷积算子,输入通道数为1,卷积核大小为3x3,# 并应用下面的设置好的数值作为卷积核权重的初始化参数conv = Conv2D(in_channels=3, out_channels=1, kernel_size=[3, 3], weight_attr=paddle.ParamAttr( initializer=Assign(value=w))) # 将读入的图片转化为float32类型的numpy.ndarrayx = np.array(img).astype('float32')# 图片读入成ndarry时,形态是[H, W, 3],# 将通道这一维度调整到最后面x = np.transpose(x, (2,0,1))# 将数据形态调整为[N, C, H, W]格局x = x.reshape(1, 3, img.height, img.width)x = paddle.to_tensor(x)y = conv(x)out = y.numpy()plt.figure(figsize=(20, 10))f = plt.subplot(121)f.set_title('input image', fontsize=15)plt.imshow(img)f = plt.subplot(122)f.set_title('output feature map', fontsize=15)plt.imshow(out.squeeze(), cmap='gray')plt.show()
图19 输入图像
8.3案例3:图像均值含糊
对一张输出图像如 图20 所示,另外一种比拟常见的卷积核,如 图21 所示。(5*5的卷积核中每个值均为1)是用以后像素跟它邻域内的像素取均匀,这样能够使图像上噪声比拟大的点变得更平滑,如下代码所示,输入图像如 图22 所示。
图20 输出图像
图21 卷积核
import paddleimport matplotlib.pyplot as pltfrom PIL import Imageimport numpy as npfrom paddle.nn import Conv2Dfrom paddle.nn.initializer import Assign# 读入图片并转成numpy.ndarray# 换成灰度图img = Image.open('./img/example2.jpg').convert('L')img = np.array(img)# 创立初始化参数w = np.ones([1, 1, 5, 5], dtype = 'float32')/25conv = Conv2D(in_channels=1, out_channels=1, kernel_size=[5, 5], weight_attr=paddle.ParamAttr( initializer=Assign(value=w)))x = img.astype('float32')x = x.reshape(1,1,img.shape[0], img.shape[1])x = paddle.to_tensor(x)y = conv(x)out = y.numpy()plt.figure(figsize=(20, 12))f = plt.subplot(121)f.set_title('input image')plt.imshow(img, cmap='gray')f = plt.subplot(122)f.set_title('output feature map')out = out.squeeze()plt.imshow(out, cmap='gray')plt.show()
图22 输入图像
参考文献¶
[1] Visualizing and Understanding Convolutional Networks