CNN反向求导推导

本文主要是借助参考文献1《Notes on Convolutional Neural Networks》的内容,以及博客【2】和【3】里面的内容,对卷积神经网络的推导做个梳理。

激活函数

logistic function

σ(x)=11+ex

hyperbolic tangent
tanh(x)=e2x1e2x+1

两者之间的关系
tanh(x)=2σ(2x)1

对激活函数求导,我们有
tanh(x)x=1tanh(x)2

σ(x)(x)=σ(x)(1σ(x))

Loss Function 及求导

一般定义pre-activation(输出层神经单元用k表示):

ak=hHLwhkbh

所以对于输出层,每个类别的概率可以用softmax函数来计算:
p(Ck|x)=eakKk=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)=(z1)ln(1y)zlny

对于多分类的问题,可以有
L(x,z)=k=1Kzklnyk

或者采用【1】中最小二乘形式的损失函数
EN=12n=1Nk=1c(znkynk)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=1z1yzy=yzy(1y)

利用链式法则,可以得到对于pre-activation的导数
L(x,z)a=L(x,z)yya=y(1y) yzy(1y)=yz

对于多分类的偏导,也可以使用类似的方式求偏导
L(x,z)ak=k=1KL(x,z)ykykak

最后可以得到
L(x,z)ak=ykzk

我们用上标 l 表示该蚕食是位于第l层,当前层,那么当前层的输出可以表示为
xl=θ(al),al=Wlxl+bl

θ 是激活函数,可以取sigmoid σ 或是 tanh 函数。

反向传播

由于神经网络是有多层,但是只有输出层才有ground truth的label以及模型输出,根据“误差”向误差减小方向调整权值。但是对于隐含层,没有ground truth label,这就需要由输出层将“误差”传播到隐含层。这里的“误差”,是损失函数对pre-activation的偏导,也可以看做损失函数对于bias b的敏感度:

δ=Eb=Eaab

al=Wlxl+bl 知道, ab=1 ,所以这个解释也可以说的过去。下面是如何反向传播 δ
δl=Exlxlal=xlalEal+1al+1xl=θ(al)(Wl+1)Tδl+1

其中 表示element-wise product。
对于输出层的 δ ,若是损失函数是negtative log, δL=Ea=yz
粗体 y 是softmax的输出概率, z 是目标label的one-of-k 向量。
对于差方损失, δ 可以得到
δL=θ(al)(ynzn)

有了 δ ,就可以通过链式法则来求得对于中间层的偏导:
EWl=EalalWl=δl(xl1)T

ΔWl=ηEWl
η 是学习速率,【1】中介绍实际中对于每个 Wij 都会有一个学习速率 ηij

卷积神经网络

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

卷积层

每个输出层可以由多个输入层卷积的组合得到,也就是说

xlj=θ(iMjxl1iklij+blj)

对于每个输出层map的每个输入层map,可以用不同的kernel klij
Mj 表示第 j 输出map的输入map集合。

下采样层

下采样层每个输出层是对对应输入层的下采样,所以输入层输出层都是N

xlj=θ(βljdown(xl1j)+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)=x1n×n

这样的话,对于特定map的敏感度求和就得到了对应的bias偏导
Ebj=u,v(δlj)u,v

对权值求导就是该权值相连的前一层数据和和当前层的敏感度乘积,由于是共享权值,所以每个权值链接的不是单一输入输出,所以要对所有该权值连接的数据进行求和
EWlij=u,v(δlj)u,v(pl1i)u,v

