BP推导——续

前言

之前有证明过一次人工神经网络——【BP】反向传播算法证明 ,但是回头看的时候,有很多地方非常不严谨,特此拿出来再单独证明一次BP,并严格保证其严谨性。如果想看看粗略的证明,可以去看我之前的博客,毕竟那个貌似也没人说细节有问题,估计很多人没有动手拆分推导。

三层sigmoid激活函数BP扩展到任意激活函数

第一步:前向传播

下图展示了一个三层神经网络:

这里写图片描述

相关说明:

  • 可见层定义为XX,共有n个单元,下标用ii索引
  • 隐藏层定义为B,共有pp个单元,下标用j索引,偏置为αα
  • 输出层定义为YY,共有q个单元,下标用kk索引,偏置为β
  • 隐藏层到可见层权重矩阵为WW,大小为(p,n)
  • 隐藏层到输出层权重矩阵为V,大小为(q,p)(q,p)

各层神经元的值:

  • 可见层:xixi
  • 隐藏层:bj=σ(ni=1Wjixi+αj)bj=σ(∑i=1nWjixi+αj)
  • 输出层:yk=σ(pj=1Vkjbj+βk)yk=σ(∑j=1pVkjbj+βk)

误差:

  • 采用平方和误差衡量期望输出与实际输出的差别
    E=12k=1q(okyk)2E=12∑k=1q(ok−yk)2

    谢谢楼下@蜜丝特潮所指出的错误:
    这里无论平方里面是(oy)(o−y)还是(yo)(y−o),误差函数的导数均为:
    Ey=12(o2+y22oy)y=yo∂E∂y=12∂(o2+y2−2oy)∂y=y−o

第二步:误差反向传播

模型参数校正是从后往前进行的,所以称为误差逆传播,计算是从输出层到隐藏层,再从隐藏层到输入层。更新的是权重和偏置,称为模型参数,两层的权重和偏置的更新是类似的。

输出层到隐藏层的参数更新

先对权重VkjVkj求梯度:

ΔVkj=EVkj=Eyk×ykVkj=(ykok)×σ(j=1pVkjbj+βk)×bjΔVkj=∂E∂Vkj=∂E∂yk×∂yk∂Vkj=(yk−ok)×σ′(∑j=1pVkjbj+βk)×bj

再对输出层的偏置 βkβk​求梯度:
Δβk=Eβk=Eyk×ykβk=(ykok)×σ(j=1pVkjbj+βk)Δβk=∂E∂βk=∂E∂yk×∂yk∂βk=(yk−ok)×σ′(∑j=1pVkjbj+βk)

隐藏层到输入层的参数更新

先对权重WjiWji求梯度

ΔWji=EWji=Ebj×bjWji=k=1q[Ekyk×ykbj]×bjWji=k=1q[(ykok)×σ(j=1pVkjbj+βk)×Vkj]×σ(i=1nWjixi+αj)×xi=k=1q[Δβk×Vkj]×σ(i=1nWjixi+αj)×xiΔWji=∂E∂Wji=∂E∂bj×∂bj∂Wji=∑k=1q[∂Ek∂yk×∂yk∂bj]×∂bj∂Wji=∑k=1q[(yk−ok)×σ′(∑j=1pVkjbj+βk)×Vkj]×σ′(∑i=1nWjixi+αj)×xi=∑k=1q[Δβk×Vkj]×σ′(∑i=1nWjixi+αj)×xi

再对偏置 αjαj求梯度
Δαj=Eαj=Ebj×bjαj=k=1q[Ekyk×ykbj]×bjαj=k=1q[(ykok)×σ(j=1pVkjbj+βk)×Vkj]×σ(i=1nWjixi+αj)=k=1q[Δβk×Vkj]×σ(i=1nWjixi+αj)Δαj=∂E∂αj=∂E∂bj×∂bj∂αj=∑k=1q[∂Ek∂yk×∂yk∂bj]×∂bj∂αj=∑k=1q[(yk−ok)×σ′(∑j=1pVkjbj+βk)×Vkj]×σ′(∑i=1nWjixi+αj)=∑k=1q[Δβk×Vkj]×σ′(∑i=1nWjixi+αj)

三层任意激活函数BP扩展到任意层数

网络定义

总共有nn层,用l索引层数,第ll层第j个单元到第l1l−1层第ii的连接权重为Wjil,第ll层的第j个单元值用yljyjl索引,偏置用bljbjl索引,则有

yljE=σ(iWljiyl1i+blj)=12j(ojynj)2yjl=σ(∑iWjilyil−1+bjl)E=12∑j(oj−yjn)2

误差对于任意层的偏置参数求导

