手撕BackPropagation (BP_Neural_Network)

深度学习基础;反向传播;

手撕一下推导过程。

0x00 BP神经网络结构

  • 输入层,隐藏层(神经元)*,输出层。
  • 一种简单的示例结构:image-20201121211828223
  • 其实理解神经网络的计算过程,计算图是最合适的。参考[2]img

0x01 梯度&链式法则

梯度

  • 神经网络常常采用随机梯度下降的方法,来使得损失降低,参数逼近最优解。

  • 所以,梯度是什么?

    • 损失函数对参数的导数

  • 参数的梯度乘以学习率就是该参数所需要更新(+/-)的值。

  • image-20201121205535658

链式法则

  • 微积分的重要定理,示例如下
  • image-20201121205727689

0x02 整体流程

  1. 正向传播,根据input计算出output,与此同时呢,会计算和记录当前的中间变量,以便反向传播时不必重复计算。

  2. 根据损失函数计算误差,记为 C (cost)。

  3. 反向传播,反向计算并记录,以便更新每一层的权重,

其中,lr是自定义的学习率。所以问题就是求参数对损失函数的微分,这一步就需要使用求微分的链式法则。

如图一所示,我们要求w1对C的偏导,就需要根据路径,根据计算图,链式的去求解。

但其实这更容易被理解成正向传播,所以我个人喜欢这么表示(具体原因下一部分会讲):

  • 现代神经网络一般分为两步,求梯度,梯度更新。(参考[3])
  • 以pytorch举例
    1. loss.backward() 反向传播
      1. backward()会根据tensor的requires_grad属性(true\false)计算梯度。
      2. 其他需要的数据在forward时已经存储。
    2. optimizer.step() 优化器更新参数。
  • 以下部分将进行详细说明

正向传播

首先,我们需要知道,直接正向传播来求,可不可以

  1. 在某种意义上是可以的,只要运算完成,根据存储的大量中间量以及最终结果,运用链式法则肯定是可以算的,那为什么还需要反向传播呢。
  2. 首先来看正向传播怎么算,这里把网络加一层image-20201121212847456
  3. 下边两个图都展示了,正向传播直接计算的话,中间变量重复性极大,每次都要计算的这些重复算式的话,计算量冗余太大,这就是正向传播,类似于正向搜索的弊端。
  4. image-20201120110645932

image-20201120110600124

反向传播

  • 因为正向传播的缺点,所以要介绍反向传播的解决方式

  • image-20201122203532108

  • 反向传播,从根传点往回传,每个结点内求和后继续传,直到叶结点停止,叶结点的值内求和即为梯度。

  • 单个纯手推

    • image-20201121215151960
  • 那么另外,为什么需要正向传播记录的中间变量,也就是一些中间输出值呢。

    • 图-6.2中李宏毅老师表示的比较清楚,计算梯度需要两部分,${\frac{∂C{}}{∂w{}}}={\frac{∂z{}}{∂w{}}}*{\frac{∂C{}}{∂z{}}}$;其中第一部分${\frac{∂z{}}{∂w{}}}$是需要正向传播过程中计算并且记录的,推导一下的话也就是一些中间输出;第二部分${\frac{∂C{}}{∂z{}}}$才是反向传播中计算的。
  • 通用推导

损失函数

训练的目的呢,就是要减小我们的训练误差,而误差呢,一般都是由自己定义或选择的一种函数,用来表示预测值与真实值之间的差距。

基于向量的反向传播

基于标量的推到可能还算简单,但是真正运用到实际的向量运算中可能就有麻烦了。这里我们以CS231n的课后作业举例,其比较具有代表性。

参考资料

  1. 如何直观地解释 backpropagation 算法? - YE Y的回答 - 知乎

  2. 如何直观形象的理解方向导数与梯度以及它们之间的关系?

  3. ∂x Δx dx?: 知乎

  4. 台大李宏毅!1. 李宏毅主页 2. Youtube

    image-20201119215307101

    image-20201119213433039 image-20201119211342321