在讲解误差反向传播算法之前,我们来回顾一下信号在神经网络中的流动过程。请细细体会,当输入向量\(X\)输入感知器时,第一次初始化权重向量\(W\)是随机组成的,也可以理解成我们任意设置了初始值,并和输入做点积运算,然后模型通过权重更新公式来计算新的权重值,更新后的权重值又接着和输入相互作用,如此迭代多次,得到最终的权重。
信号向前传播,权重的更新反向传播,是这样吗?
是的,你的直觉没错,确实是反向传播。
1. 前馈的实质
反向传播这个术语经常被误解为用于多层神经网络的整个学习算法。实际上,反向传播仅指用于计算梯度的方法,而另一种算法,例如随机梯度下降,使用该梯度来进行学习。此外,反向传播经常被误解为仅适用于多层神经网络,但是原则上它可以计算任何函数的导数(对于一些函数,正确的响应是报告函数的导数是未定义的)。
1.1 初始化权重和输入信号
不如我们还是使用上一节矩阵乘法的列子来可视化的讲解,这样有助于我们去理解反向传播。假设有如下三层网络,输入层、隐藏层、输出层,现有一组信号\(X\)输入网络,输入层和隐藏层的链接权重\(W_{input-hidden}\)和隐藏层与输出层之间的权重\(W_{hidden-ouput}\)我们随机初始化。为了清晰效果,我们仅标注了几个权重,第一个输入节点和中间隐藏层第一个节点之间的权重为\(w_{1,1}\) = 0.9,正如上图中的神经网络所示。同样,你可以看到输入的第二节点和隐藏层的第二节点之间的链接的权重为\(w_{2,2}\) = 0.8,隐藏层第三个节点和输出层第二个节点之间链接的权重为\(w_{3,2}\) = 0.2......此命名方式前面解释过,标注之后在分析反向传播时可帮助我们理解。
图5.2.1
输入矩阵:
\[X=\begin{bmatrix} 0.9\\ 0.1\\ 0.8\end{bmatrix}\]
输入层和隐藏层之间的连接权重:
\[W_{input-hidden}=\begin{bmatrix} 0.9 & 0.3&0.4 \\ 0.2& 0.8&0.2 \\ 0.8& 0.1&0.9 \end{bmatrix}\]
隐藏层和输出层之间的连接权重:
\[W_{hidden-output}=\begin{bmatrix} 0.3 & 0.7&0.5 \\ 0.6& 0.5&0.2 \\ \end{bmatrix}\]
1.2 输入层到隐藏层
初始值定义好以后,开始计算输入到隐藏层的组合调节输入值\(X_{hidden}\)。
\[X_{hidden} = W_{input_hidden} \cdot X\]
此处的矩阵乘法还是交由计算机来执行,计算出的答案如下:
\[X_{hidden} =\begin{bmatrix} 0.9 & 0.3&0.4 \\ 0.2& 0.8&0.2 \\ 0.8& 0.1&0.9 \end{bmatrix} \cdot \begin{bmatrix} 0.9\\ 0.1\\ 0.8\end{bmatrix}\]
\[X_{hidden} =\begin{bmatrix} 1.16\\ 0.42\\ 0.62\end{bmatrix}\]
别着急往下走,让我们来整理一下网络的信号流动情况,\(X_{hidden}\)作为第一层的输出,第二层的输入已经正确求解,现在它准备进入隐藏层。
图5.2.2
\(X_{hidden}\)一进入隐藏层,我们就对\(X_{hidden}\)的这些节点使用S激活函数,使其变得更加自然,并且我们把经过S函数处理后的这组输出信号命名为\(O_{hidden}\)。
\[O_{hidden}=Sigmoid(X_{hidden})=Sigmoid(\begin{bmatrix} 1.16\\ 0.42\\ 0.62\end{bmatrix})=\begin{bmatrix} 0.761\\ 0.603\\ 0.650\end{bmatrix}\]
1.3 隐藏层到输出层
让我们再次可视化这些输入到第二层隐藏层的组合调节输入。现在信号已经向前流动到了第二层,下一步当然是计算第三层的输出信号\(X_{output}\)(还未经过S函数的输出信号),计算的方法和前面一样,没有什么区别,不管我们的网络是几层,这种方法都适用。
图5.2.3
于是,我们有:
\[X_{output}=W_{hidden-output} \cdot O_{hidden}=\begin{bmatrix} 0.3 & 0.7&0.5 \\ 0.6& 0.5&0.2 \\ \end{bmatrix} \cdot \begin{bmatrix} 0.761\\ 0.603\\ 0.650\end{bmatrix}= \begin{bmatrix} 0.975\\ 0.888\\ \end{bmatrix}\]
现在,更新示意图展示我们的进展,从初始输入信号开始,一层层往前流动的前馈信号,最后得到了最终层的组合输入信号。
图5.2.4
最后一步当然是使用S函数得到最后一层的输出,用\(O_{ouput}\)表示:
\[O_{ouput}=Sigmoid(X_{output})=Sigmoid( \begin{bmatrix} 0.975\\ 0.888\\ \end{bmatrix} )= \begin{bmatrix} 0.726\\ 0.708\\ \end{bmatrix} \]
前馈信号的流动到此为止,任务完成!通过可视化的图形,前馈神经网络中信号流入方向,变化等情况我们用网络图最后形展示出来。
图5.2.5
毫无疑问,整个过程就是前馈的意思,信号一直向前流动,最后输出,中间任意层没有信号反回上一级网络。
下一步我们会将神经网络的输出值与训练样本中的输出值进行比较,计算出误差,并使用这个误差值来反向调节权重值。
2. 反向传播的实质
上一步我们得到了前向传播的输出值为[0.726, 0.708],这个值与真实值[0.01,0.99]还存在一定差距,不过没关系,反向传播误差会帮助我们更新权值,缩小这些误差,让我们来实验一下。
2.1 计算总误差
因为总误差为:\(E=\sum(target-O_{output})^2=E_{1}+E_{2}=(target1-O_{output1})^2+(target2-O_{output2})^2\)
由于我们的实验网络有两个输出,因此总误差为两个输出误差之和。
第一个误差:
\[E_{1}=(target_{1}-O_{output1})^2=(0.726-0.01)^2=0.512656\]
第二个误差:
\[E_{2}=(target_{2}-O_{output2})^2=(0.706-0.99)^2=0.079524\]
总误差:
\[E=E_{1}+E_{2}=0.512656+0.079524=0.59218\]
2.2 隐藏层和输出层的权重更新
对于隐藏层和输出层之间的权重\(w_{1,1}\)来说,如果我们想知道\(w_{1,1}\)对整体误差产生了多少影响,可以用总误差对\(w_{1,1}\)求偏导,该偏导可以使用链式法则表示。
\[\frac{\partial E}{\partial w_{1,1}}=\frac{\partial E}{\partial O_{ouput1}} \cdot \frac{\partial O_{ouput1}}{\partial X_{ouput1}} \cdot \frac{\partial X_{ouput1}}{\partial w_{1,1}}\]
如图所示的反向传播示意图,并结合求导表达式,可以帮助我们更清楚的了解误差是怎么反向传播的。
图5.2.6
下面我们对以上求导式子中的每个小式子分别求值
1、首先是计算$\frac{\partial E}{\partial O_{ouput1}} $
\[E=(target_{1}-O_{output1})^2+(target2-O_{output2})^2\]
\[\frac{\partial E}{\partial O_{ouput1}}=-2(target_{1}-O_{output1})+0=-2(0.01-0.726)=1.432\]
2、再来计算\(\frac{\partial O_{ouput1}}{\partial X_{ouput1}}\)
\[O_{ouput1}=\frac{1}{1+e^{-X_{ouput1}}}\]
\[\frac{\partial O_{ouput1}}{\partial X_{ouput1}}=O_{ouput1}(1-O_{ouput1})=0.726(1-0.726)=0.198924\]
3、最后计算\(\frac{\partial X_{ouput1}}{\partial w_{1,1}}\)
\[X_{ouput1}=w_{1,1} \cdot O_{hidden1}+w_{2,1} \cdot O_{hidden2}+w_{3,1} \cdot O_{hidden3}\]
\[\frac{\partial X_{ouput1}}{\partial w_{1,1}}=O_{hidden1}=0.761\]
所以:
\[\frac{\partial E}{\partial w_{1,1}}=\frac{\partial E}{\partial O_{ouput1}} \cdot \frac{\partial O_{ouput1}}{\partial X_{ouput1}} \cdot \frac{\partial X_{ouput1}}{\partial w_{1,1}}=1.432 \times 0.198924 \times 0.761=0.216777826848\]
我们取学习率\(\eta=0.5\),利用公式\[{w_{1,1}}_{new}=w_{1,1}-\eta \frac{\partial E}{\partial w_{1,1}}\]
得到更新后的\({w_{1,1}}_{new}\)为:\[{w_{1,1}}_{new}=0.3-0.5 \times 0.216777826848=0.191611086576\]
综上所述,也可以这样去计算\(\frac{\partial E}{\partial w_{1,1}}\):
\[\frac{\partial E}{\partial w_{1,1}}=-2(target_{1}-O_{output1}) \cdot O_{ouput1}(1-O_{ouput1}) \cdot O_{hidden1}\]
因此,改变上述式子的变量可以更新\(w_{2,1}\),\(w_{2,1}\),\(w_{1,2}\),\(w_{2,2}\),\(w_{3,2}\)等权重值。
2.3 输入层和隐藏层的权重更新
计算输入层和隐藏层之间的权重和上面的方法一样,但使用误差对权重进行求导时,该误差应使用两个输出口的总误差,而不是一个输入口的误差。我们仍然用图形化的方式来展示:
图5.2.7
如上图所示,对于隐藏层和输出层之间的权重\(w_{1,1}\)来说,如果我们想知道\(w_{1,1}\)对整体误差产生了多少影响,可以用总误差对\(w_{1,1}\)求偏导,该偏导可以使用链式法则表示。
\[\frac{\partial E}{\partial w_{1,1}}=\frac{\partial E}{\partial O_{hidden1}} \cdot \frac{\partial O_{hidden1}}{\partial X_{hidden1}} \cdot \frac{\partial X_{hidden1}}{\partial w_{1,1}}\]
我们还是一个一个的计算上面的式子。
1、首先计算\(\frac{\partial E}{\partial O_{hidden1}}\)
对于隐藏层的输出,它会接受来自两个输出传来的误差,所以:
\[\frac{\partial E}{\partial O_{hidden1}}=\frac{\partial E_{1}}{\partial O_{hidden1}}+\frac{\partial E_{2}}{\partial O_{hidden1}}\]
\[\because \frac{\partial E_{1}}{\partial O_{hidden1}}=\frac{\partial E_{1}}{\partial X_{output1}} \cdot \frac{\partial X_{output1}}{\partial O_{hidden1}}\]
\[\because \frac{\partial E_{1}}{\partial X_{output1}}=\frac{\partial E_{1}}{\partial O_{output1}} \cdot \frac{\partial O_{output1}}{\partial X_{output1}}=1.437 \times 0.198924=0.285853788\]
下面的\(w'_{j,k}\)为隐藏层和输出层的链接权重
\[X_{output1}=w'_{1,1} \cdot O_{hidden1}+w'_{2,1} \cdot O_{hidden2}+w'_{3,1} \cdot O_{hidden3}\]
\[\therefore \frac{\partial X_{output1}}{\partial O_{hidden1}}=w'_{1,1}=0.3\]
\[\therefore \frac{\partial E_{1}}{\partial O_{hidden1}}=\frac{\partial E_{1}}{\partial X_{output1}} \cdot \frac{\partial X_{output1}}{\partial O_{hidden1}}=0.285853788 \times 0.3=0.0857561364\]
再来计算\(\frac {\partial E_{2}}{\partial O_{hidden1}}\)
\[\because \frac{\partial E_{2}}{\partial O_{hidden1}}=\frac{\partial E_{2}}{\partial X_{output2}} \cdot \frac{\partial X_{output2}}{\partial O_{hidden1}}\]
\[\because \frac{\partial E_{2}}{\partial X_{output2}}=\frac{\partial E_{2}}{\partial O_{output2}} \cdot \frac{\partial O_{output2}}{\partial X_{output2}}\]
\[\because X_{output2}=w'_{1,2} \cdot O_{hidden1}+w'_{2,2} \cdot O_{hidden2}+w'_{3,2} \cdot O_{hidden3}\]
\[\therefore \frac{\partial X_{output2}}{\partial O_{hidden1}}=w'_{1,2}\]
\[\therefore \frac{\partial E_{2}}{\partial O_{hidden1}}=\frac{\partial E_{2}}{\partial X_{output2}} \cdot \frac{\partial X_{output2}}{\partial O_{hidden1}}=-0.116599104 \times 0.2=-0.0233198208\]
最后得到
\[\frac{\partial E}{\partial O_{hidden1}}=\frac{\partial E_{1}}{\partial O_{hidden1}}+\frac{\partial E_{2}}{\partial O_{hidden1}}=0.0857561364-0.0233198208=0.0624363156\]
2、再计算\(\frac{\partial O_{hidden1}}{\partial X_{hidden1}}\)
\[\because O_{hidden1}=\frac{1}{1+e^{-X_{hidden1}}}\]
\[\frac{\partial O_{hidden1}}{\partial X_{hidden1}}=O_{hidden1}(1-O_{hidden1})=0.761(1-0.761)=0.181879\]
3、最后计算\(\frac{\partial X_{hidden1}}{\partial w_{1,1}}\)
\[\because X_{hidden1}=w_{1,1} \cdot X_{1}+w_{2,1} \cdot X_{2}+w_{3,1} \cdot X_{3}\]
\[\therefore \frac{\partial X_{hidden1}}{\partial w_{1,1}}=X1=0.9\]
\[\frac{\partial E}{\partial w_{1,1}}=\frac{\partial E}{\partial O_{hidden1}} \cdot \frac{\partial O_{hidden1}}{\partial X_{hidden1}} \cdot \frac{\partial X_{hidden1}}{\partial w_{1,1}}=0.0624363156 \times 0.181879 \times 0.9=0.01022026918051116\]
我们取学习率\(\eta=0.5\),利用公式\[{w_{1,1}}_{new}=w_{1,1}-\eta \frac{\partial E}{\partial w_{1,1}}\]
得到更新后的\({w_{1,1}}_{new}\)为:\[{w_{1,1}}_{new}=0.9-0.5 \times 0.01022026918051116=0.191611086576=0.89488986540974442\]
同样的方法可以更新其他权重的值。这样我们就完成了误差反向传播算法的介绍,在实际训练中我们通过这种方法不停的迭代,直到总误差接近0为止,得到的最优权重保留下来,训练完成。
参考文献:
1、《Python神经网络编程》
2、https://www.cnblogs.com/charlotte77/p/5629865.html