第七章 卷积神经网络
卷积神经网络(CNN)。CNN被用于图像识别、语音识别等各种场合,在图像识别的比赛中,基于深度学习的方法几乎都以CNN为基础。
1.整体结构
了解CNN的网络结构和大致框架。CNN和之前介绍的神经网络一样,可以像乐高积木一样通过组装层来构建。不过,CNN中新出现了卷积层(Convolution层)和池化层(Pooling层)。
之前介绍的神经网络中,相邻层的所有神经元之间都有连接,这称为全连接。另外,我们使用了Affine层实现了全连接层。CNN中新增了Convolution层和Pooling层。CNN的连接顺序是“Convolution—ReLU—(Pooling)”,Pooling层有时会被省略。
2.卷积层
CNN中出现了一些特有的术语,比如填充、步幅等。此外,各层中传递的数据是有形状的数据,这与之前的全连接网络不同。
(1)全连接层存在的问题
之前介绍的全连接的神经网络使用了全连接层(Affine层)。在全连接层中,相邻层的神经元全部连接在一起,输出的数量可以任意决定。
全连接层存在的问题:数据的形状被“忽视”了。
而卷积层可以保持形状不变,当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此,在CNN中,可以(有可能)正确理解图像等具有形状的数据。
另外,CNN中,有时将卷积层的输入输出数据称为特征图。其中,卷积层的输入数据称为输入特征图,输出数据称为输出特征图。
(2)卷积运算
卷积层进行的处理就是卷积运算。卷积运算相当于图像处理中的“滤波器运算”。
在全连接的神经网络中,除了权重参数,还存在偏置。CNN中,滤波器的参数就对应之前的权重。并且,CNN中也存在偏置。偏置通常只有1个(1×1),这个值会被加到应用了滤波器的所有元素上。
(3)填充
在进行卷积层的处理之前,有时要相输入数据的周围填入固定的数据(比如0等),这称为填充,是卷积运算中经常会用到的处理。
使用填充主要是为了调整输出的大小。如果每次进行卷积运算都会缩小空间,那么在某个时刻输出大小就有可能变成1,导致无法再应用卷积运算。为了避免这样的情况,就要使用填充。
使用填充后,卷积运算可以在保持空间大小不变得情况下将数据传给下一层。
(4)步幅
应用滤波器的位置间隔称为步幅。
增大步幅后,输出大小会变小。而增大填充后,输出大小会变大。
(5)3维数据的卷积运算
对加上了通道方向的3维数据进行卷积运算的例子。
通道方向上有多特征图时,会按通道进行输入数据和滤波器的卷积运算,并将结果相加,从而得到输出。
需要注意的是,在3维数据的卷积运算中,输入数据和滤波器的通道数要设置为相同的值,滤波器的大小可以设定为任意值,不过,每个通道的滤波器大小要全部相同。
(6)结合方块思考
卷积运算中(和全连接层一样)存在偏置。每个通道只有一个偏置。两个方块相加时,要对滤波器的输出结果按通道加上相同的偏置值。
(7)批处理
神经网络的处理中进行了将输入数据打包的批处理。通过批处理,能够实现处理的高效化和学习时mini-batch的对应。
批处理将N次的处理汇总成了1次进行。
3.池化层
池化是缩小高、长方向上的空间的运算。
一般来说,池化的窗口大小会和步幅设定成相同的值。
Max池化是获取最大值的运算。除了Max池化之外,还有Average池化等。相对于Max池化是从目标区域中取出最大值,Average池化则是计算目标区域的平均值。在图像识别领域,主要使用Max池化。
池化层的特征:
1)没有要学习的参数:池化只是从目标区域中取最大值(或者平均值),所以不存在要学习的参数。
2)通道数不发生变化:经过池化运算,输入数据和输出数据的通道数不会发生变化。计算是按通道独立进行的。
3)对微小的位置变化具有鲁棒性(健壮):输入数据发生微小偏差时,池化仍会返回相同的结果。因此,池化对输入数据的微小偏差具有鲁棒性。
4.4维数组
(1)4维数组
CNN中各层间传递的数据是4维数组。所谓4维数组,比如数据的形状是(10,1,28,28),则它对应10个高为28,长为28,通道为1的数据。
像这样,CNN中处理的是4维数据,因此卷积运算的实现看上去会很复杂,但是通过im2col这个技巧,问题就会变得很简单。
(2)基于im2col的展开
如果老老实实地实现卷积运算,估计要重复好几层的for语句。这样的实现有点麻烦,而且,NumPy中存在使用for语句后处理变慢的缺点(NumPy中,访问元素时最好不要用for语句)。
im2col是一个函数,将输入数据展开以适合滤波器(权重)。对3维的输入数据应用im2col后,数据转换为2维矩阵(正确的讲,是把包含批数量的4维数据转换成了2维数据)。
im2col会把输入数据展开以适合滤波器(权重)。具体的说,对于输入数据,将应用滤波器的区域(3维方块)横向展开为1列。im2col会在所有应用滤波器的地方进行这个展开处理。
在实际的卷积运算中,滤波器的应用区域几乎都是重叠的。在滤波器的应用区域重叠的情况下,使用im2col展开后,展开后的元素个数会多于原方块的元素个数。因此,使用im2col的实现存在比普通的实现消耗更多内存的缺点。但是,汇总成一个大的矩阵进行计算,对计算机的计算颇有益处。
im2col这个名称是“image to column”的缩写,翻译过来就是“从图像到矩阵”的意思。
使用im2col展开输入数据后,之后就只需要将卷积层的滤波器(权重)纵向展开为1列,并计算2个矩阵的乘积即可。基于im2col方式的输出结果是2维矩阵。但因为CNN中数据会保存为4维数组,所以要将2维输出数据转换为合适的形状。
(3)卷积层的实现
本书提供了im2col函数,并将这个im2col函数作为黑盒(不关心内部实现)使用。
本实现中,forward的实现中,最后会将输出大小转换为合适的形状。转换时使用了NumPy的transpose函数。transpose会更改多维数组的轴的顺序。通过指定从0开始的索引(编号)序列,就可以更改轴的顺序。
接下来就是卷积层的反向传播的实现,在进行卷积层的反向传播时,必须进行im2col的逆处理。
(4)池化层的实现
池化层的实现和卷积层相同,都使用im2col展开输入数据。不过,池化的情况下,在通道方向上是独立的,这一点和卷积层不同。池化的应用区域按通道单独展开,展开后只需对展开的矩阵求各行的最大值,并转换为合适的形状即可。
5.CNN的实现
CNN的实现中,网络的构成是“Convolution-ReLU-Poolin-Affine-ReLU-Affine-Softmax”。由第1层的卷积层和剩余两个全连接层组成。
这里,参数x是输入数据,t是教师标签。用于推理的predict方法从头开始依次调用已添加的层,并将结果传递给下一层。
在求损失函数的loss方法中,除了使用predict方法进行的forward处理之外,还会继续进行forward处理,直到到达最后的SoftmaxWithLoss层。
参数的梯度通过误差反向传播法(反向传播)求出,通过把正向传播和反向传播组装在一起来完成。因为已经在各层正确实现了正向传播和反向传播的功能,所以这里只需要以合适的顺序调用即可。
最后,把各个权重参数的梯度保存到grads字典中。这就是SimpleConvNet的实现。
如果使用MNIST数据集训练SimpleConvNet,则训练数据的识别率为99.82%,测试数据的识别率为98.96%。测试数据的识别率大约为99%,就小型网络来说,这是一个非常高的识别率。
下一章,我们会通过进一步叠加层来加深网络,实现测试数据的识别率超过99%的网络。
如上所述,,卷积层和池化层是图像识别中必备的模块。CNN可以有效读取图像中某种特性,在手写数字识别中,还可以实现高精度的识别。
6.CNN的可视化
本节将通过卷积层的可视化,探索CNN中到底进行了什么处理。
(1)第1层权重的可视化
滤波器可以可视化为1通道的灰度图像。我们将卷积层(第1层)的滤波器显示为图像,比较一下学习前和学习后的权重,学习前的滤波器是随机进行初始化的,所以在黑白的浓淡上没有规矩可循,但学习后的滤波器变成了有规律的图像。我们发现,通过学习,滤波器被更新成了有规律的滤波器,比如从白到黑渐变的滤波器、含有块状区域(称为blob)的滤波器等。
有规律的滤波器在观察边缘(颜色变化的分界线)和斑块(局部的块状区域)等。比如,左半部分为白色,右半部分为黑色的滤波器的情况下,会对垂直方向上的边缘有响应。
卷积层的滤波器会提取边缘过斑块等原始信息。而刚才实现的CNN会将这些原始信息传递给后面的层。
(2)基于分层结构的信息提取
上面的结果是针对第一层的卷积层得出的。第一层的卷积层中提取了边缘或斑块等“低级”信息,根据深度学习的可视化相关的研究,随着层次加深,提取的信息(正确的讲,是反应强烈的神经元)也越来越抽象。
如果堆叠了多层卷积层,则随着层次加深,提取的信息也愈加复杂、抽象,这是深度学习中很有意思的一个地方。最开始的层对简单的边缘有响应,接下来的层对纹理有响应,再后面的层对更加复杂的物体部件有响应。也就是说,随着层次加深,神经元从简单的形状向“高级”信息变化。
7.具有代表性的CNN
(1)LeNet
LetNet在1998年被提出,是进行手写数字识别的网络。它有连续的卷积层和池化层(正确的讲,是只“抽选元素”的子采样层),最后经全连接层输出结果。
和现在的CNN相比,LeNet有几个不同点。第一个不同点在于激活函数。LeNet中使用sigmoid函数,而现在的CNN中主要使用ReLU函数。此外,原始的LeNet中使用子采样(subsampling)缩小中间数据的大小,而现在的CNN中Max池化是主流。
(2)AlexNet
AlexNet的网络结构和LeNet基本上没有什么不同。AlexNet叠有多个卷积层和池化层,最后经由全连接层输出结果。虽然结构上AlexNet和LeNet没有大的不同,但是有以下几点差异:
1)激活函数使用ReLU
2)使用进行局部正规化的LRN(Local Response Normalization)层
3)使用Dropout
如上所述,关于网络结构,AlexNet和LeNet没有太大的不同。但是,围绕它们的环境和计算机技术有了很大的进步。具体的说,现在任何人都可以获得大量的数据。而且,擅长大规模并行计算的GPU得到普及,高速进行大量的运算已经成为可能。大数据和GPU已成为深度学习发展的巨大的原动力。
大多数情况下深度学习(加深了层次的网络)存在大量的参数。因此,学习需要大量的计算,并且需要使那些参数“满意”的大量数据。