由于公众号改版不再按照作者的发布时间进行推送,为防止各位朋友错过月来客栈推送的最新文章,大家可以手动将公众号设置为“星标”以第一时间获得推送内容,感谢各位~

1 前言
在前面的两篇文章中,笔者分别介绍了卷积的思想与原理以及卷积操作在各类场景下的具体计算过程。在接下来的这篇文中,笔者将主要围绕着卷积后形状的计算、卷积中的池化操作以及Pytorch中卷积操作的用法这三方面来进行介绍。在这篇文章后,对于卷积的基础知识就算是介绍完了,后面笔者将开始对一些经典的卷积网络进行介绍。
2 形状的计算
在前面一篇文章中,笔者详细介绍了卷积操作中的卷积计算过程,但是对于卷积后特征图形状的计算并没有进行介绍。下面,我们就来看看如何计算卷积后的形状。
2.1 输出形状
对于最后输出形状的计算在我们自己写代码的过程中是十分重要的,关系到你如何设置卷积核的大小,以及卷积的层数。现在我们用来表示输入特征图的宽度,表示卷积核的宽度,表示卷积核每移动一次的步长,那么此时卷积后特征图的宽度为:
其中表示对向上取整, 表示对向下取整。公式中的两种计算方法都行,记住其中一种即可。
例如有输入形状为的特征图,卷积核的形状为,同时步长为,那么卷积后的形状则为:
即的特征图。
2.2 Padding
从上面的计算过程可以看出,每卷积一次所得到特征图的大小都会小于输入时特征图的大小,但是在一些情况下我们更希望其卷积后的大小能够等同于输入时的大小。那这该怎么做呢?为了保持卷积后的特征图的大小与输入时一直,通常来说我们都会对输入的特征图进行填充(Padding),也就是把他的形状变大,这样卷积后的大小就可以与原始输入的特征图保持一致。
图 1. 填充图
如图1所示,左边为原始的特征图,其大小 ;右边为填充后的特征图,其大小变成了。对左右两边均用大小为的卷积核进行卷积(),那么卷积后左边的大小为,有右边的大小为。可以发现,经过填充处理后,就能够使得卷积后特征图的大小与输入时的大小保持一致。当然,如果是多通道的话,则对应在每个通道都这样填充即可。
同时,我们把图1中右边填充的参数称作,且此时的,即填充了圈。那现在假如原始的特征图大小为,卷积核大小为,步长为,并且希望卷积后特征图的大小为,那么此时对应的填充参数应该等于多少呢?其应该等于:
举两个例子:
例一:原始特征图大小为,卷积核大小为,,那么为何值时能够使得卷积后的大小与输入保持一致?
由公式可知,
即,将原始特征填充圈后,卷积后特征图的大小会与输入时保持一致(可以根据公式自行检验)。
例二:原始特征图大小为,卷积核大小为,,那么为何值时能够使得卷积后的大小为?
由公式可知,
即,将原始特征填充圈后,卷积后特征图的大小会变成。
当然,在实际过程中不会这么刁钻,通常情况下我们都是希望与输入的特征图大小保持一致。最后,对于池化操作来说,想要使得池化后的输出为特定的大小,也只需要按照上述方法进行填充即可。
3 池化
说起池化操作,它可以算是卷积神经网络中一个必不可少的步骤,几乎绝大多数卷积网络都用到了池化来提升网络模型的精度。但这也并不是一个必须的选项,你同样可以选择不用。那什么又是池化,为什么又需要池化呢?
3.1 什么是池化
所谓池化,你可以将其看作是一个信息筛选或者过滤的操作。池化操作使用某一位置的相邻输出的总体特征来代替网络在该位置的输出[1]。例如最大池化(max pooling)会给出相邻矩形区域内的最大值作为该位置的输出。除此之外还有最小池化(min pooling)和平均池化(average pooling)等。下面我们就来池化操作的具体计算步骤进行介绍。
3.2 池化的计算
如图2所示,左边为输入的特征图,右边为经过最大池化后的结果。
图 2. 单通道最大池化图
从图2可以看出,最大池化就是给定一个固定大小的滑动窗口,然后选择窗口中的最大值来代替整个区域作为输出,最后再依次对整个特征图进行池化操作就得到池化后的特征输出。同时可以发现,对于池化操作来说其并没有权重参数。
图 3. 多通道最大池化
如图3所示为多通道的池化操作,左边为输入的特征图,右边为池化后的特征图。可以发现,所谓多通道的池化操作,其实就是在每个特征通道上各自进行池化操作,它并没有改变特征的通道数(这一点不同于多通道卷积)。
同理,对于最小池化和平均池化来说,其与最大池化的不同点仅仅在于计算方式上的不同。最小池化和平均池化分别会选择滑动窗口中的最小值和平均值来代替整个区域作为输出,其它地方并没有什么不同,因此就不再赘述。下面我们来看看为什么需要池化操作。
3.2 为什么需要池化
通常来说深度学习中的每一个操作都有着其对应的作用,而池化操作的作用主要就体现在两个方面:减少参数量和防止过拟合。
3.2.1 减少参数量
由于在图像处理中输入的图片像素普遍较大,同时在采取深度卷积后也会得到多个特征通道(在有的网络中,这一数字可能是1024或者更大),因此最终得到的特征图在进行后续的其它操作(例如全连接)时就会对应有大量的权重参数。以输入形状为的图片为例,在经过形状为的卷积核卷积处理后,将会得到形状为的特征图。如果后续再通过一个包含有个神经元的全连接层来对其进行分类,那么此时将会有个神经元。但是,如果先对特征图进行池化处理,那么这一数字就可能变成,缩小了4倍。
同时值得注意的是,在实际的操作中大家一般会选择窗口大小为3步长为2,或者是窗口大小为2步长为2的配置进行最大池化操作[2],并且更常见是第二种配置。
3.2.2 防止过拟合
通常来说,在卷积网络中输入的特征图都具有比较高的像素密度,以实现对某一类特征元素的精确刻画。但是这样一来也会带来一个弊端,那就是容易造成模型的过拟合现象。其原因在于,如果在网络训练结束后某些层的特征图像素密度很高,那么就会造成这些层的特征容错能力很低,结果就会导致在实际的预测过程中如果输入时的特征图与训练时的特征图存在一定的差异,那么后续下游任务的精度将会大打折扣。
因此,如果我们只用一个像素值来表示该像素值周围的值,那么从理论上将是不是就能够在一定程度上缓解这种过拟合的敏感现象?

