• CNN反向求导推导


    激活函数

    logistic function σ(x)=11+e−x
    hyperbolic tangent tanh(x)=e2x−1e2x+1
    两者之间的关系
    tanh(x)=2σ(2x)−1
    对激活函数求导,我们有
    ∂tanh(x)∂x=1−tanh(x)2
    ∂σ(x)∂(x)=σ(x)(1−σ(x))

    Loss Function 及求导

    一般定义pre-activation(输出层神经单元用k表示):
    ak=∑h∈HLwhkbh
    所以对于输出层,每个类别的概率可以用softmax函数来计算:
    p(Ck|x)=eak∑Kk′=1eak′
    ground truth 的类别z用个one-of-k维的向量来表示。这样的话,目标label的概率为
    p(z|x)=∏k=1Kyzkk
    对于损失函数,一般可以用negtative log likelihood L(x,z)=−lnp(z|x) ,得到:
    L(x,z)=(z−1)ln(1−y)−zlny
    对于多分类的问题,可以有
    L(x,z)=−∑k=1Kzklnyk
    或者采用【1】中最小二乘形式的损失函数
    EN=12∑n=1N∑k=1c(znk−ynk)2
    znk (【1】用 znk 表示)是第n个实例的ground truth的对应第k个维度的label (0 or 1表示是否是这个类别).
    从这个形式可以看出来,最小化差方形式的损失函数,等价于同时最大化truth label的概率,最小化false label的概率。而negtative log likelihood 只是最大化truth label的概率。
    Loss function对output以及pre activation的求导:
    ∂L(x,z)∂yk=−zkyk
    对于二分类的情况
    ∂L(x,z)∂y=−1−z1−y−zy=y−zy(1−y)
    利用链式法则,可以得到对于pre-activation的导数
    ∂L(x,z)∂a=∂L(x,z)∂y∂y∂a=y(1−y) y−zy(1−y)=y−z
    对于多分类的偏导,也可以使用类似的方式求偏导
    ∂L(x,z)∂ak=∑k′=1K∂L(x,z)∂yk′∂yk′∂ak
    最后可以得到
    ∂L(x,z)∂ak=yk−zk
    我们用上标 l 表示该蚕食是位于第 l 层,当前层,那么当前层的输出可以表示为
    xl=θ(al),al=Wlxl+bl
    θ 是激活函数,可以取sigmoid σ 或是 tanh 函数。

    反向传播

    由于神经网络是有多层,但是只有输出层才有ground truth的label以及模型输出,根据“误差”向误差减小方向调整权值。但是对于隐含层,没有ground truth label,这就需要由输出层将“误差”传播到隐含层。这里的“误差”,是损失函数对pre-activation的偏导,也可以看做损失函数对于bias b的敏感度:
    δ=∂E∂b=∂E∂a∂a∂b
    由 al=Wlxl+bl 知道, ∂a∂b=1 ,所以这个解释也可以说的过去。下面是如何反向传播 δ
    δl=∂E∂xl∂xl∂al=∂xl∂al∑∂E∂al+1∂al+1∂xl=θ′(al)∘(Wl+1)Tδl+1
    其中 ∘ 表示element-wise product。
    对于输出层的 δ ,若是损失函数是negtative log, δL=∂E∂a=y−z
    粗体 y 是softmax的输出概率, z 是目标label的one-of-k 向量。
    对于差方损失, δ 可以得到
    δL=θ′(al)∘(yn−zn)
    有了 δ ,就可以通过链式法则来求得对于中间层的偏导:
    ∂E∂Wl=∂E∂al∂al∂Wl=δl(xl−1)T
    ΔWl=−η∂E∂Wl
    η 是学习速率,【1】中介绍实际中对于每个 Wij 都会有一个学习速率 ηij

    卷积神经网络

    卷积神经网络(CNN),含有两种类型的网络连接,卷积层和sub-sampling层。

    卷积层

    每个输出层可以由多个输入层卷积的组合得到,也就是说
    xlj=θ(∑i∈Mjxl−1i∗klij+blj)
    对于每个输出层map的每个输入层map,可以用不同的kernel klij
    Mj 表示第 j 输出map的输入map集合。

    下采样层

    下采样层每个输出层是对对应输入层的下采样,所以输入层输出层都是N
    xlj=θ(βljdown(xl−1j)+blj)
    down(.) 表示下采样,一般来说,这个函数会对一个 n×n 大小的block求和,然后乘以一个乘法 bias β 和一个加法 b .

    卷积层梯度的计算

    类似于BP算法过程,首先是求得下一层敏感度和下一层权值的内积,然后做点乘。在CNN中,卷积层与sub-sampling层是依次挨着的。sub-sampling对nxn大小的block求和,可以看做权值是1。所以先要用nxn大小的全1矩阵与下一层敏感度矩阵做Kronecker积,完成权值相乘与上采样,得到与当前层敏感度大小map。然后与激活函数导数做点乘。
    当然,【1】中提到了下采样之后用一个大小为 β 的标量相乘,看做下采样层的权值都为 β ,所以这里在计算完之后乘以一个 β 。所以式子就是
    δlj=βl+1j(θ′∘up(δl+1j))
    其中,上采样就是与全1矩阵做一个Kronecker积
    up(x)=x⊗1n×n
    这样的话,对于特定map的敏感度求和就得到了对应的bias偏导
    ∂E∂bj=∑u,v(δlj)u,v
    对权值求导就是该权值相连的前一层数据和和当前层的敏感度乘积,由于是共享权值,所以每个权值链接的不是单一输入输出,所以要对所有该权值连接的数据进行求和
    ∂E∂Wlij=∑u,v(δlj)u,v(pl−1i)u,v
    按照【1】中的说法这里单独记录kernel的每个权值在相邻两层的连接元素比较麻烦,但是由于kernel和out map以及input map都是矩形,而且卷积过程是顺序操作,显然可以用互相关来得到对应元素的乘积。可以使用matlab的卷积来进行互相关运算,只不过要先将数据进行翻转。
    可以这么解释,假设一个 k×k 大小的kernel和一个 N×N 大小的图像进行卷积操作,生成的map是 (N−k+1)×(N−k+1) ,对于kernel上的每个weight,会和原来图像的一个 (N−k+1)×(N−k+1) 大小的连续区域的所有元素进行乘积。假设 (1,1) 位置的kernel的weight,会和原来map(图像)右下方 (N−k+1)×(N−k+1) 的区域每个元素乘积,然后贡献到下层map的 (N−k+1)×(N−k+1) 的每个对应位置上。所以与(1,1)相关的元素是输入层map的右下方的 (N−k+1)×(N−k+1) 和输出层的 (N−k+1)×(N−k+1) 大小map。所以说反向传播过程中的偏导计算可以使用互相关操作来完成,用matlab代码:
    ∂E∂kli,j=rot180(conv2(xl−1i),rot180(δlj,′valid′))
    注意到前面还有一个 rot180 操作,那是因为(1,1)在输入层map对应的是右下方 (N−k+1)×(N−k+1) 区域,所以互相关之后还是在右下方 (k,k) 位置,所以要旋转180度得到(1,1)位置。

    下采样层梯度的运算

    首先是计算敏感度map δlj ,由反向传播计算下一层的敏感度 δl+1j 计算,与kernel相乘然后与激活函数的导数做element-wise相乘。下一层是卷积操作,当前层map的每个元素通过kernel的不同链接与下一层的map的多个元素有链接。所以用下一层map敏感度与kernel进行互相关操作得到BP敏感度公式中权值和下层敏感度的乘积。
    δlj=θ′(alj)∘conv2(δl+1j,rot180(kl+1j),′full′)
    注意到这里用的是full,在前向过程计算下层中,下层元素每维度少了 k−1,(n−k+1)×(n−k+1) ,所以对于边缘,例如input map (1,1)位置,只和output map的(1,1)有关,所以需要用0补全然后再做互相关操作。
    然后就是求参数 bj 和 βj 的偏导了。
    bj 的偏导仍是把该层敏感度相加
    ∂E∂bj=∑u,v(δlj)u,v
    然后求权值偏导,首先保存下采样数据
    dlj=down(xl−1j)
    然后对所有相连的数据相乘求和
    ∂E∂βj=∑u,v(δlj∘dlj)u,v

    学习特征map的组合

    现有的output map是由多个不同的map组合的,但是如何组合目前还是通过人工的方式进行选择,如何自动地进行学习哪些input map可以组成哪些output map呢?
    我们设定 αij 是组成output map j时,input map i所占有的权重,所以就有:
    xlj=θ(∑i=1Ninαij(xl−1i∗kli+blj)
    subject to
    ∑iαij=1,  and  0≤αij≤1
    αij 是一个概率,可以用softmax函数来表示 αij=exp(cij)∑kexp(ckj)
    cij 表示对应的weight,由于这里j都是一样,所以可以把下班j省立
    对 cj 求偏导
    ∂αk∂ci=δkiαi−αiαk
    这里的 δki 是指示函数,k==i时为1,不等时为0.
    再求损失函数对 αi 的偏导
    ∂E∂αi=∂E∂al∂al∂αi=∑u,v(δl∘(xl−1i∗kli))u,v
    然后合并起来
    ∂E∂ci=∑k∂E∂αk∂αk∂ci=αi(∂E∂αi−∑k∂E∂αkαk)

    关于sparsity

    加上1范数的regularization。
    E~n=En+λ∑i.j|(αi,j)|
    求导:
    ∂Ω∂ci=∑k∂Ω∂αk∂αk∂ci=λ(|αi|−αi∑k|αk|)
    整个偏导公式:
    ∂E~n∂ci=∂En∂ci+∂Ω∂ci
    参考文献:
    【1】Notes on Convolutional Neural Networks
    【2】http://blog.csdn.net/zouxy09/article/details/9993371
    【3】http://www.cnblogs.com/tornadomeet/p/3468450.html
    【4】Supervised Learning with Recurrent Neural Networks

  • 相关阅读:
    8个高质量免费电子书网站,绝大多数电子书都能找到!
    面试必备:HashMap底层源码原来是这么简单(分析)
    【2023研电赛】商业计划书命题:基于三维视觉感知的可重构智能表面通信设计
    算法通关村第15关【白银】| 海量数据场景下的热门算法题
    《算法导论》14.3 区间树
    问题:如果要编辑建好的建筑和空间,需要在分级按钮( )和细分操作按钮楼层下,才能选中建筑物和空间; #微信#媒体#其他
    【Python高级语法】——迭代器 (Iterator)
    umi浅用
    docker进阶作业
    kubernetes部署rocketmq集群
  • 原文地址:https://blog.csdn.net/liuliuhelingdao/article/details/127652146