Eblj=Eylj×yljblj=Eylj×σ(iWljiyl1i+blj)∂E∂bjl=∂E∂yjl×∂yjl∂bjl=∂E∂yjl×σ′(∑iWjilyil−1+bjl)

很容易发现重点在于Eylj∂E∂yjl的推导,这个就是传说中的链式法则,从最后一层递推到第ll层,这一步一定要注意上下标

我之前很理所当然地写出了下式

Eyl=Eyn×ynyn1×yl+1yl

如果按照矩阵求导方法深究这个式子是有问题的,第一项Eyn∂E∂yn是标量对向量的偏导,ynyn1∂yn∂yn−1是列向量对列向量的求导,它俩的维度根本不一样,做不了乘法操作。那么如何执行链式求导?可以从最后层向前推几层试试:

  • 误差函数对第nn层的第i个单元的偏导:

Eyni=oiyi∂E∂yin=oi−yi

  • 误差函数对第n1n−1层的第ii个单元的偏导:

    Eyin1=j[Eyjn×yjnyin1]

  • 误差函数对第n2n−2层的第ii个单元的偏导:

    Eyin2=j[Eyjn1×yjn1yin2]

    然后将误差函数对第n1n−1层的第jj个单元的偏导带入进来就可以求出来
    以此类推…………………

  • 误差函数对第l层的第ii个单元的偏导:

    Eyil=j[Eyjl+1×yjl+1yil]

    上述式子中的Eyl+1i∂E∂yil+1可以用递推的方法求解出来,而另一项是:

    yl+1jyli=σ(iWl+1jiyli+bl+1j)×Wl+1ji∂yjl+1∂yil=σ′(∑iWjil+1yil+bjl+1)×Wjil+1

最终得到误差函数关于第ll层的第i个单元偏置参数的偏导

Ebli=Eylj×σ(iWljiyl1i+blj)=Eyl+1j×yl+1jyli×σ(iWljiyl1i+blj)=j[Eyl+1j×σ(iWl+1jiyli+bl+1j)×Wl+1ji]×σ(iWljiyl1i+blj)∂E∂bil=∂E∂yjl×σ′(∑iWjilyil−1+bjl)=∂E∂yjl+1×∂yjl+1∂yil×σ′(∑iWjilyil−1+bjl)=∑j[∂E∂yjl+1×σ′(∑iWjil+1yil+bjl+1)×Wjil+1]×σ′(∑iWjilyil−1+bjl)

注意上式开头的 j∑j中的 jj是第l+1层的神经元索引,后面的 σ(i+blJ)σ′(∑i+bJl) jj是第i层的索引。

式子看起来很复杂,感觉跟网上看到的不一样啊,网上的多简单,这个看着这么多加和以及乘法,乱七八糟的,必须得验证一下,我们把它套到三层BP中,验证隐层和输出层的偏置更新:

  • 误差对输出层的偏置导数

Ebnj=Eynj×σ(iWnjiyn1i+blj)=(yjoj)×σ(iWnjiyn1i+blj)∂E∂bjn=∂E∂yjn×σ′(∑iWjinyin−1+bjl)=(yj−oj)×σ′(∑iWjinyin−1+bjl)

  • 误差对隐藏层的偏置导数

Ebn1j=j[Eynj×σ(iWnjiyli+bnj)×Wnji]×σ(iWljiyn2i+bn1j)=j[(yjoj)×σ(iWnjiyli+bnj)×Wnji]×σ(iWljiyn2i+bn1j)∂E∂bjn−1=∑j[∂E∂yjn×σ′(∑iWjinyil+bjn)×Wjin]×σ′(∑iWjilyin−2+bjn−1)=∑j[(yj−oj)×σ′(∑iWjinyil+bjn)×Wjin]×σ′(∑iWjilyin−2+bjn−1)

可以发现与第二章的结论完全一致的。

误差对任意层的权重参数求导

这个其实与偏置很类似:

EWlji=Eylj×yljWlji=Eylj×σ(iWljiyl1i+blj)×yl1i=Eblj×yl1i=j[Eyl+1j×σ(iWl+1jiyli+bl+1j)×Wl+1ji]×σ(iWljiyl1i+blj)×yl1i∂E∂Wjil=∂E∂yjl×∂yjl∂Wjil=∂E∂yjl×σ′(∑iWjilyil−1+bjl)×yil−1=∂E∂bjl×yil−1=∑j[∂E∂yjl+1×σ′(∑iWjil+1yil+bjl+1)×Wjil+1]×σ′(∑iWjilyil−1+bjl)×yil−1

简化结果

上面的式子看的头晕眼花,复杂得飞起,网上其它教程为啥都那么简单,只有δl+1δl+1 什么什么的,我们来试试将上式简化一波,同时也是由于神经网络中并不是一个梯度一个梯度更新,你没有看到过谁写梯度更新用for循环分别控制权重wjiwji的两个维度吧,一般都是直接用矩阵运算计算得到ww,记住E是实数值而非向量,WWb一个是二维矩阵,一个是一维列向量,然后利用矩阵求导法则试试。

