反向传播算法的基本原理
反向传播算法(Backpropagation)是神经网络训练的核心算法。它通过计算损失函数相对于网络权重的梯度,来更新权重以最小化预测误差。反向传播算法的基本思想是利用链式法则,从输出层开始向输入层逐层计算梯度。
数学推导
若已经建立了一个神经网络,其具有输入层、隐藏层、与输出层。在输入 x 进行完成一轮前馈算法后产生了输出 y^ (由于有其他上标,本节向量使用粗体标注),我们训练集中预期的输出为 y,那么我们获得的差值为 y−y^。
神经网络始终希望我们获得的输出与预期的输出一致,那么我们希望 y−y^ 总是最小的,若 y−y^ 较大,我们需要调整神经网络中任意 l 层中第 i 个节点的权重 wl,j 以及阈值 θl,j,以让 y−y^ 回归于 0。
损失函数
我们将模型的预测值与训练集中的标签值的差异用以衡量损失,有很多种方法衡量这种损失,不同的方法产生了不同的损失函数 Loss,最常用的是均方误差和类似均方误差来衡量损失。一般说来均方误差为:
Loss=MSE=n1i=0∑n(yi−y^i)2
梯度计算
为了直观调整 Loss,我们可以构建 Loss 关于权重 wl,j 以及阈值 θl,j 的函数。所有的权重为 Wl,j(l)=wl,j,所有的阈值为 Θl,j(l)=θl,j。
Loss=loss(W,Θ,x)withy=constant
每一次前馈传播完成,Loss 对应的 y 就确定下来了,而 y^ 由 W、Θ 与 x 决定。我们调整的目标对象为权重 wl,j 以及阈值 θl,j,因此我们需要得出权重与阈值的变化对于 Loss 的影响,即:
∂wl,j∂lossand∂θl,j∂loss
神经元计算
由于我们要计算每一个层 l 和它所属的每一个神经元 j(l) 的权重 wl,j 和阈值 θl,j,因此要考虑每一个神经元的输入与输出。对于神经元 j(l),其接收上一层的值,加权计算后并减去阈值后,得出结果 Zl,j(l),我们将这个值称为为它的输入。经过激活函数后得到输出 Al,j(l),即:
Zl,j(l)=wl,j(l)T×Al−1,j(l−1)−θl,j(l)
Al,j(l)=Active(Zl,j(l))
链式求导
根据上述的前馈传播法则与复合函数的求导法则,我们可以计算损失函数 loss(W,Θ,x) 关于每一个神经元的权重 wl,j(l) 和阈值 θl,j(l) 的偏导数:
∂wl,j(l)∂loss=∂Al,j(l)∂loss⋅∂Zl,j(l)∂Al,j(l)⋅∂wl,j(l)∂Zl,j(l)
∂θl,j(l)∂Loss=∂Al,j(l)∂Loss⋅∂Zl,j(l)∂Al,j(l)⋅∂θl,j∂Zl,j(l)
输出层计算
回到我们的网络之中,一个重要的问题是,最后一层的输出是什么?这里我们使用 l=end 表述,显然:
Aend,j(end)=y^j(end)
当我们再次回顾 MSE 函数、Zl,j(l)=wl,j(l)T×Al−1,j(l−1)−θl,j(l) 以及 Al,j(l)=Active(Zl,j(l)) 三个式子,我们从输出层开始,计算:
∂Aend,j(end)∂loss∂Zend,j(end)∂Aend,j(end)∂wend,j(end)∂Zend,j(end)∂Aend,j(end)∂Loss∂Zend,j(end)∂Aend,j(end)∂θend,j∂Zend,j(end)
隐藏层计算
我们成功获取到了输出层中每一个神经元的 loss(W,Θ,x) 关于其自身权重 wl,j(l) 与阈值 θl,j(l) 的偏导数。在偏导数的计算中,我们只剩下最后的问题了,隐藏层中的 ∂Al,j(l)∂loss 是如何计算的。我们只知道 ∂y^j(end)∂loss,同样借助复合函数的求导法则:
∂Al,j(l)∂loss=∂y^j(end)∂loss⋅∂Al,j(l)∂y^j(end)
直观上,取 l=end−1,则:
y^j(end)=Aend,j(end)=Active(wend,j(end)T×Aend−1,j(end−1)−θend,j(end))
若 l=end−1,我们可以一直进行链式求导:
∂Al,j(l)∂loss=∂y^j(end)∂loss⋅∂Aend−1,j(end−1)∂y^j(end)⋅∂Aend−2,j(end−2)∂Aend−1,j(end−1)…∂Al,j(l)∂Al+1,j(l+1)
递推公式
这样,我们从输入层开始如核裂变一样不断地传递下去,使用递推表述为:
∂Al,j(l)∂loss=∂Al+1,j(l+1)∂loss⋅∂Al,j(l)∂Al+1,j(l+1)
再次展开计算:
∂Al,j(l)∂Al+1,j(l+1)=∂Zl,j(l)∂Al+1,j(l+1)⋅∂Al,j(l)∂Zl,j(l)=wl,j(l)
最终公式
最后,把他们拼装起来:
∂wl,j(l)∂loss=MSE′(y^)⋅end−1∏lwl,j(l)⋅Active′(Zl,j(l))⋅Al−1,j(l−1)
∂θl,j(l)∂Loss=MSE′(y^)⋅end−1∏lwl,j(l)⋅Active′(Zl,j(l))⋅(−1)
Active′(Zl,j(l)) 都是简单的函数,可以很轻易得到。MSE′(y^) 显然易得,那么我们完全计算出了损失函数对于每一个神经元地权重与阈值的偏导数。这意味着,我们获取了神经网络中 wl,j(l) 与 θl,j(l) 的变动对 Loss 的影响。
梯度下降更新
回到神经网络训练的目标,我们是为了最小化 Loss,那么调整 Loss 与 θl,j(l) 使得 Loss 值减小由于偏导的可得性变得可行。
∇loss=(∂wl,j(l)∂loss,∂θl,j(l)∂Loss)
当我们计算出 ∇loss 后,将 wl,j(l) 与 θl,j(l) 值向其梯度负方向调整 η 倍,那么将导致 loss 下降,同样使得 ∇loss 趋近于 0。这就是梯度下降的过程,也是计算每一层的每一个节点偏导的意义。
学习率
我们只剩下最后的一个问题了,η 的取值。η 就是梯度下降向最低点移动的程度,也被称为”学习率”,因为梯度是通过网络计算学习到的,因此学习多少这个获取的梯度值就是学习率本身的含义。学习率过大会导致模型调整错过最低点,过小导致收敛缓慢。常见的学习率可以手动调整,也有使用退火算法进行。
权重更新公式
最后给出我们的最终目标式子:
wl,j(l)=wl,j(l)(1−η∂wl,j(l)∂loss)
θl,j(l)=θl,j(l)(1−η∂θl,j(l)∂loss)