反向传播深度推理

  1. 前言:反向传播实质就是链式求导法则的反复用。本文记录一下反向传播的过程,也是为了理解后续出现的梯度消失和爆炸问题(连乘效应)。本文完全按照一位大佬的博客来推理反向传播。

说起神经网络大家会想起以下的只有三层的简单神经网络

该神经网络共三层:输入层(L1)、隐含层(L2)和输出层(L3)。我们现在手里有一堆数据{x1,x2,x3,......,xn},输出也是一堆数据{y1,y2,y3,......,yn}。现在就是要把这些数据灌进去,经过隐含层做某种变换,获得我们期望的输出结果。

case1:如果我们希望输出与输入一样,那这样就是常见的自编码模型(Auto-Encoder)。可能有人会问,为什么要输入输出都一样呢?有什么用啊?其实应用挺广的,在图像识别,文本分类等等都会用到,大佬说他会专门再写一篇Auto-Encoder的文章来说明,包括一些变种之类的。

case2:如果你的输出与原始输入不一样,那么就是很常见的人工神经网络了。相当于让原始数据通过一个映射来得到我们想要的输出数据。这也是我接下来要学习所记录的。

本文直接举一个例子,带入数值演示反向传播法的过程,公式的推导等到下次写Auto-Encoder的时候再写,其实也很简单,感兴趣的同学可以自己推导下试试:(推导过程见另一篇博客))

假设有这样一个网络:

 第一层是输入层包含两个神经元i1,i2以及一个截距项b1; 第二层是隐藏层,包含两个神经元h1,h2以及一个截距项b2,第三层是输出o1和o2。每条线上标的wi是层与层之间连接的权重。激活函数我们默认为sigmoid函数。

现在对他们赋上初值如下:

 其中,

输入数据i1=0.05,i2=0.10

输出数据o1=0.01, o2=0.99

权重w1=0.15, w2=0.20, w3=0.25, w4=0.30, w5=0.40, w6=0.45, w7=0.50, w8=0.55

目的:给出输入数据i1和i2,使输出尽可能与原始输出o1和o2接近。

step1:前向传播

(1)输入层--->隐含层

计算神经元h1的输入加权和:

h1 =(i1*w1+i2*w2)+ b1 = (0.05*0.15+0.10*0.20)+  0.35 = 0.3775

计算神经元h2的输入加权和:

h2 = (i1*w3+i2*w4)+b1 = (0.05*0.25+0.10*0.30) + 0.35 = 0.3925

神经元h1和h2经过激活函数sigmoid后输出为:

out_h1 = S(h1) = sigmoid(h1)  =  \frac{1}{1+e^{-h}}  =  0.5933

同理out_h2 = S(h2) = sigmoid(h2) = 0.5969

(2) 隐含层--->输出层

计算输出层神经元o1和o2的值:

o1 = (out_h1*w5+out_h2*w6) + b2 = (0.5933*0.40+0.5969*0.45) + 0.60 = 1.1059

o2 = (out_h1*w7 + out_h2*w8) + b2 = (0.5933*0.50+0.5969*0.55) + 0.60 = 1.2249

输出层神经元o1和o2经过激活函数sigmoid后输出为:

finalout_{o1}=S(o1)=sigmoid(o1)=0.7514

finalout_{o2}=S(o2)=sigmoid(o2)=0.7729

这样,我们的前向传播的过程就结束了。我们得到输出值为[0.7514, 0.7729],这与实际值[0.01, 0.99]相差还很远。现在我们对误差进行反向传播,更新权值,重新计算输出

step2:反向传播

(1) 计算总误差

总误差(平方误差)

但是有两个输出,所以分别计算o1和o2的误差,总误差为两者之和。

Eo1=\frac{1}{2}\left ( target_{o1} -finalout_{o1}\right )^{2}=\frac{1}{2}\left ( 0.01-0.7514 \right )^{2}=0.2748

Eo2=\frac{1}{2}\left ( target_{o2} -finalout_{o2}\right )^{2}=\frac{1}{2}\left ( 0.99-0.7729 \right )^{2}=0.0236

E_{total}=E_{o1}+E_{o2}=0.2748+0.0236=0.2984

 (2) 隐含层--->输出层的权值更新:

以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5进行求偏导求出:(链式法则)

