卷积神经网络CNN的反向传播原理

卷积神经网络CNN的反向传播原理  上一篇博客《详解神经网络的前向传播和反向传播》推导了普通神经网络(多层感知器)的反向传播过程,这篇博客则讨论一下卷积神经网络中反向传播的不同之处。先简单回顾一下普通神经网络中反向传播的四个核心公式:…

大家好,又见面了,我是你们的朋友全栈君。

回顾

  上一篇博客《详解神经网络的前向传播和反向传播》推导了普通神经网络(多层感知器)的反向传播过程,这篇博客参考刘建平Pinard 《卷积神经网络(CNN)反向传播算法》对卷积神经网络中反向传播的不同之处进行了讨论。
  我们先简单回顾一下普通神经网络(DNN)中反向传播的四个核心公式:

δLj=CzLj=CaLjaLjzLj=CaLjσ(zLj)(BP1) (BP1) δ j L = ∂ C ∂ z j L = ∂ C ∂ a j L ∂ a j L ∂ z j L = ∂ C ∂ a j L σ ′ ( z j L )


δl=((wl+1)Tδl+1)σ(zl)(BP2) (BP2) δ l = ( ( w l + 1 ) T δ l + 1 ) ⊙ σ ′ ( z l )


Cblj=Czljzljblj=Czlj=δlj(BP3) (BP3) ∂ C ∂ b j l = ∂ C ∂ z j l ∂ z j l ∂ b j l = ∂ C ∂ z j l = δ j l


Cwljk=CzljzLjwljk=Czljal1k=al1kδlj(BP4) (BP4) ∂ C ∂ w j k l = ∂ C ∂ z j l ∂ z j L ∂ w j k l = ∂ C ∂ z j l a k l − 1 = a k l − 1 δ j l

只要计算出

Cwljk ∂ C ∂ w j k l


Cblj ∂ C ∂ b j l
就能使用梯度下降算法对网络进行训练了。

问题提出

  那么我们能不能直接在CNN上直接套用DNN的传播算法呢?当然不能,不然我也不会写这篇博客了嘿嘿。我们先从最直观的网络结构的角度来分析一下。
1. 全连接层
  CNN中的全连接层和DNN层结构完全一致,这个可以照搬。
2. 池化层
  池化层简而言之就是利用feature map的统计特征来代表这块区域。如下图所示,可以利用红色区域的均值、最大值、最小值等统计量来代表该块红色区域,一方面引入了平移不变性(这个在另外一篇博客中讲),一方面减少了参数数量。但是我们在反向传播时,知道右边 2×2 2 × 2 区域的 δl δ l 的情况下,如何计算左边完整区域的 δl1 δ l − 1 ?而且池化层一般没有激活函数,这个问题怎么处理?



卷积神经网络CNN的反向传播原理


3. 卷积层

  卷积层是通过张量卷积,或者说是若干个矩阵卷积求和而得到当前层的输出,这和DNN直接进行矩阵乘法有很大区别,那么如何递推相应的

δl1 δ l − 1
呢?



卷积神经网络CNN的反向传播原理


4. 反卷积层和BN层

  这个日后弄懂再补上来。

池化层的反向传播

  池化层没有激活函数可以直接看成用线性激活函数,即 σ(z)=z σ ( z ) = z ,所以 σ(z)=1 σ ′ ( z ) = 1 。接下来看看池化层如何递推 δl δ l
  在前向传播时,我们一般使用max或average对输入进行池化,而且池化区域大小已知。反向传播就是要从缩小后的误差 δl+1 δ l + 1 ,还原池化前较大区域对应的误差 δl δ l 。根据(BP2), δl=((wl+1)Tδl+1)σ(zl) δ l = ( ( w l + 1 ) T δ l + 1 ) ⊙ σ ′ ( z l ) ,在DNN中 wl+1 w l + 1 是已知的,所以我们可以直接通过矩阵乘法将 l+1 l + 1 层的误差映射回 l l 层的误差,但对于池化层,要求
(wl+1)Tδl+1


(



w



l


+


1





)


T




δ



l


+


1



就需要一些特殊的操作了。
  用一个例子可以很清楚的解释这一过程:假设现在我们是步长为1的 2×2 2 × 2 池化, 4×4 4 × 4 大小的区域经过池化后变为 2×2 2 × 2 。如果 δl δ l 的第k个子矩阵为:

δl+1k=[2486] δ k l + 1 = [ 2 8 4 6 ]

首先我们要确定

δl+1k δ k l + 1
中4个误差值分别和原来

4×4 4 × 4
大小的哪个子区域所对应,根据前向传播中池化窗口的移动过程,我们可以很轻松的确定2对应左上角

2×2 2 × 2
的区域,8对应右上角

2×2 2 × 2
的区域,以此类推。这一步完成之后,我们就要对不同类型的池化进行不同的操作。

  如果是max pooling,我们只需要记录前向传播中最大值的位置,然后将误差放回去即可。如果最大值位置分别为

2×2 2 × 2
的左上,右下,右上,左下,还原后的矩阵为:


