计算过程
现在我们有这样一个神经网络:
输入层有两个神经元i1和i2,隐藏层有两个神经元h1和h2,偏差都为b1,输出层有两个神经元o1和o2,偏差都为b2,权重为w
神经元的输入经过激活函数转变为输出,即带权输入net经过激活函数转变为输出激活值out,如图所示:
现在一步一步进行计算
前向传播
输入层 -> 隐藏层
- 计算隐藏层神经元h1与h2的带权输入:
neth1=ω1∗i1+ω2∗i2+b1
neth2=ω3∗i1+ω4∗i2+b1 - 计算h1与h2的输出激活值(激活函数为sigmoid函数):
sigmoid函数: S(x)=11+e−x
outh1=11+e−neth1
outh2=11+e−neth2
隐藏层 -> 输出层
- 计算输出层神经元o1与o2的带权输入:
neto1=ω5∗outh1+ω6∗outh2+b2
neto2=ω7∗outh1+ω8∗outh2+b2 - 计算o1与o2的输出激活值:
outo1=11+e−neto1
outo2=11+e−neto2
至此,我们就计算出了前向传播的输出,接下来进行反向传播
反向传播
计算误差(代价函数)
- 分别计算o1和o2的误差:
这里使用二次代价函数:E=12(target−output)2
Eo1=12(targeto1−outputo1)2
Eo2=12(targeto2−outputo2)2
2. 计算总误差:
总误差为:Etotal=∑12(target−output)2
Etotal=Eo1+Eo2
权值更新
微分知识告诉我们,导数体现变化率,那么权值对于总误差的影响则体现在导数上
要更新权值,就要计算总误差对权值的偏导数,即权值能对总误差产生多少影响,这里用到了链式法则
隐藏层 -> 输出层的权值更新
- 以w5为例:
∂Etotal∂outo1∗∂outo1∂neto1∗∂neto1∂ω5=∂Etotal∂ω5
下图可以更直观的感受反向传播误差: - 分别计算等号左边的三个式子:
- ∂Etotal∂outo1:
Etotal=12(targeto1−outputo1)2+12(targeto2−outputo2)2
∂Etotal∂outo1=−(targeto1−outputo1) - ∂outo1∂neto1(即对sigmoid函数求导):
outo1=11+e−neto1
∂outo1∂neto1=outo1(1−outo1) - ∂neto1∂ω5:
neto1=ω5∗outh1+ω6∗outh2+b2
∂neto1∂ω5=outh1
- 然后乘起来即可:
∂Etotal∂ω5=−(targeto1−outputo1)∗outo1(1−outo1)∗outh1
现在我们得到了整体误差E(total)对w5的偏导值,为了表达方便,在此我们定义:
δ为神经元的误差
(与上文提到的误差不同,上文着重最终结果的误差,此处更着重单个神经元的误差)
- 那么δo1即为神经元o1的误差,即:
δo1=∂Etotal∂outo1∗∂outo1∂neto1=∂Etotal∂neto1
δo1=−(targeto1−outputo1)∗outo1(1−outo1)
所以,整体误差E(total)对w5的偏导为:
∂Etotal∂ω5=δo1∗outh1
最后,w5得到更新:
ω5→ω5−η∗∂Etotal∂ω5
η是学习速率,也叫步长
输入层(隐藏层) -> 隐藏层的权值更新
- 以w1为例:
∂Etotal∂outh1∗∂outh1∂neth1∗∂neth1∂ω1=∂Etotal∂ω1
计算方法与上面类似,但是有个地方需要变一下,在计算h1的误差时,out(h1)会接受来自o1和o2两个神经元的误差,所以在这两个都要计算 - 分别计算等号左边的三个式子:
- ∂Etotal∂outh1:
∂Etotal∂outh1=∂Eo1∂outh1+∂Eo2∂outh1
先计算∂Eo1∂outh1:
∂Eo1∂outh1=∂Eo1∂neto1∗∂neto1∂outh1
其中:
∂Eo1∂neto1=∂Eo1∂outo1∗∂outo1∂neto1
neto1=ω5∗outh1+ω6∗outh2+b2
∂neto1∂outh1=ω5
得到:
∂Eo1∂outh1=∂Eo1∂outo1∗∂outo1∂neto1∗ω5
代入上边计算出的结果可得:
∂Eo1∂outh1=−(targeto1−outputo1)∗outo1(1−outo1)∗ω5
观察1,2两个式子,我们可以发现,等号右边的左边两项,其实就是δo1,所以上式可以化简为:
∂Eo1∂outh1=δo1∗ω5
同理可得另一项:
∂Eo2∂outh1=δo2∗ω7
然后加起来便得到第一项:
∂Etotal∂outh1=δo1∗ω5+δo2∗ω7 - ∂outh1∂neth1(即对sigmoid函数求导):
outh1=11+e−neth1
∂outh1∂neth1=outh1(1−outh1) - ∂neth1∂ω1:
neth1=ω1∗i1+ω2∗i2+b1
∂neth1∂ω1=i1
- 然后乘起来即可:
∂Etotal∂ω1=(δo1∗ω5+δo2∗ω7)∗outh1(1−outh1)∗i1 - 那么δh1即为神经元h1的误差,即:
δh1=∂Etotal∂outh1∗∂outh1∂neth1=∂Etotal∂neth1
δh1=(δo1∗ω5+δo2∗ω7)∗outh1(1−outh1)
所以,整体误差E(total)对w1的偏导为:
∂Etotal∂ω1=δh1∗i1
最后,w5得到更新:
ω1→ω1−η∗∂Etotal∂ω1
结论公式
首先我们重新规定一下命名,z表示带权输入,a表示输出激活值,即为经过激活函数的带权输入,C表示代价函数,L表示神经网络的层数。
现在我们以sigmoid激活函数为例,用四个公式总结一下反向传播算法:
输出层误差的方程
L层第j个神经元的误差:
δLj=∂C∂aLj∗σ′(zLj)
用微分算子表示的矩阵形式为:
δL=∇aC⊙σ′(zL)
使用下一层的误差表示当前层的误差
下一层的误差呈上下一层的权重值,再点乘上当前层的输出,即为当前层的误差:
δl=(δl+1(ωl+1)T)⊙σ′(zl)
偏置b在代价函数C中的改变率
仔细观察上述计算过程可以发现,偏置b是带权输入z中的一项,而且偏置b的系数为1,所以我们可以得出,代价函数C对某神经元的偏置b的偏导即为该神经元的误差:
∂C∂b=δ
权重ω在代价函数C中的改变率
根据带权输入的表达式(ain为输入该神经元的激活值):
z=ω∗ain+b
可知,代价函数
C对
ω的偏导是在误差的基础上乘上了输入激活值:
∂C∂ω=ain∗δout
总结
四个公式:
δL=∇aC⊙σ′(zL)
δl=(δl+1(ωl+1)T)⊙σ′(zl)
∂C∂b=δ
∂C∂ω=ain∗δout