\frac{\partial E_{total}}{\partial w_{5}}=\frac{\partial E_{total}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1}*\frac{\partial o1}{\partial w_{5}}

(注意:w5与o1(即下图中的net_{o1})关联,然后o1(即下图中的net_{o1})与finalout_{o1}(即下图中的out_{o1})关联, 最后finalout_{o1}与Etotal关联)

下面的图可以更直观的看清楚误差是怎么样做反向传播的:

注意:图中的net_{o1}实际是本文中的o1, out_{o1}}实际是本文中的finalout_{o1}该图是大佬博客里面的原图,我懒得画直接用了。

现在我们分别计算每个式子的值:

\frac{\partial E_{total}}{\partial w_{5}}=\frac{\partial E_{total}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1}*\frac{\partial o1}{\partial w_{5}}


1.求 \frac{\partial E_{total}}{\partial finalout_{o1}} 的值

E_{total}=E_{o1}+E_{o2}=\frac{1}{2}\left ( target_{o1} -finalout_{o1}\right )^{2} + \frac{1}{2}\left ( target_{o2} -finalout_{o2}\right )^{2}

=\frac{\partial E_{total}}{\partial finalout_{o1}}=\left ( target_{o1} -finalout_{o1}\right )\ast \left ( -1 \right )=\left (0.01- 0.7514\right )\ast \left ( -1 \right )=0.7414

2.求\frac{\partial finalout_{o1}}{\partial o1}的值

finalout_{o1}=\frac{1}{1+e^{-o1}}

===>

\frac{\partial finalout_{o1}}{\partial o1}=

\frac{e^{-o1}}{\left ( 1+e^{-o1} \right )^{2}}=finalout_{o1}\ast \left ( 1-finalout_{o1} \right )=0.7514\ast \left ( 1-0.7514 \right )=0.1868

3.求\frac{\partial o1}{\partial w_{5}}的值

o1 = (out_h1*w5+out_h2*w6)

\frac{\partial o1}{\partial w_{5}}=out_h1=0.5933

4.最后三者相乘结果为

\frac{\partial E_{total}}{\partial w_{5}}=\frac{\partial E_{total}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1}*\frac{\partial o1}{\partial w_{5}}=0.7414*0.1868*0.5933=0.0822

这样我们就计算出了整体误差E_{total}对w5的偏导值!!!!!!!!!!!!!

##############################################################

回过头我们再来观察上面三个公式,我们发现:

\frac{\partial E_{total}}{\partial w_{5}}=\frac{\partial E_{total}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1}*\frac{\partial o1}{\partial w_{5}}=

-\left ( target_{o1} -finalout_{o1}\right )*finalout_{o1}\ast \left ( 1-finalout_{o1} \right )*out_h1

注意:out_h1就是out_h1

为了表达方便,我们用\delta _{o1}表示输出层的误差,即:

\delta _{o1}=\frac{\partial E_{total}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1}

\delta _{o1}=-\left ( target_{o1} -finalout_{o1}\right )*finalout_{o1}\ast \left ( 1-finalout_{o1} \right )

因此整体误差E_{total}对w5的偏导可以写成:

\frac{\partial E_{total}}{\partial w_{5}}=\delta _{o1}*out_h1

注意:这个\delta也就是吴恩达视频9-2里面的Delta

如果输出层误差计为负值的话,也可以写成:

\frac{\partial E_{total}}{\partial w_{5}}=-\delta _{o1}*out_h1

最后我们来更新权值w5的值:

w_{5}^{+}=w_{5}-\eta\frac{\partial E_{total}}{\partial w_{5}}=0.40-0.5*0.0822=0.3589

其中,\eta是我们常说的学习率,表征梯度下降的快慢

同理可更新w6,w7,w8:

w_{6}^{+}=0.4087

w_{7}^{+}=0.5113

w_{8}^{+}=0.5614

 (3) 隐含层--->输入层的权值更新:

方法与上面的差不多,但是有个地方需要变一下。在上文计算总误差对w5的偏导时,是从finalout(o1)--->o1(o1)--->w5。

但是在隐含层与输入层之间的权值更新时,是finalout(h1)--->o1(h1)--->w1

而finalout(h1)会接受Eo1和Eo2两个地方传来的误差,所以这个地方两个都要算。

为什么finalout(h1)会跟Eo1和Eo2两个有关联?

