CNN的反向传播推导与理解

来源:互联网 发布:anaconda for mac 编辑:程序博客网 时间:2024/06/04 18:16

参考与说明

  • 本文主要是通过阅读相关论文和一些辅助的博文来理解卷积神经网络里面的反向传播算法;相关的论文可以查看Notes on Convolutional Neural Networks, Jake Bouvrie

准备工作

  • 首先呢,我们还是先回顾下在深度学习里面的反向传播算法的公式,损失函数为
    C=12yaL2=12j(yjaLj)2
    公式如下 
    图示 
    关于公式更加详细的一些介绍可以参考
  • 我们可以发现其实论文里面的公式与上面的形式不大一样,但是其实道理是一样的; 第一个是损失函数,论文里面的是
    EN=12n=1Nk=1c(tnkynk)2
    ,然后为了简化问题,我们直接针对单个用例(第n个用例)的情况得到它的损失函数就是
    En=12k=1c(tnkynk)2
    ,当然这做法是合理的,符合数学理论(我们每轮只使用一个用例,而不是使用全部用例进行更新),同时是为了方便分析简化问题;接下来我们可以看到每层的公式
    xl=f(ul)ul=Wlxl1+bl
    公式里面的ul表示第l层的加权值,而f表示激活函数,而xl为其输出,直观上来说xl就是我们常说的特征图(feature map),当然每层的特征图可能不只一个;
  • 这里有一个先要理清楚,我们知道在卷积神经网络的卷积层中, 我们如何通过多个输入特征图得到我们的每个输出特征图的,直观上来说就是我们的每个输出特征图是使用全部的输入特征图的,如何使用呢?就是每个输出特征图对应于每个输入特征图都有一个核进行卷积的,将所有的卷积结果进行相加再加上我们的偏置再激活就是我们的输出了;就是在卷积神经网络的BP推导中, 我们要理清特征图与核权重与偏置的关系;每个输出特征图都与所有的输入特征图有关(这里假设使用的是全部)的话,那么这个输出特征图对应于每个输入特征图都有一个核;所以呢,总结一下就是我们的每个输出特征图都会对应于多个核和一个偏置,一个核处理一个输入特征图,并将结果进行对应相加;而对于池化层的话,只是一个下采样层,每个输入特征图对应于一个输出特征图,关于这个可以参考
  • 符号说明 
    • xlj,表示我们的第l层的第j个输出特征图
    • klij表示我们第l层生成第j个输出特征图时作用于第l-1层中第i个输出特征的核(权重),直观理解就是是一个矩阵来的
    • blj表示第l层的第j个输出特征图的偏置;
    • δlj表示第l层第i个输出特征图的误差(在论文中叫做sensitivity,其实也差不多意思,就是当前的输出对误差的影响率);
    • (δlj)uv表示特征图对应的误差图(每个元素都会有一个对应的误差值)中的第(u,v)个
    • ulj表示第l层的第j个输出加权值特征图,还没有进行激活处理的特征图;

进入主题

  • 首先明确我们的目的,无论是对应卷积层还是池化层,我们的目的都是得到参数对于损失函数的偏导
  • 下面我们讨论的是卷积层和池化层,且有一个假设,就是卷积层的前面是一个池化层,后面也是一个池化层;而池化层的前面是一个卷积层,后面也是一个卷积层;因为其他的情况可以使用普通的反向传播进行解决
  • 为了方便直观理解,我们在这里使用一个模型,我们使用如下的Letnet-5的一部分模型图 
    图示
    每个方形表示一个图片,在第一层就表示输入,后面的就是相应的特征图了,方形里面的数字表示大小,对应的每一层是什么操作也已经用箭头进行说明了。

