NN的学习中需要计算权重和偏置参数的梯度,对于梯度的计算,很容易想到数值导数,即前向差分
d x = f ( x + h ) − f ( x ) h dx=\frac{f(x+h)-f(x)}{h} dx=hf(x+h)−f(x)
或者改进一点,用中心差分(更接近准确的导数值)
d x = f ( x + h ) − f ( x − h ) 2 h dx=\frac{f(x+h)-f(x-h)}{2h} dx=2hf(x+h)−f(x−h)
h取一个接近0的数值,如0.0001
但这样计算是比较慢的,尤其是大型网络,参数众多的情况,所以我们用一种更快的方法计算参数的梯度值——反向传播。
反向传播的精髓,本质,核心是链式法则chain rule
正是链式法则的应用简化了梯度计算,而且链式法则和反向传播都特别简单,非常好理解。
由于太简单,本文跳过原理叙述直接写代码,如果想仔细学习BP可以看斋藤康毅的《Deep Learning from Scratch》(很火的红色封面,有一条灰色的鱼,优快云下载链接,我下载看过,非常清晰)中第五章关于反向传播的讲解,极为透彻!!!用计算图作为示例,一点一点,推导加法器,乘法器,RELU,sigmoid,softmax,除法器,exp运算,log运算等,总之所有的NN中用到的运算模块的反向导数,还推导了softmax-with-cross_entropy_error层的反向导数求解,得到了极为漂亮的结果,也正是这个结果使得梯度的计算如此简单。
NN的每一层都实现为一个类,包括Affine层,Sigmoid层,Relu层,Softmax-with-Loss层(loss用cross-entropy-error),类中定义前向传播和反向传播的计算方法。
1. Relu层
y = { x , x > 0 0 , x ≤ 0 y=\left\{ \begin{aligned} x,x>0\\ 0,x\leq0\\ \end{aligned} \right. y={ x,x>00,x≤0
导数自然就是:
∂ y ∂ x = { 1 , x > 0 0 , x ≤ 0 \frac{\partial y}{\partial x}=\left\{ \begin{aligned} 1,x>0\\ 0,x\leq0\\ \end{aligned} \right. ∂x∂y=