回答:对于Eo2--->finalout_{o2}--->o2--->out_h1,说明h1除了跟E01有关系,也是跟Eo2有关系的。

1.首先计算总误差E_{total}带来的影响\frac{\partial E_{total}}{\partial out_h1}

E_{total}=E_{o1}+E_{o2}可知:

\frac{\partial E_{total}}{\partial out_h1}=\frac{\partial E_{o1}}{\partial out_h1}+\frac{\partial E_{o2}}{\partial out_h1}

1)先计算 \frac{\partial E_{o1}}{\partial out_h1}

\frac{\partial E_{o1}}{\partial out_h1}=\frac{\partial E_{o1}}{\partial o1}*\frac{\partial o1}{\partial out_h1}=(\frac{\partial E_{o1}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1})*\frac{\partial o1}{\partial out_h1}

又因为:

\frac{\partial o1}{\partial out_h1}=w_{5}

所以:

\frac{\partial E_{o1}}{\partial out_h1}=\frac{\partial E_{o1}}{\partial o1}*\frac{\partial o1}{\partial out_h1}=(\frac{\partial E_{o1}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1})*\frac{\partial o1}{\partial out_h1}=(\frac{\partial E_{o1}}{\partial finalout_{o1}}*\frac{\partial finalout_{o1}}{\partial o1})*w_{5}

=0.7414*0.1868*0.40=0.0554

2)再计算\frac{\partial E_{o2}}{\partial out_h1}

同理计算得到

\frac{\partial E_{o2}}{\partial out_h1}=-0.0190

3)两者相加

\frac{\partial E_{total}}{\partial out_h1}=\frac{\partial E_{o1}}{\partial out_h1}+\frac{\partial E_{o2}}{\partial out_h1}=0.0554-0.0190=0.0364

2.再计算\frac{\partial out_h1}{\partial h1}

因为out_h1=\frac{1}{1+e^{-h1}}

所以

\frac{\partial out_h1}{\partial h1}=out_h1\left ( 1- out_h1\right )=0.5933\left ( 1-0.5933 \right )=0.2413

3.然后再计算\frac{\partial h1}{\partial w_{1}}

因为h1 =(i1*w1+i2*w2)+ b1

所以

\frac{\partial h1}{\partial w_{1}}=i1=0.05

4.最后三者相乘

\frac{\partial E_{total}}{\partial w_{1}}=\frac{\partial E_{total}}{\partial out_h1}*\frac{\partial out_h1}{\partial h1}*\frac{\partial h1}{\partial w1} =0.0364*0.2413*0.05=0.0004

最后更新w1的权值:

w_{1}^{+}=w_{1}-\eta \frac{\partial E_{total}}{\partial w_{1}}=0.15-0.5*0.0004=0.1498

同理,可更新w2,w3,w4的权值:

w_{2}^{+}=0.1996

w_{3}^{+}=0.2498

w_{4}^{+}=0.2995

这样误差反向传播就完成了,最后我们再把更新的权值wi重新计算,不停的迭代。在这个例子中第一次迭代后,总误差E_{total}由0.29837下降到0.29103。迭代一万次后,总误差为0.000035,输出为

[0.015912196,0.984065734](原输入为[0.01,0.99]),证明效果还是不错的。

注意:为什么隐含层到输出层的权重w5, w6, w7, w8在反向传播过程中更新了,而在更新输入层到隐含层的权重w1, w2, w3, w4时,使用到的w5....w8还是未更新之前的0.4, 0.45, 0.5, 0.55?

答:反向传播更新权重时,用到的loss是本次前向推理用到的权重,所以所有的weight都是本次的迭代的。换句话说如果你传播还没结束的过程中就把权重更新了再计算,那你用的loss就不对了。梯度下降法里面的参数更新都是一个一个更新的,用的是更新原来的式子求偏导(看书里都是这样)

参考文章:https://blog.csdn.net/weixin_38347387/article/details/82936585#commentBox

参考文章:BP神经网络与Python实现 - -Finley- - 博客园

参考文章:https://blog.duohuo.org/2019/02/19/155/

参考文章:机器学习练习四:用Python实现BP神经网络 - 掘金

参考文章:PyTorch实现一个简单的神经网络_程序员椰子橙的博客-CSDN博客

参考文章:Pytorch——实现简单的三层网络_我是小杨我就这样的博客-CSDN博客_用pytorch搭建三层神经网络

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值