图 4. 池化结果图
如图4所示,左边的为一张正常显示的图片,右边为该图片经过最大池化后的结果。可以看到,虽然右边的图片在一定程度上变得更加模糊了,但是我们依然大致能够看出来它是什么。同时,这个模糊的程度会取决于池化窗口的大小,窗口越大得到的结果也就会更加的模糊,当然最后网络就会呈现出欠拟合的状态。因此,我们可以通过调节池化窗户大小这个超参数来找到网络在过拟合与欠拟合之间的一个平衡点。
当然,也有一些人认为完全没有必要使用池化层来进行处理,只需要使用深层的卷积操作即可[2]。因此,对于到底使用还是不使用就是仁者见仁智者见智了,不过主流的做法还是会使用池化层。
4 总结
在这篇文章中,笔者首先介绍了如何计算卷积后特征图形状大小的计算;接着介绍了什么是填充操作,如何来计算填充的参数;然后介绍了什么是池化操作、池化操作的计算以及为什么需要池化操作等。同时,由于文章篇幅有限,对于如何使用深度学习框架来实现卷积计算等内容,笔者将会在下一篇文章中进行介绍。
本次内容就到此结束,感谢您的阅读!如果你觉得上述内容对你有所帮助,欢迎关注并传播本公众号!若有任何疑问与建议,请添加笔者微信'nulls8'或文末留言进行交流。青山不改,绿水长流,我们月来客栈见!
引用
[1]《深度学习》
[2]https://cs231n.github.io/convolutional-networks/#pool
推荐阅读
[1]原来卷积是这么计算的
[2]看不懂卷积或许只是因为
[3]什么你还不会实现反向传播?
