前言
从2012年AlexNet成名之后,CNN如同雨后春笋一样,出现了各种各样的Net,其中也有很多知名的,例如VGG、GoogleNet、Faster R-CNN等,每个算法都在前面研究工作的基础上做出了很大的改进,但是这些CNN模型中主要使用的组件却有很多重叠之处,这个组件主要有:
- 卷积层
- 池化层
- 激活函数
- 优化函数
- 全连接层
- Dropout
- 批量正则化
- 填充padding
- ......
其实一个CNN网络的模型搭建过程非常容易,现在有很多优秀的机器学习框架,例如tensorflow、pytorch、mxnet、caffe、keras等,借助这些机器学习框架搭建一个CNN网络模型只需要几十行代码即可完成,而且使用到的函数屈指可数,难度并不大。而上述提到的这些组件却是CNN中非常核心的概念,了解它们是什么?有什么价值?在哪里起作用?掌握这些之后再回头看这些CNN模型就会发现轻而易举,因此,这几节会先把上述这些技术介绍一下,然后逐个讲解如何一步一步搭建那些成熟优秀的CNN模型。
由于上述每个技术都涉及很多知识点,本文为了效率就用简单的语言介绍它是什么?有什么价值?具体详细的内容可以阅读文章或者外网资料详细了解,本文主要介绍3点:
- 卷积层
- 池化层
- 填充padding
卷积层
介绍
卷积神经网络(convolutional neural network),从它的名称就可以看出,卷积是其中最为关键的部分。在前面讲解图像去噪和图像分割中提到了一些用于分割和去噪的算法,例如sobel算子、中值滤波,其实卷积的概念和这些有相同之处。
把输入图像看作是一个n维矩阵,然后拿一个m*m维(m<n)的卷积核(或者称为滤波器),从图像的左上角开始沿着从左至右、从上之下进行"扫描",每当移动到一个窗口后和对应的窗口做卷积运算(严格的说是互相关运算),用直白的话来说就是对应元素相乘之后加和。
移动过程中涉及一个重要的概念--步长(stride),它的意思就是"扫描"过程中每次移动几个像素,如果步长stride=1,那么从左至右、从上之下逐个像素的移动。
以上图二维卷积运算为例,输入图像为一个5*5的矩阵,卷积核为3*3,以步长stride=1进行卷积运算,在左上角这个窗口每个对应元素先相乘再加和,即,
以这种方式逐个窗口进行计算,就得到图中等号右边的输出结果。
tensorflow使用
在tensorflow中关于卷积层的函数为,
tensorflow.nn. conv2d(input, filter, strides, padding)
其中参数分别为:
- input:输入数据或者上一层网络输出的结果
- filter:卷积核,它的是一个1*4维的参数,例如filter=[5, 5, 3, 96],这4个数字的概念分别是卷积核高度、卷积核宽度、输入数据通道数、输出数据通道数
- strides:这是前面所讲的步伐,同卷积核一样,它也是一个1*4维的参数,例如strides=[1, 2, 2, 1],这4个数字分别是batch方向移动的步长、水平方向移动的步长、垂直方向移动的步长、通道方向移动的步长,由于在运算过程中是不跳过batch和通道的,所以通常情况下第1个和第4个数字都是1
- padding:是填充方式,主要有两种方式,SAME, VALID,后面会讲什么是填充
池化层
介绍
池化层和卷积层一样,是CNN模型必不可少的一个部分,在很多卷积层后会紧跟一个池化层,而且在统计卷积神经网络时,池化层是不单独称为网络层的,它与卷积层、激活函数、正则化同时使用时共同称为1个卷积层。
池化层又成为下采样或者欠采样,它的主要功能是对于特征进行降维,压缩数据和参数量,避免过拟合,常用的池化方式有两种:
- 最大池化
- 平均池化
以最大池化为例介绍一下它是怎么实现的,
和卷积层类似,池化层也有窗口和步长的概念,其中步长在里面的作用也是完全相同的,就是窗口每次移动的像素个数,所以不再赘述。
池化层的窗口概念和卷积层中是截然不同的,在卷积层中每移动到一个窗口,对应的卷积核和输入图像做卷积运算。而在池化层中,窗口每移动到一个位置,就选择出这个窗口中的最大值输出,如果是平均池化就输出这个窗口内的平均值。
tensorflow使用
tensorflow中池化运算的函数为,
tensorflow.nn.max_pool(value, ksize, strides, padding)
从函数的参数即可看出来,它和卷积层非常相似,它的参数概念分别是,
- value:输入数据或者上一层网络输出的结果
- ksize:卷积核,它的是一个1*4维的参数,例如ksize=[1, 3, 3, 1],这4个数字的概念分别是batch维度池化窗口、池化窗口高度、池化窗口宽度、通道维度窗口尺寸,由于在batch和通道维度不进行池化,所以通常情况下第1和第4个元素为1
- strides:这和卷积层中相同
- padding:这和卷积层中的也相同
填充
在前面讲解卷积层和池化层时都提到了一个概念--填充,可见它是非常重要的。什么是填充?SAME, VALID这两种填充方式又有什么区别?下面来介绍一下。从前面卷积层和池化层可以看出,卷积层和池化层的输出尺寸大小和选取的窗口大小有着密切关系,以卷积层为例,上述输入为5*5,但是输出为3*3,输出尺寸变小了,而且在输入图像的四周的元素只被卷积了一次,中间的元素却被利用多次,也就是说,如果是一副图像,图像四周的信息未被充分提取,这就体现了填充的价值,
- 保持边界信息
- 使得输入输出图像尺寸一致
那怎么样达到上述这2个目的?就是通过填充,一般情况下是在图像周围填充0,如下,
如上图所示,在输入图像周围填充0,然后通过卷积运算,输入和输出的尺寸都为5*5。当然,这是针对卷积核为3*3情况下,外层填充1层,具体填充几层,要根据卷积核大小而定。然后回到前面所提到的,tensorflow中填充padding参数有两个选项:SAME, VALID,它们有什么区别呢 ?VALID:不进行填充SAME:填充0,使得输出和输入的尺寸相同,就如同上面这个例子。