在此,先规定,我们所求的偏置向量为列向量,这里先套用实值对列向量的导数如下:

Ebl=Eb1Eb2Ebi∂E∂bl=[∂E∂b1∂E∂b2⋮∂E∂bi⋮]

为了便于书写或者与网络的证明方法对齐,我们还设
δl+1jzljEbli=Eyl+1j×σ(iWl+1jiyli+bl+1j)=(iWljiyl1i+blj)=j[Eyl+1j×σ(iWl+1jiyli+bl+1j)×Wl+1ji]×σ(iWljiyl1i+blj)=j(δl+1j×Wl+1ji)×σ(zli)δjl+1=∂E∂yjl+1×σ′(∑iWjil+1yil+bjl+1)zjl=(∑iWjilyil−1+bjl)⇒∂E∂bil=∑j[∂E∂yjl+1×σ′(∑iWjil+1yil+bjl+1)×Wjil+1]×σ′(∑iWjilyil−1+bjl)=∑j(δjl+1×Wjil+1)×σ′(zil)

然后我们简化 Ebl∂Ebl,即误差 对第 ll层偏置向量求导得到的梯度向量
Ebl=[W11l+1W21l+1Wj1l+1W12l+1W22l+1Wj2l+1W1il+1W2il+1Wjil+1]×[δ1l+1δ2l+1δjl+1][σ(z1l)σ(z2l)σ(zil)]=(Wl+1)T×δl+1σ(zl)

注意式子中” ××”代表矩阵与列向量的乘法操作, 代表两个相同维度列向量的对应位置元素乘积。

现在应该熟悉了最终的式子与网上的基本一致。这就是整个BP的推导过程。

后记

此篇博客一方面是对上一篇证明BP的博客的更进一步详解与结论证明,另一方面是为了矫正自己之前对矩阵偏导的误解。矩阵偏导分别包含:行向量对行向量的偏导、行向量对列向量的偏导、列向量对列向量的偏导、列向量对行向量的偏导、矩阵对行向量的偏导、矩阵对列向量的偏导、行向量对矩阵的偏导、列向量对矩阵的偏导、矩阵对矩阵的偏导;在证明BP的时候,要严格按照求导法则来做,不能弄混了。

关于使用矩阵对向量的求导来证BP的一些问题,可以见本人与刘建平老师在深度神经网络(DNN)反向传播算法(BP)博客评论区的讨论,主要针对(WX)X∂(WX)∂X即下一层未激活前的输入向量对上一层激活后的输出向量的偏导值是否为WTWT或者是更大矩阵的讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab学习——强连通分量

前言 最近motion graph相关实验,发现实现运动过渡需要构建运动图,而为了避免运动过渡陷入死胡同,需要对图结构进行裁剪,方法就是计算图模型的极大强联通分量,但是自己懒得去实现,所以就去搜了一下matlab中…

【音频处理】离散傅里叶变换

前言 最近复现音乐驱动舞蹈的文章《Dancing-to-Music Character Animation》,用到了与傅里叶变换很相似的称为常Q变换的方法去分割音乐,所以对傅里叶变换做了一个小了解,本文不深入各种乱糟糟的理论,比如什么蝶形算法啥的&#x…

【音频处理】短时傅里叶变换

前言 上一篇博客讲了离散傅里叶变换,里面的实例是对整个信号进行计算,虽然理论上有N点傅里叶变换(本博客就不区分FFT和DFT了,因为它俩就是一个东东,只不过复杂度不同),但是我个人理解是这个N点是信号前面连续的N个数值…

【theano-windows】学习笔记十九——循环神经网络

前言 前面已经介绍了RBM和CNN了,就剩最后一个RNN了,抽了一天时间简单看了一下原理,但是没细推RNN的参数更新算法BPTT,全名是Backpropagation Through Time。 【注】严谨来说RNN有两个称呼:①结构上递归的recursive n…

【theano-windows】学习笔记二十——LSTM理论及实现

前言 上一篇学习了RNN,也知道了在沿着时间线对上下文权重求梯度的时候,可能会导致梯度消失或者梯度爆炸,然后我们就得学习一波比较常见的优化方法之LSTM 国际惯例,参考网址: LSTM Networks for Sentiment Analysis …

刚体运动学——欧拉角、四元数、旋转矩阵

前言 刚体运动旋转一般用:欧拉角、四元数、轴角对等表示,在对某个坐标旋转的时候,只需将欧拉角或四元数转换为旋转矩阵,并与原始坐标相乘,便可得到旋转以后的坐标。这里主要看看欧拉角、四元数和旋转矩阵。 国际惯例…

