上文讲解了卷积层中每个神经元与输入数据体之间的连接方式,但是尚未讨论输出数据体中神经元的数量,以及它们的排列方式。共有3个超参数控制着输出数据体的尺寸:深度(depth),步长(stride)和零填充(zero-padding)。下面是对它们的讨论:
1) 输出数据体深度
它和使用的滤波器的数量一致,每个滤波器会在输入数据中寻找一些不同的东西。举例来说,如果第一个卷积层的输入是原始图像,那么在深度维度上的不同神经元将可能被不同方向的边界,或者是颜色斑点激活。我们将这些沿着深度方向排列、感受野相同的神经元集合称为深度列(depthcolumn)。如下图所示卷积层共有6个滤波器,输出的数据深度也为6。
2) 步长
在滑动滤波器的时候,必须指定步长。当步长为1,滤波器每次移动1个像素。当步长为2(或者不常用的3,或者更多,这些在实际中很少使用),滤波器滑动时每次移动2个像素。这个操作会让输出数据体在空间上变小。如下图所示,移动的步长为1,输入的数据尺寸6 * 6,而输出的数据尺寸为4 * 4。
3) 填充
卷积层滤波器输出会减少数据的尺寸,如下图,32 * 32 * 3的输入经过一个5 * 5 * 3的滤波器时输出28 * 28 * 1尺寸的数据。
而零填充有一个良好性质,即可以控制输出数据体的空间尺寸(最常用的是用来保持输入数据体在空间上的尺寸,这样输入和输出的宽高都相等)。将输入数据体用0在边缘处进行填充是很方便的,这个零填充(zero-padding)的尺寸是一个超参数。如下图所示通过零填充保持了输入输出数据宽高的一致。
卷积层输出计算公式:
假设输入数据体的尺寸为:
卷积层4个超参数为:
则输出数据体的尺寸为:
其中:
对这些超参数,常见的设置是F=3,S=1,P=1。比如输入是7x7,滤波器是3x3,步长为1,填充为0,那么就能得到一个5x5的输出。如果步长为2,输出就是3x3。
(3) 参数共享
在卷积层中使用参数共享是用来控制参数的数量。每个滤波器与上一层局部连接,同时每个滤波器的所有局部连接都使用同样的参数,此举会同样大大减少网络的参数。
这里作一个合理的假设:如果一个特征在计算某个空间位置(x,y)的时候有用,那么它在计算另一个不同位置(x2,y2)的时候也有用。基于这个假设,可以显著地减少参数数量。换言之,就是将深度维度上一个单独的2维切片看做深度切片(depth slice),比如一个数据体尺寸为55x55x96的就有96个深度切片,每个尺寸为55x55。在每个深度切片上的神经元都使用同样的权重和偏差。在反向传播的时候,都要计算每个神经元对它的权重的梯度,但是需要把同一个深度切片上的所有神经元对权重的梯度累加,这样就得到了对共享权重的梯度。这样,每个切片只更新一个权重集。
在一个深度切片中的所有权重都使用同一个权重向量,那么卷积层的前向传播在每个深度切片中可以看做是在计算神经元权重和输入数据体的卷积(这就是“卷积层”名字由来)。这也是为什么总是将这些权重集合称为滤波器(filter)(或卷积核(kernel)),因为它们和输入进行了卷积。下图动态的显示了卷积的过程:
1.2.2 池化层通常,在连续的卷积层之间会周期性地插入一个池化层。它的作用是逐渐降低数据体的空间尺寸,这样的话就能减少网络中参数的数量,使得计算资源耗费变少,也能有效控制过拟合。池化层使用Max操作,对输入数据体的每一个深度切片独立进行操作,改变它的空间尺寸。最常见的形式是池化层使用尺寸2x2的滤波器,以步长为2来对每个深度切片进行降采样,将其中75%的激活信息都丢掉。每个Max操作是从4个数字中取最大值(也就是在深度切片中某个2x2的区域)。深度保持不变。
池化层的计算公式:
输入数据体尺寸:
池化层有两个超参数:
输出数据体尺寸:
其中:
因为对输入进行的是固定函数计算,所以没有引入参数。在池化层中很少使用零填充。