卷积层(针对于输出特征图)

  • 首先进行卷积层的说明,第一个先说明一下前向计算的时候的公式
    xlj=f(iMjxl1iklij+blj)
    ;公式本身不难理解,是一个卷积操作,其中klij是核,它是第l层中在生成第j个输出特征图时,第i个输入特征图使用的核,如果我们的核使用的是5×5的话,它就是一个5×5的核;而blj表示在第l层中用于生成第j个输出特征图时使用的偏置;而f表示激活函数;xlj就是表示第l层的第j个输出特征图了,那么整个公式表示的意思就是在第l层中,我们在生成第j个输出特征图时,我们是使用了Mj集合中的特征图,针对每个特征图我们使用对应的核,并将所有核卷积后生成的特征图矩阵进行矩阵相加再加上对应的偏置得到新的结果,最后将每一个值再经过一个激活函数得到我们的输出特征图;说完了前向计算,接下来我们就来说如何进行反向传播了,根据我们前面说的反向传播的公式,我们知道在反向传播算法中, 我们主要是通过计算一个中间量,也就误差值,在论文中叫做敏感值δ来计算我们的每个参数偏导的,所以关键问题就在于如何计算误差值了,首先我们要知道在普通的深度神经网络中每个神经元的误差值的定义式为
    δlj=CZlj=kwl+1kjδl+1kσ(zlj).
    ,其中l表示第l层,j表示第j个神经元,Z表示加权值;我们直接从一整个层的角度来看就是
    δl=((wl+1)Tδl+1)σ(zl)
    ;直观理解公式的意思就是我们要计算l层的神经元j的误差的话,需要使用第l+1层中与第l层第j个神经有相连的所有神经元的误差值,将这些误差值对应去乘各自的权重,再去乘以对应的第l层第j个神经元的激活函数对于加权值的偏导就可以了;那么应用到卷积神经网络中,有几个不同的地方,首先一个是在使用全连接的神经网络中,我们每个第l层的神经元与第l+1层的神经元都有联系,所以Wljk对于所有k都存在,但是在卷积网络中,并不是使用全连接的方式,而是使用了局部感受野的方式,换句话来说,就是说第l层的神经元j与第l+1层的第个神经元并不是都有直接联系的;第二个就是在卷积层的后面是一个池化层,是一个下采样的操作;基于上面的说明我们现在的目的针对池化的操作进行反向传播的,是将池化后的输出特征图结果(δl+1)的误差值反向传回到卷积层的输出特征图上δl(池化是一个一对一的,一个输入特征图对应一个输出特征图);以我们的模型中下面这 
    池化反向 
    我们知道在池化操作中是以将一个区域的数字归于一个数字(池化的操作是步长等于核的宽度或长度),这样的话,我们的输入特征图j中像素(神经元)i就只是对应了输出特征图j中的像素(神经元)i了; 这样我们的操作就是将卷积层的下一层的池化结果进行上采样到与输入特征图一样的大小(就是卷积层的输出特征图)再将其结果与卷积层的结果进行对应元素相乘就可以了,到了这里,还差一个就是权重,就是卷积层到池化层中间那些权重怎么算,其实在生成同一个池化结果时的权重都等于同一个值(β)(后面到池化层的时候会详细说明),到这里,我们就可以得到结果了
    δlj=βl+1j(f(ulj)up(δl+1j))
    ,其中 是一个Hadamard product的过程(逐元素积);δlj表示第l层中第j个输出特征图的误差值,ulj表示第l层的第j个输入特征图得到的卷积结果(加权值),到这里我们就得到了第l层的误差值,它的大小与对应的特征图大小一样,每个值对应了每个特征图像素的误差值;其实up(x)就是一个Kronnecker product的结果,
    up(x)=x1n×n
    1nn表示一个n*n的全1矩阵,在我们使用池化时,如果是2×2的核的话,
    up(δl+1j)=δl+1j12×2
  • 终于辛苦的得到了我们的误差值的公式,接下来我们就要得到我们的偏置的偏导和核权重的偏导了;首先先回忆下一个公式,
    ulj=iMjxl1iklij+blj
    ; 对于偏置的偏导,其定义为
    Ebj
    ,跟推导正常的反向传播公式一样要用到多元函数的求导法则,这里我们先设l层的输出特征图的大小为28×28,且一共有6个特征图,我们可以令
    E=g((ul(0,1,...,6))(0,0),(ul(0,1,...6))(0,1),...(ul(0,1,2,...,6))(27,27))
    ,也就是说把损失函数表示成第l层的所有特征图的一个函数,(ul(0,1,...,6))(0,0)表示第l层中所有的6个特征图(只是加权值)的第(0,0)个位置的值;所以要求
    Ebj
    的话,可以得到
    Eblj=ku,vE(ulk)uv(ulk)u,vblj
    ;但是我们知道ulk只有当k=j的时候才与blj有关,因为ulk是表示第l层的一个第k个特征图(加权值,还没激活),与它相关的偏置值只有blk所以,当k!=j时,(ulk)u,vblj求偏导是为0的,所以有,当k==j时,(ulk)u,vblj的值为1,所以有整体的推导为
    Eblj=ku,vE(ulk)uv(ulk)u,vblj=u,vE(ulj)uv(ulj)u,vblj=u,vE(ulj)uv=u,v(δlj)uv
  • 接着就是我们的权重k了,其定义为
    Eklij
    ;这里的klij表示第l层生成第j个特征图时,作用于第i个输入特征图的核权重,在我们的模型中取一个例子就是 
    图示; 6个输入特征图生成了一个输出特征图,每个输入特征图会有一个对应的卷积核;而klij也就表示其中的一个核,所以我们得到的结果应该是一个与核一样大小的矩阵;这里的道理与推导偏置的时候是一个样的,可以得到
    Eklij=mu,vE(ulm)uv(ulm)u,vklij=u,vE(ulj)uv(ulj)u,vklij
    这里我们需要去思考下当k==j的时候,
    (ulj)u,vklij
    会等于什么?为了加强理解,我们先考虑单个值的情况,我们先求
    E(klij)mn
    表示针对核的值里面的{m,n}位置求偏导,其他原先的一样,只是现在变成去求
    (ulj)u,v(klij)mn
    ,它的值就是我们的核里面的(m,n)位置在进行卷积(移动)的过程中与输入特征图有进行相乘操作的区域,假设在下面的这样一个卷积过程中 
    示例我们针对左边的大矩阵去进行一个卷积操作,我们可以知道在使用核进行卷积移动的过程中,红底的1有经过(进行了相乘操作)的区域就是左边用黄底标出的部分,黄色区域代表的移动范围我们应该如何表示呢?
    ulj(klij)mn
    ,对于图中的黄色区域就是(m,n)=(0,0),直观上也可以理解,针对输入特征图的ulj对核的(m,n)位置求偏导的话,由ulj公式可以知道得到的就是与核(m,n)位置有乘积关系的xl1i内的值,其余都会为0,归纳起来就是类似我们上面的黄色小区域; 而
    (ulj)u,v(klij)mn
    这个公式的值就是一个类似于黄底的小区域在(u,v)位置处的值;我们这里使用(ql1i)mn表示核的(m,n)位置在移动的过程中,经过的区域,也就是黄色的区域,这个区域的大小会与卷积结果有大小一致的关系(细想下就知道了,可以移动一格就表示可以得到一个输出结果);所以我们的公式推导就是
    E(klij)mn=mu,vE(ulm)uv(ulm)u,v(klij)mn=u,vE(ulj)uv(ulj)uv(klij)mn=u,v(δlj)uv((pl1i)mn)uv
    ;直观上来说上面的公式我们在求核klij的(m,n)位置的权重的偏导的时候,我们要先得到这个位置在输入特征图中经过的区域(它的大小与输出特征图j是一样大小的),然后将这个区域与输出特征图的误差值矩阵进行Hadamard product(逐元素积)再进行结果的所有元素求和;现在我们考虑如何全部一次性得到整个kjij的偏导,而不是一个个得到;直接根据公式有
    Eklij=mu,vE(ulm)uv(ulm)u,vklij=u,vE(ulj)uv(ulj)uvklij
    ,要理解
    (ulj)uvklij
    ,它就是一个针对特征图(u,v)位置进行一个向量求导,其实也与我们上面针对每个权重进行求导是一个样的,只是我们上面是每次得到一个标量
    (ulj)u,v(klij)mn
    ,这里是每次都得到一个与klij一样大小的向量,它的值其实就是
    (ulj)u,v(klij)0,0(ulj)u,v(klij)4,0(ulj)u,v(klij)0,4(ulj)u,v(klij)4,4
    ,根据我们卷积的过程
    (ulj)u,v=iMj(xl1i)u,vklij+blj
    ;表示在生成第l层第j个特征图时的公式,(xl1i)u,v表示对应使用的区域,所以我们上面的矩阵的值就是等于
    ((xl1i)u,v)0,0((xl1i)u,v)4,0((xl1i)u,v)0,4((xl1i)u,v)4,4
    ;其中
    ((xl1i)u,v)0,0
    表示利用第i个输入特征图生成输出特征图(u,v)位置的值时使用的区域的(0,0)位置的值;我们使用(pl1i)uv表示这样的一个矩阵,也就是表示在生成利用输入特征图i生成输出特征图(u,v)位置的值时使用的区域,于是我们就可以得到一个与论文一样的公式
    Eklij=mu,vE(ulm)uv(ulm)u,vklij=u,vE(ulj)uv(ulj)uvklij=u,v(δlj)uv(pl1i)uv
    ;直观理解就是我们在计算一整个核的偏导时,是遍历一次本层的误差值,针对每个误差值,取输入特征图中生成这个位置的加权值uuv时使用的区域,将误差值与这个区域进行标量与矩阵乘法,遍历所有元素后,得到u*v个矩阵,将这些矩阵进行矩阵加法就可以得到我们的结果了;

