[TOC]

概述

卷积是卷积神经网络中最常用的操作,卷积到底是如何运算的呢?

卷积(Convolution)

我们先从一维来看,如上图所示,有一个滑动的窗口从左到右,从上到下滑动,这个滑动的3*3的矩阵我们就称作卷积核,卷积核里面的数和输入矩阵的数字一一相乘后相加,就得到了一个新的数字,这些新的数字按从左到右、从上到下的顺序排列,就得到了输出矩阵,整个这个过程,我们就叫做卷积。

通过一维的卷积我们可以看到,输入的矩阵内的数字是固定的,输出矩阵的数字其实完全取决于卷积核内的数字,如果我想要输出正确的结果,只能通过修正卷积核。换句话来说,卷积核就是我们需要修正的参数,这一点希望大家能够明确。

对于图像来讲,我们看到的都是三通道的彩色图(RGB格式),也就是说最初的输入是一个3通道的矩阵,比如(3,640,640),对于多通道的矩阵,卷积操作也不难理解。

其实就是将一维的卷积重复了三次有3个卷积窗口分别滑动得到了三个矩阵,最后将这三个矩阵内的数相加,得到了最后的输出。可以看到上图的输入shape为(3,5,5),卷积核的shape为(3,3,3),输出的shape为(1,3,3)

然而,输入图像往往需要经过多个卷积层才能输出,也就是说,输入的通道数是不固定的,可能是3、16、64等等,对于这些情况如何卷积呢?

如上图所示,有一个通道数很大的输入矩阵,类比我们三通道的卷积方式,其实也不难看出,卷积核的通道数应该等于输入的通道数,这样每一层对应起来,其实就变成了一维的形式,最后把每层的结果相加,就得到了一个一维的输出矩阵

到这边其实还没有结束,因为除了输入通道以外,我们还希望可以控制输出通道数。具体如何控制输出通道数呢?

就是用Dout个卷积核重复我们上一步的操作,这样的话,输入通道和输出通道都可以是任意的数

我们可以作出以下的总结,对于一个(Din,Hin,Win)的输入矩阵,经过Dout个(Din,h,w)的卷积核之后,输出为(Dout,Hout,Wout)的矩阵。换句话来说卷积核的通道数等于输入通道数,卷积核的个数等于输出通道数。

池化(Pooling)

除了卷积以外,池化也是一个比较常用的运算操作,池化主要分为两种最大池化和平均池化。

上图分别为最大池化和平均池化,池化窗口的大小为(2,2),步长为2,池化就是将这个窗口内的数变成一位数,对于最大池化来说,就是变成窗口内的最大数,平均池化就是变成窗口内所有数的平均值。对于多通道的输入来说,池化和卷积不同,池化就是对每一个通道上都进行这样的操作,最后不需要加在一起,也就是说池化前后的输入输出通道不变,仅仅改变了特征图的大小。

更加直观得来说,池化其实相当于对特征图进行了resize的操作。图像的特征特征不会明显改变,池化可以有效地减少参数量,而且可以有效地防止过拟合。

归一化(Normalization)

归一化的含义也非常简单,就是把矩阵内所有的数不失真地映射到0-1之间。这样做可以防止某一维或某几维对数据影响过大,一般我们在卷积运算之后紧跟着都需要进行归一化操作。

左图是未归一化的梯度等高图,右图是归一化之后的图,明显左图受到某些维度的数据影响过大,右图梯度下降就平缓很多,相对更容易达到期望的最优解

激活函数(Activation)

通过以上的讨论,不难发现整个卷积网络都是对矩阵的一些线性化操作,对于一些非线性的情况,是无法精确拟合的,这就需要增加一些函数略微扭曲输出的结果,这些函数也被称为激活函数

常见的激活函数有很多,例如relu,swish,mish,softmax等。

这些激活函数看似区别不大,对最终的模型表现却有极大的影响。例如有些激活函数是无上下限的,有些函数时间成本很高,这些都会影响到最后模型的速度和精度

## 参考资料

https://mp.weixin.qq.com/s?__biz=MzA5ODEzMjIyMA==&mid=2247496109&idx=1&sn=a7a6558b086266c062925600e3e71394&source=41#wechat_redirect

https://blog.csdn.net/gwplovekimi/article/details/89890510

https://blog.csdn.net/program_developer/article/details/78637711?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-4.pc_relevant_aa&spm=1001.2101.3001.4242.3&utm_relevant_index=7