按照【1】中的说法这里单独记录kernel的每个权值在相邻两层的连接元素比较麻烦,但是由于kernel和out map以及input map都是矩形,而且卷积过程是顺序操作,显然可以用互相关来得到对应元素的乘积。可以使用matlab的卷积来进行互相关运算,只不过要先将数据进行翻转。
可以这么解释,假设一个 k×k 大小的kernel和一个 N×N 大小的图像进行卷积操作,生成的map是 (Nk+1)×(Nk+1) ,对于kernel上的每个weight,会和原来图像的一个 (Nk+1)×(Nk+1) 大小的连续区域的所有元素进行乘积。假设 (1,1) 位置的kernel的weight,会和原来map(图像)右下方 (Nk+1)×(Nk+1) 的区域每个元素乘积,然后贡献到下层map的 (Nk+1)×(Nk+1) 的每个对应位置上。所以与(1,1)相关的元素是输入层map的右下方的 (Nk+1)×(Nk+1) 和输出层的 (Nk+1)×(Nk+1) 大小map。所以说反向传播过程中的偏导计算可以使用互相关操作来完成,用matlab代码:
Ekli,j=rot180(conv2(xl1i),rot180(δlj,valid))

注意到前面还有一个 rot180 操作,那是因为(1,1)在输入层map对应的是右下方 (Nk+1)×(Nk+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,在前向过程计算下层中,下层元素每维度少了 k1,nk+1)×(nk+1) ,所以对于边缘,例如input map (1,1)位置,只和output map的(1,1)有关,所以需要用0补全然后再做互相关操作。
然后就是求参数 bj βj 的偏导了。
bj 的偏导仍是把该层敏感度相加
Ebj=u,v(δlj)u,v

然后求权值偏导,首先保存下采样数据
dlj=down(xl1j)

然后对所有相连的数据相乘求和
Eβj=u,v(δljdlj)u,v

学习特征map的组合

现有的output map是由多个不同的map组合的,但是如何组合目前还是通过人工的方式进行选择,如何自动地进行学习哪些input map可以组成哪些output map呢?
我们设定 αij 是组成output map j时,input map i所占有的权重,所以就有:

