一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)

一、前言

卷积神经网络(Convolutional Neural Network,CNN)出现之前,神经网络中相邻的所有神经元之间都有连接,这称为全连接(fully-connected),如图1所示

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图1 全连接(fully-connected)

这种全连接方式会带来一个问题,如图2所示,假设输入图像大小为 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,隐藏层一共有 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 个神经元,如果采用全连接的方式的话,那一共有 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 条连接,即 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 个权重,这么多的参数,如果每个参数都是浮点类型存储,可以想象这是多么恐怖,另外,不说别的,参数那么多,模型训练时容易学习到无关紧要的特征,容易导致过拟合,即在训练集中表现得很好,而在其它数据集中表现很差,具备很差的泛化能力

然而有科学研究,人眼去观察外界时,是通过先观察物体的局部信息,然后通过这些局部信息从而获得全局信息,即识别这个物体是什么.所以根据这个原理去设计神经网络的话,每一个神经元都不需要对全局图像做感受,每个神经元只感受局部的图像区域,然后在更高层,将这些感受不同局部的神经元综合起来就可以得到全局的信息了。显然,这种连接方式大大减少了连接数目,也就是减少了权重参数

这里也就出现了我们经常说的感受野(Receptive Field),即某个神经元能看到的输入图像的区域,关于更多Receptive Field的知识我前面有专栏详细讲解它的理解和计算

玖零猴:感受野(Receptive Field)的理解与计算

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图2 全连接和局部连接(来自[1])

假如局部感受野是一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图),隐层每个感受野只需要和这一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)的局部图像相连接,所以这 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 的隐层神经元就只有一亿个连接,即 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 个权重参数。比原来的 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 少了四个数量级,这样训练起来就没那么费力了,但还是感觉依旧很多参数!

其实,我们还漏掉了偏置参数(bias),每个神经元的输出公式应该为 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)

从上面分析可知,隐含层的每一个神经元都连接一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)图像区域,也就是说每一个神经元存在100个连接,即每个神经元有100个权重参数和1个偏置参数,那如果每个神经元都共享相同的权重参数和偏置参数呢?于是,就出现了我们熟知的共享权重共享偏置(统称共享权值),这样一来两层的连接就只有101个参数了,是不是非常妙啊?

为了加深大家对以上所有过程的认识,我们用图3形象地表达下从全连接到局部连接再到共享权值的过程

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图3 全连接-局部连接-权值共享

二、卷积层

而卷积层就是干了这些事情,每个神经元局部连接上一层的神经元,并且共享权值。

其实, 就是我们经常看到的图4,利用卷积实现了局部连接,然后输出数据里的每个神经元通过同一个卷积核(共享权重)去卷积图像后再加上同一个偏置(共享偏置)得到的,如果没有用共享权值,那么一个神经元需要对应一个卷积核一个偏置,而现在是每个神经元对应的是同一个卷积核同一个偏置,显然参数量大幅下降

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图4 卷积(来自[2])

卷积层中进行的处理叫卷积运算,相当于图像处理中的滤波器运算,用来作卷积运算的东西叫卷积核(也叫核、滤波器或者过滤器),下图5演示卷积过程,下面蓝色的表示输入数据,蓝色上有 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 大小的阴影面积的是卷积核,每一次卷积操作则将卷积核上的每个元素和对应输入数据的元素相乘,最后把所有的结果相加,即为本次卷积的结果(一个绿色),然后将卷积核移动一个步长(stride)接着下一次卷积,直到卷积核遍历完输入数据即可

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图5 卷积动图 (图来自[3])

有时候还会在​​卷积操作之前向输入数据的周围填充固定的数据(比如0等),这个称为填充(padding),填充为1时,向周围填充一圈,填充为2时,向周围填充两圈.

不同的卷积核大小,不同的填充大小,不同的步长都会影响输出数据的尺寸,直接上公式,假设输入大小 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,卷积核的大小 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,填充 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,步长 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,输出大小 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)

上述的情况是输入数据为单通道,而在实际情况中,输入数据多为多通道,那这个时候又是如何进行卷积呢?如图6所示,卷积核的通道一定要等于输入数据的通道,而其它都是一样的,比如卷积过程是一样的,只不过数据在处理时多算了一个维度,此外,输出数据的尺寸计算上述公式同样适用,通道是不影响输出数据的尺寸.下图省略了 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 个偏置,输出数据的每个元素应该加上这个偏置

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图6 单个卷积核作卷积(来自[2])

从上面的卷积过程中,我们很明显地发现,不管输入数据是单通道还是多通道,输出数据依旧是单通道.这是因为我们只用了一个卷积核,也就是说卷积核的数量 = 输出数据的通道数,即一个卷积核对应一个通道的输出数据.另外,每个通道的输出数据也对应一个偏置进行相加

如图7所示,输入数据为 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 经过 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 个卷积核 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 后得到的输出数据为 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,然后每个通道的输出数据对应一个偏置与它们的元素进行相加

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图7 多个卷积核作卷积(来自[2])

讲完了卷积操作之后,我们再回到开始的话题,用共享的卷积核和偏置确实减少了大量的参数,可是这非常不靠谱,一个卷积核一个偏置就能够把数据所有的特征全部提取出来了?这显然做不到,怎么办?没错,如图7所示的那样,用多组(卷积核和偏置)不就行了吗?每一组的参数不一样所提取的特征也不一样,图中可以有 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) 个特征,并且有一点特别重要:即使我增加了一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)组这样的参数,参数量的增加也只是单纯地相乘,即 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,远远小于全连接层时的那些数量.

综上所述, 卷积层不仅大大地减少了参数量,并且还不影响特征的提取

三、池化层

CNN除了新增卷积层外,还新增了池化层,池化(pooling)是用来缩小数据尺寸的运算

在正式讲之前,解释一下特征图(feature map),有时将卷积层或者池化层的输入输出数据称为特征图(feature map),输入数据称为输入特征图(input feature map),输出数据称为输出特征图(output feature map),因此在卷积层中卷积核的数量是等于输出特征图的数量,因为我们知道一个卷积核提取一个特征.

卷积层之后一般是pooling层,池化操作也有一个类似卷积核一样东西在特征图上移动,书[2]中叫它池化窗口,所以这个池化窗口也有大小,移动的时候有步长,池化前也有填充操作,每次移动池化窗口一般要计算的是窗口里的最大值(Max)或者平均值(Average)。

如图8所示,池化窗口为 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,无填充,步长为 一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图) ,Max池化.一般来说,池化的窗口大小会和步长设定相同的值

一文看懂CNN(卷积池化、感受野、共享权重和偏置、特征图)
图8 Max池化 (来自[2])

池化层有三个特征:

  1. 没有要学习的参数,这和池化层不同.池化只是从目标区域中取最大值或者平均值,所以没有必要有学习的参数
  2. 通道数不发生改变,即不改变feature map的数量
  3. 它是利用图像局部相关性的原理,对图像进行子抽样,这样在保留有用信息的,对微小的位置变化具有鲁棒性(健壮), 输入数据发生微小偏差时, 池化仍会返回相同的结果


reference

1、理解卷积神经网络CNN中的特征图 feature map

2、《深度学习入门基于Python的理论与实现》

3、卷积动图来源