【手撕】神经网络反向传播

版权声明:欢迎转载,转载请注明出处:土豆洋芋山药蛋 https://blog.csdn.net/qq_33414271/article/details/85490209

神经网络前向传播一般用于搭建整个神经网络的结构框架,形成整个网络的逻辑通路。反向传播用于更新每层之间的权重,减少损失,进而提升预测准确度。

下面是一个神经网络的结构图:
在这里插入图片描述
第一层是输入层,包含两个神经元i1,i2,和截距项b1;第二层是隐含层,包含两个神经元h1,h2和截距项b2,第三层是输出o1,o2,每条线上标的wi是层与层之间连接的权重,激活函数我们默认为sigmoid函数。

激活函数的作用:
在这里插入图片描述
正如上图所示,每个神经元节点可以分为两部分,第一步是从前面计算而来的net_i,但这个net_i不能直接传送给后面。第二步就是利用激活函数计算出out_i,再根据权重传给后面。

初始化神经网络

附上权重以后如下图:
在这里插入图片描述

其中,
输入数据 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(0.05和0.10),使输出尽可能与原始输出o1,o2(0.01和0.99)接近。

Step1: 前向传播

1. 输入层 \rightarrow 隐含层

计算神经元h1的输入加权和(net_h1):
逻辑表达式为: h = i w + b h=i*w+b

矩阵表示形式为:
[ i 1 i 2 ] [ w 1 w 3 w 2 w 4 ] + b 1 = [ n e t h 1 n e t h 2 ] \begin{bmatrix}i1 & i2\end{bmatrix}\begin{bmatrix}w1 &w3 \\ w2 &w4 \end{bmatrix} +b1=\begin{bmatrix}net_{h1}& net_{h2}\end{bmatrix}

如:
n e t h 1 = w 1 i 1 + w 2 i 2 + b 1 = 0.15 0.05 + 0.2 0.1 + 0.35 = 0.3775 net_{h1}=w1*i1+w2*i2+b1=0.15*0.05+0.2*0.1+0.35=0.3775

再利用Softmax激活函数计算得到 o u t h 1 out_{h1} 传递给下一层:
o u t h 1 = 1 1 + e n e t h 1 = 1 1 + e 0.3775 = 0.593269992 out_{h1}=\frac{1}{1+e^{-net_{h1}}}=\frac{1}{1+e^{-0.3775}}=0.593269992

同理我们可以计算出: o u t h 2 = 0.596884378 out_{h2}=0.596884378

2. 隐含层 \rightarrow 输出层

逻辑表达式为: o = h w + b o=h*w+b

矩阵表示形式为:
[ o u t h 1 o u t h 2 ] [ w 5 w 7 w 6 w 8 ] + b 2 = [ n e t o 1 n e t o 2 ] \begin{bmatrix}out_{h1} & out_{h2}\end{bmatrix}\begin{bmatrix}w5 &w7 \\ w6 &w8 \end{bmatrix} +b2=\begin{bmatrix}net_{o1}& net_{o2}\end{bmatrix}

如:
n e t o 1 = w 5 o u t h 1 + w 6 o u t h 2 + b 2 = 0.45 0.596884378 + 0.6 1 = 1.105905967 net_{o1}=w5*out_{h1}+w6*out_{h2}+b2=0.45*0.596884378+0.6*1=1.105905967

再利用Softmax激活函数计算得到 o u t o 1 out_{o1} 传递给下一层:
o u t o 1 = 1 1 + e n e t o 1 = 1 1 + e 1.105905967 = 0.75136507 out_{o1}=\frac{1}{1+e^{-net_{o1}}}=\frac{1}{1+e^{-1.105905967}}=0.75136507

同理我们可以计算出: o u t o 2 = 0.772928465 out_{o2}=0.772928465