(wl+1)Tδl+1=2000004000060800 ( w l + 1 ) T δ l + 1 = [ 2 0 0 0 0 0 0 8 0 4 0 0 0 0 6 0 ]



  如果是average pooing,我们只需要将池化单元的误差平均值放回原来的子矩阵即可:


(wl+1)Tδl+1=0.50.5110.50.511221.51.5221.51.5 ( w l + 1 ) T δ l + 1 = [ 0.5 0.5 2 2 0.5 0.5 2 2 1 1 1.5 1.5 1 1 1.5 1.5 ]

可以发现这其实就是将上一层的误差进行一次池化的逆操作,还是比较容易理解的。

  得到了

(wl+1)Tδl+1 ( w l + 1 ) T δ l + 1
之后就可以利用

δl=((wl+1)Tδl+1)σ(zl) δ l = ( ( w l + 1 ) T δ l + 1 ) ⊙ σ ′ ( z l )
求得

δlk δ k l
了。

卷积层的反向传播

  继续回到方程(BP2), δl=((wl+1)Tδl+1)σ(zl) δ l = ( ( w l + 1 ) T δ l + 1 ) ⊙ σ ′ ( z l ) ,那你可能会问,之前说池化层因为 wl+1 w l + 1 无法直接计算,所以需要特殊操作,那么卷积核的参数不是知道吗,岂不是可以直接代入计算了。是带进去计算没错,但是权重矩阵需要旋转180°。为什么呢,下面以一个简单的例子说明。
  假设 l l 层的激活输出是一个
3×3


3


×


3

的矩阵,第 l+1 l + 1 层卷积核 Wl+1 W l + 1 是一个 2×2 2 × 2 的矩阵,卷积步长为1,则输出 zl+1 z l + 1 是一个 2×2 2 × 2 的矩阵。我们简化 bl=0 b l = 0 ,则有:

zl+1=alWl+1(1) (1) z l + 1 = a l ∗ W l + 1

列出

a a



W


W




z z
的矩阵表达式如下:


[z11z21z12z22]=a11a21a31a12a22a32a13a23a33[w11w21w12w22](2)





(2)





[






z



11







z



12









z



21







z



22







]



=



[






a



11







a



12







a



13









a



21







a



22







a



23









a



31







a



32







a



33







]







[






w



11







w



12









w



21







w



22







]





利用卷积的定义,很容易得出:

z11=a11w11+a12w12+a21w21+a22w22z12=a12w11+a13w12+a22w21+a23w22z21=a21w11+a22w12+a31w21+a32w22z22=a22w11+a23w12+a32w21+a33w22(3) (3) z 11 = a 11 w 11 + a 12 w 12 + a 21 w 21 + a 22 w 22 z 12 = a 12 w 11 + a 13 w 12 + a 22 w 21 + a 23 w 22 z 21 = a 21 w 11 + a 22 w 12 + a 31 w 21 + a 32 w 22 z 22 = a 22 w 11 + a 23 w 12 + a 32 w 21 + a 33 w 22

接下来我们计算

Cal ∂ C ∂ a l

al=Cal=Czl+1zl+1al=δl+1zl+1al(4) (4) ∇ a l = ∂ C ∂ a l = ∂ C ∂ z l + 1 ∂ z l + 1 ∂ a l = δ l + 1 ∂ z l + 1 ∂ a l

由方程(2)可以得知,

zl+1al ∂ z l + 1 ∂ a l


Wl+1 W l + 1
相关。假设

δl+1=[δ11δ21δ12δ22] δ l + 1 = [ δ 11 δ 12 δ 21 δ 22 ]

在式(3)的4个等式中,

a11 a 11
只和

z11 z 11
有关(

z12,z21,z22 z 12 , z 21 , z 22
表达式中均没有

a11 a 11
),所以

a11=δl+111zl+111al11+δl+112zl+112al11+δl+121zl+121al11+δl+122zl+122al11=δ11w11 ∇ a 11 = δ 11 l + 1 ∂ z 11 l + 1 ∂ a 11 l + δ 12 l + 1 ∂ z 12 l + 1 ∂ a 11 l + δ 21 l + 1 ∂ z 21 l + 1 ∂ a 11 l + δ 22 l + 1 ∂ z 22 l + 1 ∂ a 11 l = δ 11 w 11

同理可以得到其他8个

a ∇ a

a12=δ11w12+δ12w11a13=δ12w12a21=δ11w21+δ21w11a22=δ11w22+δ12w21+δ21w12+δ22w11a23=δ12w22+δ22w12a31=δ21w21a32=δ21w22+δ22w21a33=δ22w22 ∇ a 12 = δ 11 w 12 + δ 12 w 11 ∇ a 13 = δ 12 w 12 ∇ a 21 = δ 11 w 21 + δ 21 w 11 ∇ a 22 = δ 11 w 22 + δ 12 w 21 + δ 21 w 12 + δ 22 w 11 ∇ a 23 = δ 12 w 22 + δ 22 w 12 ∇ a 31 = δ 21 w 21 ∇ a 32 = δ 21 w 22 + δ 22 w 21 ∇ a 33 = δ 22 w 22