池化层(下采样层)(针对于输出特征图)

  • 先直接前向计算时的公式为
    xlj=f(βljdown(xl1j)+blj)
    ;公式中的βlj表示乘性偏置,而blj表示加性偏置,对于生成每个输出特征图来说,对应的每个输入特征图都只有一个乘性和加性偏置;而down表示一个下采样的过程,也就是对应的池化过程,可以是最大值等;f表示对应的激活函数;一般情况我们可能设乘性偏置为1,加性偏置为0,激活函数为线性函数f(x)=x
  • 我们先要解决误差值的计算,直接看论文里面的公式,个人感觉不对,因为我们知道计算误差值,就是找出本层与下一层误差值之间有联系的神经元,因为卷积神经网络有多个特征图,但是论文中只是找了一个特征图;这里我以自己的推导进行,如果有误,请指正;
    δlj=iδl+1ikl+1jif(uj)
    公式的意义是在求第l层的第j个特征图的误差值时,先针对每一个l+1层的输出特征图利用它的核进行全卷积操作(要补0操作),得到关于所有输出特征图的卷积结果(每个卷积结果的大小都会与第l层的第j个输出特征图一样大小,因为使用的是全卷积,会补0进行扩展,关于全卷积可以参考)后进行矩阵加法,之后再与f(ulj)进行一个Hdamamard product(逐元素积)就可以得到第l层的第j个输出特征图的结果了;为什么是上面那个公式呢?推导过程主要是先利用求解单个位置的误差值,同卷积层求权重差不多;接下来我们主要是针对乘性偏置和加性偏置进行求偏导;对于加性偏置我们有
    Eblj=ku,vE(ulk)uv(ulk)u,vblj=u,vE(ulj)uv(ulj)u,vblj=u,vE(ulj)uv=u,v(δlj)uv

    对于乘性偏置我们有,
    Eβlj=ku,vE(ulk)uv(ulk)u,vβlj=u,vE(ulj)uv(ulj)u,vβlj=u,vE(ulj)uv(down(xl1j))up=u,v(δljdown(xl1j))uv

