我们取网络所有输出层节点的误差平方和作为目标函数:
其中,表示是样本的误差。
然后,我们用文章《零基础入门深度学习(2) - 线性单元和梯度下降》中介绍的随机梯度下降算法对目标函数进行优化:
随机梯度下降算法也就是需要求出误差Ed对于每个权重Wji的偏导数(也就是梯度),怎么求呢?
观察上图,我们发现权重Wji仅能通过影响节点j的输入值影响网络的其它部分,设netj是节点j的加权输入,即
Ed是netj的函数,而netj是Wji的函数。根据链式求导法则,可以得到:
上式中,Xji是节点i传递给节点j的输入值,也就是节点的输出值。
对于
的推导,需要区分输出层和隐藏层两种情况。
输出层权值训练
考虑上式第一项:
考虑上式第二项:
将第一项和第二项带入,得到:
如果令
,也就是一个节点的误差项是网络误差对这个节点输入的偏导数的相反数。带入上式,得到:
上式就是式3。
将上述推导带入随机梯度下降公式,得到:
上式就是式5。
隐藏层权值训练
上式就是式4。
——数学公式警报解除——
至此,我们已经推导出了反向传播算法。需要注意的是,我们刚刚推导出的训练规则是根据激活函数是sigmoid函数、平方和误差、全连接网络、随机梯度下降优化算法。如果激活函数不同、误差计算方式不同、网络连接结构不同、优化算法不同,则具体的训练规则也会不一样。但是无论怎样,训练规则的推导方式都是一样的,应用链式求导法则进行推导即可。
神经网络的实现
现在,我们要根据前面的算法,实现一个基本的全连接神经网络,这并不需要太多代码。我们在这里依然采用面向对象设计。
首先,我们先做一个基本的模型:
如上图,可以分解出5个领域对象来实现神经网络:
Network 神经网络对象,提供API接口。它由若干层对象组成以及连接对象组成。
Layer 层对象,由多个节点组成。
Node 节点对象计算和记录节点自身的信息(比如输出值、误差项等),以及与这个节点相关的上下游的连接。
Connection 每个连接对象都要记录该连接的权重。