其实上面的9个式子可以用一个矩阵卷积的形式统一表示:


a11a21a31a12a22a32a13a23a33=00000δ11δ2100δ12δ2200000[w22w12w21w11](5) (5) [ ∇ a 11 ∇ a 12 ∇ a 13 ∇ a 21 ∇ a 22 ∇ a 23 ∇ a 31 ∇ a 32 ∇ a 33 ] = [ 0 0 0 0 0 δ 11 δ 12 0 0 δ 21 δ 22 0 0 0 0 0 ] ∗ [ w 22 w 21 w 12 w 11 ]



  为了符合梯度计算,我们在误差矩阵周围填充了一圈0,此时我们将卷积核翻转后和反向传播的梯度误差进行卷积,就得到了前一次的梯度误差,然后用(BP2)就可以得到上一层的误差。卷积层的(BP2)形式如下:

δl=(δl+1rot180(wl+1))σ(zl) δ l = ( δ l + 1 ∗ r o t 180 ( w l + 1 ) ) ⊙ σ ′ ( z l )



  还需要注意的是,在利用(BP4)推导该层权重的梯度

Cwl ∂ C ∂ w l
时,也需要进行一个旋转180°的操作:

Cwl=CzlzLwl=δlzLwl=δlrot180(al1) ∂ C ∂ w l = ∂ C ∂ z l ∂ z L ∂ w l = δ l ∂ z L ∂ w l = δ l ∗ r o t 180 ( a l − 1 )



  对于偏置

b b
则有些特殊,因为


δl



δ


l



是3维张量,而

bl b l
只是一个一维向量,不能像DNN中那样直接

Cbl=δl ∂ C ∂ b l = δ l
,通常是将

δl δ l
的各个子矩阵分别求和,得到一个误差向量,即

bl b l
的梯度:


Cbl=u,v(δl)u,v ∂ C ∂ b l = ∑ u , v ( δ l ) u , v

总结

  虽然CNN的反向传播和DNN有所不同,但本质上还是4个核心公式的变形,思路是一样的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/139825.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • ue4动态加载模型(unity资源加载)

    本帖纯属个人原创,如有转载请注明出处需要注意的几点:1.调试环境下进行的资源加载方式到打包出来后不一定能够使用。2.假如遇到调试模式下程序运行正常,但是打包出来后程序crash,可以查看log:Saved/Logs/filename/log3.资源路径的代码书写格式map:”Game/Maps/Main.map”蓝图类:”Game/Blueprint/Skil

  • C语言中的break和continue

    C语言中的break和continue一般在的,while,for这样含有循环体的语句中,某些情况下我们会需要立即跳出当前循环。这时使用break语句就可以实现直接从当前循环体直接跳出开始执行while,for语句的下一条语句。另外,break这种可以从一段复合语句中跳出的功能也被switch广泛借用,来跳过switch复合语句,也就是被花括号框住的代码块中剩余的部分,转去执行switc…

  • Python爬虫系列:爬取小说并写入txt文件

    Python爬虫系列:爬取小说并写入txt文件Python爬虫系列——爬取小说并写入txt文件文章介绍了如何从网站中爬取小说并写入txt文件中,实现了单章节写取,整本写取,多线程多本写取。爬虫使用的python版本为python3,有些系统使用python指令运行本脚本,可能出现错误,此时可以试一试使用python3运行本脚本。本文是一个教程,一步步介绍了如何爬取批量小说内容以及存储这是txt文件中,以下是项目源码地址。

  • pycharm如何创建flask项目_适合flask的前端框架

    pycharm如何创建flask项目_适合flask的前端框架在网上看了很多办法,大都是用用命令行来实现,而且对Windows用户很不友好。其实只要在settings中选择projectinterpreter,再在右边点击+,再搜索flask选择第一个进行install就可以了,pycharm还会帮你装上所需要的其他插件第一篇博客,大家觉得有用的话给个赞可好你好!这是你第一次使用Markdown编辑器所展示的欢迎页。如果你想学习如何使用Mar…

  • vim编辑保存退出「建议收藏」

    vim编辑保存退出「建议收藏」vim编辑保存退出命令vim要打开的文件名字比如要打开test.log命令为:vimtest.log注意:如果不存在test.log则会自动创建进入编辑器后按字母“i”即可进入编辑状态(此时左下角会出现“插入”)退出的时候分为4种情况:保存退出、正常退出、不保存退出以及强制退出 2.1:保存退出:按“Esc”键后此时的“插入”会消失,然后按Shift+zz就可以保存修改内容并退出 2.2:不保存退出:当修改修改了一部分内容后发现修改错了,此时就会进

  • linux内外网配置_服务器内网ip

    linux内外网配置_服务器内网ip1、/etc/sysconfig/network-scripts/ifcfg-eth0创建这个文件里面的内容如下TYPE=“Ethernet”  BOOTPROTO=“none”  DEFROUTE=“yes”  IPV4_FAILURE_FATAL=“no”  NAME=“eth1”  DEVICE=“eth1”  ONBOOT=“yes”  IPADDR=“192.168…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号