卷积神经网络的训练
和全连接神经网络相比,卷积神经网络的训练要复杂一些。但训练的原理是一样的:利用链式求导计算损失函数对每个权重的偏导数(梯度),然后根据梯度下降公式更新权重。训练算法依然是反向传播算法。
我们先回忆一下上一篇文章零基础入门深度学习(3) - 神经网络和反向传播算法介绍的反向传播算法,整个算法分为三个步骤:
- 前向计算每个神经元的输出值(表示网络的第个神经元,以下同);
- 反向计算每个神经元的误差项,在有的文献中也叫做敏感度(sensitivity)。它实际上是网络的损失函数对神经元加权输入的偏导数,即;
- 计算每个神经元连接权重的梯度(表示从神经元连接到神经元的权重),公式为,其中,表示神经元的输出。
最后,根据梯度下降法则更新每个权重即可。
对于卷积神经网络,由于涉及到局部连接、下采样的等操作,影响到了第二步误差项的具体计算方法,而权值共享影响了第三步权重的梯度的计算方法。接下来,我们分别介绍卷积层和Pooling层的训练算法。
卷积层的训练
对于卷积层,我们先来看看上面的第二步,即如何将误差项传递到上一层;然后再来看看第三步,即如何计算filter每个权值的梯度。
卷积层误差项的传递
最简单情况下误差项的传递
我们先来考虑步长为1、输入的深度为1、filter个数为1的最简单的情况。
假设输入的大小为3*3,filter大小为2*2,按步长为1卷积,我们将得到2*2的feature map。如下图所示:
在上图中,为了描述方便,我们为每个元素都进行了编号。用表示第层第行第列的误差项;用表示filter第行第列权重,用表示filter的偏置项;用表示第层第行第列神经元的输出;用表示第行神经元的加权输入;用表示第层第行第列的误差项;用表示第层的**函数。它们之间的关系如下:
上式中,、、都是数组,是由组成的数组,表示卷积操作。
在这里,我们假设第中的每个值都已经算好,我们要做的是计算第层每个神经元的误差项。
根据链式求导法则:
我们先求第一项。我们先来看几个特例,然后从中总结出一般性的规律。
例1,计算,仅与的计算有关:
因此:
例2,计算,与和的计算都有关:
因此:
例3,计算,与、、和的计算都有关:
因此:
从上面三个例子,我们发挥一下想象力,不难发现,计算,相当于把第层的sensitive map周围补一圈0,在与180度翻转后的filter进行cross-correlation,就能得到想要结果,如下图所示:
因为卷积相当于将filter旋转180度的cross-correlation,因此上图的计算可以用卷积公式完美的表达:
上式中的表示第层的filter的权重数组。也可以把上式的卷积展开,写成求和的形式:
现在,我们再求第二项。因为
所以这一项极其简单,仅求**函数的导数就行了。
将第一项和第二项组合起来,我们得到最终的公式:
也可以将式7写成卷积的形式:
其中,符号表示element-wise product,即将矩阵中每个对应元素相乘。注意式8中的、、都是矩阵。
以上就是步长为1、输入的深度为1、filter个数为1的最简单的情况,卷积层误差项传递的算法。下面我们来推导一下步长为S的情况。
卷积步长为S时的误差传递
我们先来看看步长为S与步长为1的差别。
如上图,上面是步长为1时的卷积结果,下面是步长为2时的卷积结果。我们可以看出,因为步长为2,得到的feature map跳过了步长为1时相应的部分。因此,当我们反向计算误差项时,我们可以对步长为S的sensitivity map相应的位置进行补0,将其『还原』成步长为1时的sensitivity map,再用式8进行求解。
输入层深度为D时的误差传递
当输入深度为D时,filter的深度也必须为D,层的通道只与filter的通道的权重进行计算。因此,反向计算误差项时,我们可以使用式8,用filter的第通道权重对第层sensitivity map进行卷积,得到第层通道的sensitivity map。如下图所示:
filter数量为N时的误差传递
filter数量为N时,输出层的深度也为N,第个filter卷积产生输出层的第个feature map。由于第层每个加权输入都同时影响了第层所有feature map的输出值,因此,反向计算误差项时,需要使用全导数公式。也就是,我们先使用第个filter对第层相应的第个sensitivity map进行卷积,得到一组N个层的偏sensitivity map。依次用每个filter做这种卷积,就得到D组偏sensitivity map。最后在各组之间将N个偏sensitivity map 按元素相加,得到最终的N个层的sensitivity map:
以上就是卷积层误差项传递的算法,如果读者还有所困惑,可以参考后面的代码实现来理解。
卷积层filter权重梯度的计算
我们要在得到第层sensitivity map的情况下,计算filter的权重的梯度,由于卷积层是权重共享的,因此梯度的计算稍有不同。
如上图所示,是第层的输出,是第层filter的权重,是第层的sensitivity map。我们的任务是计算的梯度,即。
为了计算偏导数,我们需要考察权重对的影响。权重项通过影响的值,进而影响。我们仍然通过几个具体的例子来看权重项对的影响,然后再从中总结出规律。
例1,计算:
从上面的公式看出,由于权值共享,权值对所有的都有影响。是、、...的函数,而、、...又是的函数,根据全导数公式,计算就是要把每个偏导数都加起来:
例2,计算:
通过查看与的关系,我们很容易得到:
实际上,每个权重项都是类似的,我们不一一举例了。现在,是我们再次发挥想象力的时候,我们发现计算规律是:
也就是用sensitivity map作为卷积核,在input上进行cross-correlation,如下图所示:
最后,我们来看一看偏置项的梯度。通过查看前面的公式,我们很容易发现:
也就是偏置项的梯度就是sensitivity map所有误差项之和。
对于步长为S的卷积层,处理方法与传递**误差项*是一样的,首先将sensitivity map『还原』成步长为1时的sensitivity map,再用上面的方法进行计算。
获得了所有的梯度之后,就是根据梯度下降算法来更新每个权重。这在前面的文章中已经反复写过,这里就不再重复了。
至此,我们已经解决了卷积层的训练问题,接下来我们看一看Pooling层的训练。
Pooling层的训练
无论max pooling还是mean pooling,都没有需要学习的参数。因此,在卷积神经网络的训练中,Pooling层需要做的仅仅是将误差项传递到上一层,而没有梯度的计算。
Max Pooling误差项的传递
如下图,假设第层大小为4*4,pooling filter大小为2*2,步长为2,这样,max pooling之后,第层大小为2*2。假设第层的值都已经计算完毕,我们现在的任务是计算第层的值。
我们用表示第层的加权输入;用表示第层的加权输入。我们先来考察一个具体的例子,然后再总结一般性的规律。对于max pooling:
也就是说,只有区块中最大的才会对的值产生影响。我们假设最大的值是,则上式相当于:
那么,我们不难求得下面几个偏导数:
因此:
而:
现在,我们发现了规律:对于max pooling,下一层的误差项的值会原封不动的传递到上一层对应区块中的最大值所对应的神经元,而其他神经元的误差项的值都是0。如下图所示(假设、、、为所在区块中的最大输出值):
Mean Pooling误差项的传递
我们还是用前面屡试不爽的套路,先研究一个特殊的情形,再扩展为一般规律。
如上图,我们先来考虑计算。我们先来看看如何影响。
根据上式,我们一眼就能看出来:
所以,根据链式求导法则,我们不难算出:
同样,我们可以算出、、:
现在,我们发现了规律:对于mean pooling,下一层的误差项的值会平均分配到上一层对应区块中的所有神经元。如下图所示:
上面这个算法可以表达为高大上的克罗内克积(Kronecker product)的形式,有兴趣的读者可以研究一下。
其中,是pooling层filter的大小,、都是矩阵。
至此,我们已经把卷积层、Pooling层的训练算法介绍完毕,加上上一篇文章讲的全连接层训练算法,您应该已经具备了编写卷积神经网络代码所需要的知识。