最近学习神经网络的前向和反向传播,读起来比较难懂,一大堆的公式推导,现在,我用一个例子来对前向传播和反向传播进行讲解。
我们要讲解的例子如下所示:
在上述例子中,我们设输入 x1=0.1,x2=0.2x1=0.1,x2=0.2x1=0.1,x2=0.2,各权重为 w1=0.15,w2=0.25,w3=0.3,w4=0.35,w5=0.4,w6=0.36,w7=0.45,w8=0.5w1=0.15,w2=0.25,w3=0.3,w4=0.35,w5=0.4,w6=0.36,w7=0.45,w8=0.5w1=0.15,w2=0.25,w3=0.3,w4=0.35,w5=0.4,w6=0.36,w7=0.45,w8=0.5 ,偏置项的值始终为1,其权重分别为 b11=b12=0.3,b21=b22=0.6b11=b12=0.3,b21=b22=0.6b11=b12=0.3,b21=b22=0.6 ,输出为 o1=0.5,o2=1o1=0.5,o2=1o1=0.5,o2=1,设隐藏层和输出层的激活函数都为 sigmoidsigmoidsigmoid 函数。
1. 前向传播
-
计算 x→hx \rightarrow hx→h
设 h1h1h1 的输入为 inputh1input_{h1}inputh1,则可以计算出
inputh1=w1∗x1+w3∗x2+b11∗1=0.15∗0.1+0.3∗0.2+0.3∗1=0.375\begin{aligned} input_{h1} &= w1 * x1 + w3 * x2 + b11 * 1 \\ &= 0.15*0.1 + 0.3*0.2+0.3*1 \\ &= 0.375 \end{aligned}inputh1=w1∗x1+w3∗x2+b11∗1=0.15∗0.1+0.3∗0.2+0.3∗1=0.375同理可计算出
inputh2=w2∗x1+w4∗x2+b12∗1=0.25∗0.1+0.35∗0.2+0.3∗1=0.395\begin{aligned} input_{h2} &= w2 * x1 + w4 * x2 + b12 * 1 \\ &= 0.25*0.1 + 0.35*0.2+0.3*1 \\ &= 0.395 \end{aligned}inputh2=w2∗x1+w4∗x2+b12∗1=0.25∗0.1+0.35∗0.2+0.3∗1=0.395 -
计算隐藏层
由于激活函数为 sigmoidsigmoidsigmoid 函数,所以,可以得到
outputh1=11+e−inputh1=0.5926665999540697outputh2=11+e−inputh2=0.5974857658270161 output_{h1} = \frac{1}{1+e^{-input_{h1}}}=0.5926665999540697 \\ output_{h2} = \frac{1}{1+e^{-input_{h2}}}=0.5974857658270161 outputh1=1+e−inputh11=0.5926665999540697outputh2=1+e−inputh21=0.5974857658270161 -
计算 h→oh \rightarrow oh→o
设 o1o1o1 的输入为 inputo1input_{o1}inputo1,则可以计算出
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ input_{o1} &= …同理可计算出
inputo2=w6∗outputh1+w8∗outputh2+b22∗1=0.36∗0.5926665999540697+0.5∗0.5974857658270161+0.6∗1=1.1121028588969732\begin{aligned} input_{o2} &= w6 * output_{h1} + w8 * output_{h2} + b22 * 1 \\ &= 0.36*0.5926665999540697 + 0.5*0.5974857658270161+0.6*1 \\ &= 1.1121028588969732 \end{aligned}inputo2=w6∗outputh1+w8∗outputh2+b22∗1=0.36∗0.5926665999540697+0.5∗0.5974857658270161+0.6∗1=1.1121028588969732 -
计算输出层
由于激活函数为 sigmoidsigmoidsigmoid 函数,所以,可以得到
outputo1=11+e−inputo1=0.7513705371459397outputo2=11+e−inputo2=0.7525209414502783 output_{o1} = \frac{1}{1+e^{-input_{o1}}}=0.7513705371459397 \\ output_{o2} = \frac{1}{1+e^{-input_{o2}}}=0.7525209414502783 outputo1=1+e−inputo11=0.7513705371459397outputo2=1+e−inputo21=0.7525209414502783
2. 反向传播
反向传播实则就是求各个权重对损失函数的梯度,然后按照负梯度的方向对各个损失函数进行梯度下降处理。
-
计算损失
在这里,我们使用平方差损失来作为损失函数,由此可以得到总损失表达如下:
Eall=Eo1+Eo2=12(o1−outputo1)2+12(o2−outputo2)2=12(0.5−0.7513705371459397)2+12(1−0.7525209414502783)2=0.06221651568284743\begin{aligned} E_{all} &=E_{o1}+E_{o2} \\ &=\frac{1}{2}(o1-output_{o1})^2+\frac{1}{2}(o2-output_{o2})^2 \\ &= \frac{1}{2}(0.5-0.7513705371459397)^2+\frac{1}{2}(1-0.7525209414502783)^2 \\ &= 0.06221651568284743 \end{aligned}Eall=Eo1+Eo2=21(o1−outputo1)2+21(o2−outputo2)2=21(0.5−0.7513705371459397)2+21(1−0.7525209414502783)2=0.06221651568284743下面我们以 w5w5w5 为例,更新权重。 -
计算偏导数
为了更新 w5w5w5,使得更新后的 w5w5w5 能够更加准确的拟合,我们需要计算出损失函数对 w5w5w5 的偏导数,然后按照梯度下降的方向对 w5w5w5 进行更新,w5w5w5 的偏导数表示如下:
∂Eall∂w5=∂Eall∂outputo1⋅∂outputo1∂inputo1⋅∂inputo1∂w5 \frac{\partial E_{all}}{ \partial w5}=\frac{ \partial E_{all}}{ \partial output_{o1}} \cdot \frac{ \partial output_{o1}}{ \partial input_{o1}} \cdot \frac{ \partial input_{o1}} { \partial w5} ∂w5∂Eall=∂outputo1∂Eall⋅∂inputo1∂outputo1⋅∂w5∂inputo1至于为什么这么表示呢,我们只截取一部分原图来讲解,请看下图
上图中,与 w5w5w5 有关系的我已经用红线画出来了, w5w5w5 能够影响到最后结果的途径就是我红线画出来的东西,以上途径中包含三个部分,一是对 w5w5w5 的加权,而是对 o1o1o1 输入的激活函数,三是对激活后的输出进行的损失计算,这三个部分都有 w5w5w5 的影响在里面,所以根据链式求导法则, w5w5w5 的偏导数表示如上。
对上面的每一部分进行计算
∂Eall∂outputo1=∂[12(o1−outputo1)2+12(o2−outputo2)2]∂outputo1=−(o1−outputo1)=0.2513705371459397∂outputo1∂inputo1=∂11+e−inputo1∂inputo1=0.18681285305496176∂inputo1∂w5=∂[w5∗outputh1+w7∗outputh2+b21∗1]∂w5=outputh1=0.5926665999540697\begin{aligned} \frac{ \partial E_{all}}{ \partial output_{o1}} &=\frac{ \partial [\frac{1}{2}(o1-output_{o1})^2+\frac{1}{2}(o2-output_{o2})^2]}{ \partial output_{o1}} \\ \\ &=-(o1-output_{o1}) \\ \\ &=0.2513705371459397 \\ \\ \frac{ \partial output_{o1}}{ \partial input_{o1}}&=\frac{ \partial \frac{1}{1+e^{-input_{o1}}}}{ \partial input_{o1}} \\ \\ &=0.18681285305496176 \\ \\ \frac{ \partial input_{o1}} { \partial w5} &=\frac{ \partial [w5 * output_{h1} + w7 * output_{h2} + b21 * 1]} { \partial w5} \\ \\ &= output_{h1} =0.5926665999540697 \end{aligned}∂outputo1∂Eall∂inputo1∂outputo1∂w5∂inputo1=∂outputo1∂[21(o1−outputo1)2+21(o2−outputo2)2]=−(o1−outputo1)=0.2513705371459397=∂inputo1∂1+e−inputo11=0.18681285305496176=∂w5∂[w5∗outputh1+w7∗outputh2+b21∗1]=outputh1=0.5926665999540697 所以有,
∂Eall∂w5=∂Eall∂outputo1⋅∂outputo1∂inputo1⋅∂inputo1∂w5=0.027831177385208006\begin{aligned} \frac{\partial E_{all}}{ \partial w5} &=\frac{ \partial E_{all}}{ \partial output_{o1}} \cdot \frac{ \partial output_{o1}}{ \partial input_{o1}} \cdot \frac{ \partial input_{o1}} { \partial w5} \\ \\ &= 0.027831177385208006 \end{aligned}∂w5∂Eall=∂outputo1∂Eall⋅∂inputo1∂outputo1⋅∂w5∂inputo1=0.027831177385208006 -
更新权重
得到了 w5w5w5 的偏导数后,对其进行负梯度的更新,此时的更新需要设置一个学习率 η\etaη,它能够控制每一轮从负梯度中更新多少,这里我们设置 η=0.3\eta=0.3η=0.3,得到
w5=w5−η∗∂Eall∂w5=0.4−0.3∗0.027831177385208006=0.3916506467844376\begin{aligned} w5&=w5-\eta * \frac{\partial E_{all}}{ \partial w5} \\ \\ &=0.4-0.3 * 0.027831177385208006 \\ &= 0.3916506467844376 \end{aligned}w5=w5−η∗∂w5∂Eall=0.4−0.3∗0.027831177385208006=0.3916506467844376按照同样的方式可以更新其他参数,需要注意的是,在更新 w1w1w1 等参数时,其产生的影响会有不止一条路径,将其进行相加即可,如下图的红线即为 w1w1w1 施加影响的路径:
按照上述方法反复进行前向传播、反向传播,即可不断更新权值,不断的优化神经网络,使损失逐渐减小。