基于Notes on Convolutional Neural Networks的卷积神经网络反向求导的理解

来源:互联网 发布:淘宝网天猫女中筒靴 编辑:程序博客网 时间:2024/05/29 07:45

多次阅读cnn_tutorial 后,结合其他作者的博客后。终于对CNN反向求导明白了点,在此写下对反向求导的理解。


1.

CNN的最终目标是以数据驱动的模式,去学习filters..,也称为kernel(filter正是从input中抽取特征)。

bp 算法,即反向传播算法的思想大概是:将当前网络的输出与期望的输出做比较。然后从后往前,调节每层的参数。

根据梯度下降算法,通过计算error(当前的输出与期望的输出的差值)对 参数的偏导,来进行参数的调节。


2.对于全连通层的bp计算


对于一个样本,error的定义: 



(n 表示第n个样本,c表示多分类问题的类别)

向前传播的过程: L 代表当前层, W是权重, b 是 bias。 之后再加上激活函数。 

BP的过程:

BP 规则: 




因为u对bias的偏导是1,所以E对bias的偏导,和E 对u(即单元的所有input)的偏导是等价的。


(u是该层的未加入激活函数的计算结果的)


 残差(或称为敏感度)是error 相对于 u 该残差表明了该节点对最终输出值的残差产生了多少影响


显然,我们只要知道了每层的残差是多少,利用这个BP规则,我们就可以知道E对每层的bias参数偏导是多少。


同样的,知道每层的残差后,E对weight的偏导也可以类似求解得到。所以下面就是要求这个残差。


利用这个公式,递归计算的 



输出层的残差计算: 





y是网络的输出结果,t是标签信息

之后根据delta 规则, 级联地可以算出参数的偏导数。

对于W:  L层的W等于这层的输入 ,乘以 L层的残差        

 下面表示计算时W的增量。n为步长,即learning rate。 




3. Convolution Layers 的计算过程

前向传播时: 





i表示 input map ; j表示output map  

一般来说, 一个output map 会有选择地挑选 几个input map 。进行卷积,再加上bias。

若同一层有2个不同的output map p, q ,他们都跟同一个input map i 做了卷积,做卷积的kernel是不同的。

若input map 有m个,output map 有n个。则kernel会有m*n个。如果是有选择性的卷积的话,则部分的kernel的元素就会都为0。


BP时,梯度的计算


为了计算L 层一个节点 的sensitivity, (即残差),根据上面的公式, 


我们首先要找出,下一层,哪些节点跟L层的这个节点相连。

然后,将 下一层跟当前L层的节点 相关联的units 的sensitivity 与

它们跟 L+1层的计算权重相乘。

然后将这个结果加起来,乘以 f’(u)。u为当前L层,未加激活函数的值。

在convolution layer 后面跟着 pooling layer的情况下,

L层的一个unit,只会跟后一层的一个unit相连。

而,这个权重,其实跟pooling 时候的scale的值是相关联的。

所以我们可以通过upsample 将后一层的残差的size 跟当前层一样大。扩大的系数跟以前的pooling 的系数是一样的,之后,再将u 值,放入到激活函数的导数中去。

对于L 层的第j 个map 






举个例子,如图,L层与L+1层间做了pooling。

如我们要求L层中A11节点的sensitivity,我们找到L+1层跟它相关的节点只有 B11

所以A11节点的敏感度 = ( 相关节点的敏感度 * 2者连线权值  )* u的激活函数的导数值。

这里的权值,取决于做什么类型的pooling。

max - pooling .若A11是最大的,权值即为1,不是最大的,权值为0

mean - pooling.权值为1/(scale^2)


计算 bias 的梯度就容易了,(bias是相对于一层来说的) 


 将算出来的残差加起来。(一般算出来的残差是二维的)

之后是算kernel的梯度, 



其中的 p 是input map i 的patch ,在前向传播中,这个patch 会跟kernel做卷积(这种patch应该有u*v 个)。


patch 做卷积的结果对应着 输出map j 的 uv点的值。

将input 与一个残差 做乘法,然后再加所有的结果加起来。

举个例子



如果kernel 是 2*2的

则u = 3 - 2 + 1 = 2, v = 3 -2 +1 = 2; 

L-1层第 i个map 的  patch1,1 = [P11, P12; P21,P22]  (2*2大小的)

A11 节点的误差敏感度 * patch1,1 + …… + A22节点的误差敏感度 *patch2,2

相当于是4个2*2的矩阵相加。这样可以得到kernel i,j 的偏导。

要找哪个patch跟下一层的哪个节点对应是比较麻烦的事情。

动手计算后可以发现,这样矩阵相加后的值跟

L-1层的 map i 与 L层的 map j 的误差敏感矩阵 做卷积后的结果是一致的。

 




4.Sub-sampling Layers  的计算过程

前向传播过程: 



sub-sampling 的计算是简单的。有 N个input map的话,也会有N个output map.

但会缩小指定的系数。

反向梯度计算:

这里的难点是计算误差敏感,也就是sensitivity map误差名矩阵.一旦我们算出了sensitivity map , 只要更新其他的bias的参数就可以了。

如果sub-sampling后面跟的是fully connected ,按照通用的bp算法就可以求解了。

如果后面跟的是卷积层。

为了计算kernel.我们要找出,在当前层的 sensitivity map 中的哪个patch 跟下一层的sensitivity map 中的pixel是对应的。这些都是为了应用delta recursion。

当然,input patch 和output pixel中关联的权重,就是the weights of the (rotated) convolution kernel.

所以可以用卷积有效地实现。 




正如之前那样,选择kernel使卷积函数进行cross- correlation 计算。这里用的是“full”卷积边界处理,因为 L+1层的unit的输入不是完整的n*n   size. 加了“full”,不足的会自动用0填充。

四周都填充 kernelsize - 1 个0 。

之后,b 的值跟之间卷积一样的,将残差加起来。

乘的系数,会包含原来的down-sampled map(当前层在前向传播中计算出来的)。

 


举个例子:要求L层的误差敏感度矩阵(在这里是3*3大小)

如要求map j 的P11节点的误差敏感度,根据之前的公式,

首先要找到L+1层中所有跟它有连接的节点和连接的权值,再求和。

如果L+1层,有1个map 与j map有关。利用卷积核去滑动下,可知:

P11节点 跟 A11节点有关,权值为 kernel j,1(1,1)。

P12节点 跟A11节点相关,权值为kernel j,1(1,2),还跟 A12节点相关,权值为kernel j,1(1,1)。这样可以获得 3*3 的误差敏感度矩阵。

如果跟L层有多个相关map。则获得到的多个误差敏感度矩阵相加即可。

这样看起来,计算比较麻烦。可以用卷积的方法方便地实现。

即在 L+1 的map 四周填充0.(2 - 1 =1 )变成4*4的了。

填充过的map 与 旋转过的kernel 做卷积。就可以得到。跟我们前面手动算误差敏感度一样的结果。

 



参考:

1 .notes on convolutional neural networks.

2.Deep learning:五十一(CNN的反向求导及练习) http://www.cnblogs.com/tornadomeet/p/3468450.html


0 0
原创粉丝点击