回顾一下梯度下降的过程:

假设当前神经网络有以下参数\(\theta = \{\omega_1,\omega_2,…,b_1,b_2,…\}\),那么梯度下降就是计算损失函数对于每个参数的梯度,然后按照梯度更新公式来更新每一个参数。但在深度学习中参数量巨大,这样计算时间过长,因此反向传播就是来高效就计算出损失函数对于每个参数的梯度的。注意反向传播并不是一个和梯度下降不同的训练方法,它只是能够更有效率就计算出损失函数对参数的梯度,来帮助梯度下降过程。

反向传播

损失函数可以如下表示:

\[L(\theta)=\sum_{n=1}^N C^n(\theta)\]

其中\(C^n(\theta)\)表示第n个样本的输出值和理想值之间的距离。那么:

\[\frac{\partial L(\theta)}{\partial w}=\sum_{n=1}^N \frac{\partial C^n(\theta)}{\partial w}\]

也就是将总体损失对参数的微分转换成每一个样本的距离对参数的微分的求和

假设对于图上网络:

\[\frac{\partial C}{\partial w}=\frac{\partial z}{\partial w}\frac{\partial C}{\partial z}\]

其中:

  • \(\frac{\partial z}{\partial w}\):称为前向传播(Forward pass),较为容易计算
  • \(\frac{\partial C}{\partial z}\):称为反向前进(Backward pass),较难计算

Forward pass

从上图中我们可以很简单地算出

\[\frac{\partial z}{\partial w_1}=x_1\\\frac{\partial z}{\partial w_2} = x_2\]

也就是说对于每条边或者说每个参数,它所连接的下一层的输入对于该参数的求导就等于上一层在这条边上的输入,例如下图:

所以前向传播这一步可以很简单的计算出来。

Bcakward pass

现在需要来考虑如何计算\(\frac{\partial C}{\partial z}\),假设前述z经过一个Sigmoid函数后得到a,那么a作为下一层神经网的某一个输入,因此就可以写出:

\[\frac{\partial C}{\partial z}=\frac{\partial a}{\partial z}\frac{\partial C}{\partial a}\]

而从上图中也可以很清楚地看到**可以用微积分的知识转换成上述公式,而其中对a的求导也可以结合我们上述的知识很容易的求解。因此现在就是如何求解C对两个z的求导了。

但假设我们当前能够通过某种方法知道了C对两个z的求导,同时我们将网络进行些许转换,如下:

根据那个公式我们可将网络反向过来,这有助于待会理解反向传播。不过值得注意的是此处神经元结点对于输入加权和后是乘上\(\sigma`(z)\),在z确定的时候(当输入确定时z就确定了)可以看成常数,因此跟正向神经网络的非线性变化不同

继续计算C对两个z的求导:

情况一

假设\(z`\)\(z“\)经过非线性变换后已经就是输出了,那么这种简单的情况可以很简单的写出上面的计算式,也就很简单的完成了我们对于参数梯度的计算工作。其中

\[\frac{\partial C}{\partial y}取决于你的损失函数\\\frac{\partial y}{\partial z}取决于最后一层的非线性变换\]

情况二

假设\(z`\)\(z“\)后面仍然有很多未知的线性变化,但通过前述的讲解我们可以明确只要知道了下一层的C对各个z的求导,那么就一定可以算出当前层C对各个z的求导。因此只要不断地往后推,找到某一层的z经过非线性变换后就是输出,那么就可以计算C对该层的z的求导(情况一),然后再往前推直到C对每一层的z的求导都算出来

那么在实际上的做法就是:

  1. 建立一个反向的神经网络,其结构相同权重参数相同,但是功能神经元结点的非线性变换变成了常数,就是之前的\(\sigma`(z)\),这需要先计算Forwardpass之后才可以计算(其中还需要计算\(\frac{\partial z}{\partial w}\))
  2. 计算损失函数C对最后一层的每个z的求导,那么它们就是这个反向神经网络的输入参数
  3. 再根据网络的不断传播就可以计算出最终结果

这就是反向传播