xlj=θ(i=1Ninαij(xl1ikli+blj)

subject to
iαij=1,  and  0αij1

αij 是一个概率,可以用softmax函数来表示
αij=exp(cij)kexp(ckj)

cij 表示对应的weight,由于这里j都是一样,所以可以把下班j省立
cj 求偏导
αkci=δkiαiαiαk

这里的 δki 是指示函数,k==i时为1,不等时为0.
再求损失函数对 αi 的偏导
Eαi=Ealalαi=u,v(δl(xl1ikli))u,v

然后合并起来
Eci=kEαkαkci=αi(EαikEαkαk)

关于sparsity

加上1范数的regularization。

E~n=En+λi.j|(αi,j)|

求导:
Ωci=kΩαkαkci=λ(|αi|αik|αk|)

整个偏导公式:
E~nci=Enci+Ωci

参考文献:
【1】Notes on Convolutional Neural Networks
【2】 http://blog.youkuaiyun.com/zouxy09/article/details/9993371
【3】 http://www.cnblogs.com/tornadomeet/p/3468450.html
【4】Supervised Learning with Recurrent Neural Networks

<think>好的,我现在需要帮助用户理解卷积神经网络CNN)中的反向传播算法的原理和实现步骤。首先,我应该回忆一下CNN的基本结构和反向传播的基本概念,然后结合用户提供的引用内容来组织回答。 用户提供的引用中提到,CNN反向传播涉及到链式法则,并且与全连接网络不同,卷积层和池化层需要特殊处理。引用[1]指出CNN反向传播需要从直观和数学两方面介绍,而引用[3]提到卷积神经网络反向传播过程与其他神经网络类似,但需要考虑卷积操作的特殊性。引用[4]详细讨论了卷积层和池化层的反向传播,特别是池化层的反向传播可能需要记录位置信息。 首先,我需要明确反向传播的整体流程:计算损失函数对参数的梯度,然后利用梯度下降法更新参数。对于CNN来说,主要的不同在于卷积层和池化层的反向传播计算。 接下来,我需要分步骤解释每个层的反向传播过程: 1. **全连接层**:这部分相对简单,类似于传统的多层感知机。需要计算损失对权重和偏置的梯度,这里可以用链式法则,误差项从后向前传递。 2. **卷积层**:这里需要处理卷积操作的反向传播。根据引用[4],卷积层的反向传播实际上是一个转置卷积操作。需要将上一层的误差项通过转置卷积核进行卷积,得到当前层的误差。同时,计算对卷积核的梯度时,需要将输入特征图与误差项进行有效卷积。 3. **池化层**:池化层通常没有可训练参数,但需要将误差项上采样。对于最大池化,需要记录前向传播时最大值的位置,将误差放到对应的位置;平均池化则是将误差平均分配到各个位置。引用[4]提到了这一点,特别是最大池化的实现需要位置信息。 然后,可能需要给出具体的数学公式,以展示梯度是如何计算的。例如,卷积层的梯度计算涉及输入和误差项的卷积操作,而池化层的梯度则需要根据池化类型来处理。 实现步骤方面,需要按照反向传播的顺序,从输出层开始,逐层计算梯度: - 计算损失函数对输出的梯度。 - 反向经过全连接层,计算权重和偏置的梯度,并传递误差。 - 处理池化层的反向传播,上采样误差。 - 处理卷积层的反向传播,计算卷积核的梯度并传递误差到前一层。 此外,需要提到实现时的具体操作,比如在反向传播卷积层时,使用翻转卷积核进行卷积操作,或者转置卷积。同时,池化层在反向传播时需要用到前向传播时记录的位置信息,这点在代码实现中需要注意。 用户可能对数学推导部分感到困惑,因此需要以清晰的步骤和示例来解释,避免过于复杂的公式堆砌。同时,结合引用中的内容,强调卷积反向传播的计算量和两次前向传播相当,如引用[4]所述。 最后,生成相关问题,帮助用户进一步学习,比如梯度计算的具体例子、不同池化层的实现差异、与全连接网络的对比等。 现在,我需要确保回答结构清晰,分点说明原理和步骤,并在适当位置引用提供的资料。同时,检查LaTeX格式是否正确,数学表达式用$...$,独立公式用$$...$$,并生成相关问题。</think>### CNN反向传播算法原理及实现步骤 #### 一、核心原理 卷积神经网络CNN)的反向传播遵循链式求导法则,但需针对卷积层和池化层设计特殊计算规则。核心目标是计算损失函数对卷积核权重、偏置等参数的梯度,并通过梯度下降优化参数[^1][^3]。 #### 二、实现步骤分解 1. **全连接层反向传播** - 梯度公式: $$ \delta^{(l)} = (W^{(l+1)})^T \delta^{(l+1)} \odot \sigma'(z^{(l)}) $$ $$ \frac{\partial L}{\partial W^{(l)}} = \delta^{(l)} (a^{(l-1)})^T $$ 其中$\delta^{(l)}$为当前层误差,$\sigma'$为激活函数导数[^1][^4]。 2. **卷积层反向传播** - **误差传递**:将上层误差$\delta^{(l+1)}$与**翻转180°的卷积核**进行转置卷积(反卷积): $$ \delta^{(l)} = \delta^{(l+1)} *_{\text{rot180}} W^{(l)} \odot \sigma'(z^{(l)}) $$ - **权重梯度计算**:通过输入特征图$a^{(l-1)}$与误差$\delta^{(l)}$的有效卷积: $$ \frac{\partial L}{\partial W^{(l)}} = a^{(l-1)} * \delta^{(l)} $$ [^3][^4] 3. **池化层反向传播** - **最大池化**:误差仅传递到前向传播中最大值的位置,其他位置置零。 - **平均池化**:误差均匀分配到前向传播的对应区域。 例如,2×2平均池化的反向传播公式: $$ \delta^{(l)}_{i,j} = \frac{1}{4} \delta^{(l+1)}_{k} $$ #### 三、实现示例(伪代码) ```python def conv_backward(delta, input, kernel): # 计算卷积核梯度 dW = convolve(input, delta, mode='valid') # 计算传递到上一层的误差 delta_prev = full_convolution(delta, rotate180(kernel)) return dW, delta_prev def max_pool_backward(delta, pool_mask): # pool_mask记录前向传播最大值位置 delta_prev = np.zeros_like(input) for i in positions: delta_prev[i] = delta[pool_mask[i]] return delta_prev ``` #### 四、复杂度分析 反向传播计算量约为**两次前向传播**,主要消耗在卷积操作和误差矩阵的转置计算上[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值