刚体运动学-四元数插值

前言 之前对写了一篇关于刚体运动学相关知识博客:刚体运动学——欧拉角、四元数、旋转矩阵,本篇博客就举例来说明,如何在运动捕捉数据中进行四元数插值。 国际惯例,参考博客: 探讨:向量(方向…

【TensorFlow-windows】学习笔记一——基础理解

前言 因为Theano已经停止更新了,所以在前面学完Theano搭建RBM,CNN,RNN相关结构以后,还是得选择一个主流框架的,由于我自身的学习最终是向强化学习靠近,可能用到的仿真环境是openai gym,所以选择了继续学习TensorFlow&…

【TensorFlow-windows】学习笔记二——低级API

前言 上一篇博客初步了解了tensorflow中建立机器学习模型的方法:可以使用eager execution和graph execution两种模式,可以使用高级API estimator中已经封装好的模型,也可以自己创建estimator,更重要的是我们也可以使用低级API自行…

【TensorFlow-windows】学习笔记五——自编码器

前言 上一篇博客介绍的是构建简单的CNN去识别手写数字,这一篇博客折腾一下自编码,理论很简单,就是实现对输入数据的重构,具体理论可以看我前面的【theano-windows】学习笔记十三——去噪自编码器 国际惯例,参考博客&…

【TensorFlow-windows】学习笔记六——变分自编码器

#前言 对理论没兴趣的直接看代码吧,理论一堆,而且还有点复杂,我自己的描述也不一定准确,但是代码就两三句话搞定了。 国际惯例,参考博文 论文:Tutorial on Variational Autoencoders 【干货】一文读懂…

【TensorFlow-windows】学习笔记七——生成对抗网络

前言 既然学习了变分自编码(VAE),那也必须来一波生成对抗网络(GAN)。 国际惯例,参考网址: 论文: Generative Adversarial Nets PPT:Generative Adversarial Networks (GANs) Generative Adversarial Nets in TensorFlow GAN原理学习笔记…

Openpose——windows编译(炒鸡简单)

前言 最近准备看看rtpose的代码,发现已经由openpose这个项目维护着了,由于经常在windows下调试代码,所以尝试了一下如何在windows下编译openpose源码,整体来说非常简单的。 国际惯例,参考博客: [OpenPos…

强化学习——Qlearning

前言 在控制决策领域里面强化学习还是占很重比例的,最近出了几篇角色控制的论文需要研究,其中部分涉及到强化学习,都有开源,有兴趣可以点开看看: A Deep Learning Framework For Character Motion Synthesis and Edit…

【TensorFlow-windows】keras接口学习——线性回归与简单的分类

前言 之前有写过几篇TensorFlow相关文章,但是用的比较底层的写法,比如tf.nn和tf.layers,也写了部分基本模型如自编码和对抗网络等,感觉写起来不太舒服,最近看官方文档发现它的教程基本都使用的keras API,这…

【TensorFlow-windows】keras接口——卷积手写数字识别,模型保存和调用

前言 上一节学习了以TensorFlow为底端的keras接口最简单的使用,这里就继续学习怎么写卷积分类模型和各种保存方法(仅保存权重、权重和网络结构同时保存) 国际惯例,参考博客: 官方教程 【注】其实不用看博客,直接翻到文末看我的c…

【TensorFlow-windows】keras接口——BatchNorm和ResNet

前言 之前学习利用Keras简单地堆叠卷积网络去构建分类模型的方法,但是对于很深的网络结构很难保证梯度在各层能够正常传播,经常发生梯度消失、梯度爆炸或者其它奇奇怪怪的问题。为了解决这类问题,大佬们想了各种办法,比如最原始的…

【TensorFlow-windows】keras接口——卷积核可视化

前言 在机器之心上看到了关于卷积核可视化相关理论,但是作者的源代码是基于fastai写的,而fastai的底层是pytorch,本来准备自己用Keras复现一遍的,但是尴尬地发现Keras还没玩熟练,随后发现了一个keras-vis包可以用于做…

【TensorFlow-windows】投影变换

前言 没什么重要的,就是想测试一下tensorflow的投影变换函数tf.contrib.image.transform中每个参数的含义 国际惯例,参考文档 官方文档 描述 调用方法与默认参数: tf.contrib.image.transform(images,transforms,interpolationNEAREST,…

【TensorFlow-windows】扩展层之STN

前言 读TensorFlow相关代码看到了STN的应用,搜索以后发现可替代池化,增强网络对图像变换(旋转、缩放、偏移等)的抗干扰能力,简单说就是提高卷积神经网络的空间不变性。 国际惯例,参考博客: 理解Spatial Transformer…