总过程

  • 最后我们使用一个简易的模型来进行说明这个过程 
    图示
    首先呢,我们前向传播,输入一个32×32的图片,进行卷积操作,卷积核为5×5,共有6个,使用卷积操作
    ulj=iMjxl1iklij+blj
    ,我们得到6个输出特征图;然后进行池化,每个输入特征图得到一个输出特征图;后面的一个道理,一直到全连接层,我们将卷积-池化得到的结果(假设有M个结果)作为全连接层的输入得到3个输出结果;接下来就是利用反向传播进行更新我们的参数了,首先计算输出层的误差值,这里因为是全连接层,我们可以直接使用普通的反向传播算法,公式如下 
    图示 
    这样我们可以得到倒数第二层的误差值,接下来我们看倒数第3层,它是池化层的输出结果,所以使用池化层的误差传播公式,可以有
    δlj=iδl+1ikl+1jif(uj)
    ,针对本层的第j个输出特征图的误差,它是等于使用倒数第2层的每个数去与它们的核(k^{l+1}_jm)进行全卷积操作得到M个5×5的矩阵,将它们进行相加再与本层的激活函数相对于加权值的偏导进行Hadamard product(逐元素积)就可以得到本层的全部误差值了;然后再根据乘性偏置和加性偏置的偏导公式可以得到偏导,就可以进行更新参数了;接下来来到倒数第4层,这是一个卷积层的输出结果;先得到误差值,根据公式
    δlj=βl+1j(f(ulj)up(δl+1j))
    就是直接使用倒数第3层的第j个特征图误差值进行一个上采样进行扩展到10×10的大小,然后再与对应的本层的第j个特征图加权值对于激活函数求导得到一个10×10的矩阵,再乘上倒数第3层的乘性偏置就可以得到本层对应的第j个特征图的误差值了;而偏置的偏导就是
    Eblj=u,v(δlj)uv
    就是将对应的特征图所有的误差值加起来就可以了;而核权重就是
    Eklij=u,v(δlj)uv(pl1i)uv
    ,为了得到第i个输入特征图指向 
    第j个输出特征图的核权重,我们是对误差值里的每个位置进行遍历,将每个元素值与对应生成这个元素值的输入特征图中的区域进行标量与矩阵的乘法,这样可以得到u×v个矩阵,将这些矩阵进行矩阵相加就可以得到我们本层kij的偏导向量了;其他也是相同的道理,不多说了。

参考

  • http://blog.csdn.net/zy3381/article/details/43274029
  • http://blog.csdn.net/xiaoyanghijk/article/details/52073162
  • http://blog.csdn.net/hjimce/article/details/47323463
0
0 0
原创粉丝点击