我们得到输出值为[0.75136079 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。

Step 2 :反向传播

1.计算总误差

总误差——使用均方误差(square error):
E t o t a l = ( t a r g e t o u t p u t ) 2 n E_{total}=\frac{\sum(target-output)^2}{n}
target表示目标值,即正确的应该是多少。

所以:
E o 1 = ( t a r g e t o 1 o u t o 1 ) 2 2 = 0.274811083 E_{o1}=\frac{(target_{o1}-out_{o1})^2}{2}=0.274811083
E o 2 = ( t a r g e t o 2 o u t o 2 ) 2 2 = 0.298371109 E_{o2}=\frac{(target_{o2}-out_{o2})^2}{2}=0.298371109

E t o t a l = E o 1 + E o 2 = 0.298371109 E_{total}=E_{o1}+E_{o2}=0.298371109

2.隐含层 \rightarrow 输出层的权值更新:

大体思路:
1.利用偏导数大小量化每个参数对结果的影响(后一个对传向前一个的权重w的偏导)。
2.更新: w + = w η w^+=w-\eta *偏导数

计算偏导数要用到链式求导法则。

比如我们要更新w5

1.计算偏导数
在这里插入图片描述
也就是下图所演示的过程:
在这里插入图片描述

t o t a l o u t o 1 \frac{\partial total}{\partial out_{o1}} 公式表示为:
E t o t a l = ( t a r g e t o 1 o u t o 1 ) 2 2 + ( t a r g e t o 2 o u t o 2 ) 2 2 t o t a l o u t o 1 = ( t a r g e t o 1 o u t o 1 ) = ( 0.01 0.75136507 ) = 0.74136507 E_{total}=\frac{(target_{o1}-out_{o1})^2}{2}+\frac{(target_{o2}-out_{o2})^2}{2}\\ \frac{\partial total}{\partial out_{o1}}=-(target_{o1}-out_{o1})=-(0.01-0.75136507)=0.74136507
.

o u t o 1 n e t o 1 \frac{\partial out_{o1}}{\partial net_{o1}} 公式表示为:
o u t o 1 = 1 1 + e n e t o 1 o u t o 1 n e t o 1 = o u t o 1 ( 1 o u t o 1 ) = 0.75136507 ( 1 0.75136507 ) = 0.186815602 out_{o1}=\frac{1}{1+e^{-net_{o1}}}\\ \frac{\partial out_{o1}}{\partial net_{o1}}=out_{o1}(1-out_{o1})=0.75136507(1-0.75136507)=0.186815602
.
n e t o 1 w 5 \frac{\partial net_{o1}}{\partial w5} 公式表示为:
n e t o 1 = w 5 o u t h 1 + w 6 o u t h 2 + b 2 n e t o 1 w 5 = o u t h 1 = 0.593269992 net_{o1}=w5*out_{h1}+w6*out_{h2}+b2\\ \frac{\partial net_{o1}}{\partial w5}=out_{h1}=0.593269992

所以算出偏导数为:
在这里插入图片描述

2.更新 w w w + w^+
w + = w η t o t a l w 5 = 0.4 0.5 0.082167041 = 0.35891648 w^+=w-\eta *\frac{\partial total}{\partial w5}=0.4-0.5*0.082167041=0.35891648

同理:
w 6 + = 0.408666186 ; w 7 + = 0.511301270 ; w 8 + = 0.561370121 w^+_6=0.408666186; w^+_7=0.511301270; w^+_8=0.561370121

3.隐含层 \rightarrow 隐含层的权值更新:

方法其实与上面说的差不多,但是有个地方需要变一下,在上文计算总误差对w5的偏导时,是从out(o1)---->net(o1)---->w5,但是在隐含层之间的权值更新时,是out(h1)---->net(h1)---->w1,而out(h1)会接受E(o1)和E(o2)两个地方传来的误差,所以这个地方两个都要计算。
在这里插入图片描述

直接放计算结果:在这里插入图片描述

最后更新 w 1 w1 :
在这里插入图片描述
同理:
在这里插入图片描述
 这样误差反向传播法就完成了,最后我们再把更新的权值重新计算,不停地迭代,在这个例子中第一次迭代之后,总误差E(total)由0.298371109下降至0.291027924。迭代10000次后,总误差为0.000035085,输出为[0.015912196,0.984065734] (原输入为[0.01,0.99]),证明效果还是不错的。

所以反向传播最主要的是要清楚求偏导的那个递推公式:
在这里插入图片描述
注意1:从哪开始推?
从最终得到的误差开始,如果输出有多个,应叠加。
注意2:推到哪结束?
利用w计算出了什么(下个节点的net值),就推到 n e t i net_i 对w求偏导为止。

都看到这里了,不如投我一票呗~

本人正在才加2018 CSDN博客之星的评选,NO.77 “土豆洋芋山药蛋”,请投我一票,谢谢大家宝贵的一票~
在这里插入图片描述

参考文献:
原始英文出处:https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/
Charlotte77的关于上一篇文章的翻译:https://www.cnblogs.com/charlotte77/p/5629865.html

猜你喜欢

转载自blog.csdn.net/qq_33414271/article/details/85490209
今日推荐