三十分钟理解计算图上的微积分:Backpropagation,反向微分

神经网络的训练算法,目前基本上是以Backpropagation (BP) 反向传播为主(加上一些变化),NN的训练是在1986年被提出,但实际上,BP 已经在不一样领域中被重复发明了数十次了(参见 Griewank (2010)[1])。更加通常性且与应用场景独立的名称叫作:反向微分 (reverse-mode differentiation)。本文是看了资料[2]中的介绍,写的蛮好,本身记录一下,方便理解。算法

从本质上看,BP 是一种快速求导的技术,能够做为一种不仅仅用在深度学习中而且能够胜任大量数值计算场景的基本的工具。markdown

计算图

必须先来说一讲计算图的概念,计算图出如今Bengio 09年的《Learning Deep Architectures for AI》,
Bengio使用了有向图结构来描述神经网络的计算:网络

这里写图片描述

整张图可当作三部分:输入结点、输出结点、从输入到输出的计算函数。上图很容易理解,就是output=sin(a*x+b) * x框架

计算图上的导数

有向无环图在计算机科学领域处处可见,特别是在函数式程序中。他们与依赖图(dependency graph)或者调用图(call graph)紧密相关。一样他们也是大部分很是流行的深度学习框架背后的核心抽象。函数

下文如下面简单的例子来描述:工具

这里写图片描述

假设 a = 2, b = 1,最终表达式的值就是 6。
为了计算在这幅图中的偏导数,咱们须要 和式法则(sum rule )和 乘式法则(product rule):学习

这里写图片描述

下面,在图中每条边上都有对应的导数了:
这里写图片描述优化

那若是咱们想知道哪些没有直接相连的节点之间的影响关系呢?假设就看看 e 如何被 a 影响的。若是咱们以 1 的速度改变 a,那么 c 也是以 1 的速度在改变,致使 e 发生了 2 的速度在改变。所以 e 是以 1 * 2 的关于 a 变化的速度在变化。
而通常的规则就是对一个点到另外一个点的全部的可能的路径进行求和,每条路径对应于该路径中的全部边的导数之积。所以,为了得到 e 关于 b 的导数,就采用路径求和:图片

这里写图片描述

这个值就表明着 b 改变的速度经过 c 和 d 影响到 e 的速度。聪明的你应该能够想到,事情没有那么简单吧?是的,上面例子比较简单,在稍微复杂例子中,路径求和法很容易产生路径爆炸:get

这里写图片描述

在上面的图中,从 X 到 Y 有三条路径,从 Y 到 Z 也有三条。若是咱们但愿计算 dZ/dX,那么就要对 3 * 3 = 9 条路径进行求和了:

这里写图片描述

该图有 9 条路径,可是在图更加复杂的时候,路径数量会指数级地增加。相比于粗暴地对全部的路径进行求和,更好的方式是进行因式分解:

这里写图片描述

有了这个因式分解,就出现了高效计算导数的可能——经过在每一个节点上反向合并路径而非显式地对全部的路径求和来大幅提高计算的速度。实际上,两个算法对每条边的访问都只有一次!

前向微分和反向微分

前向微分从图的输入开始,一步一步到达终点。在每一个节点处,对输入的路径进行求和。每一个这样的路径都表示输入影响该节点的一个部分。经过将这些影响加起来,咱们就获得了输入影响该节点的所有,也就是关于输入的导数。

这里写图片描述

相对的,反向微分是从图的输出开始,反向一步一步抵达最开始输入处。在每一个节点处,会合了全部源于该节点的路径。

这里写图片描述

前向微分 跟踪了输入如何改变每一个节点的状况。反向微分 则跟踪了每一个节点如何影响输出的状况。也就是说,前向微分应用操做 d/dX 到每一个节点,而反向微分应用操做 dZ/d 到每一个节点。

让咱们从新看看刚开始的例子:
这里写图片描述

咱们能够从 b 往上使用前向微分。这样得到了每一个节点关于 b 的导数。(写在边上的导数咱们已经提早算高了,这些相对比较容易,只和一条边的输入输出关系有关)

这里写图片描述

咱们已经计算获得了 de/db,输出关于一个输入 b 的导数。可是若是咱们从 e 往回计算反向微分呢?这会获得 e 关于每一个节点的导数:

这里写图片描述

反向微分给出了 e 关于每一个节点的导数,这里的确是每个节点。咱们获得了 de/da 和 de/db,e 关于输入 a 和 b 的导数。(固然中间节点都是包括的),前向微分给了咱们输出关于某一个输入的导数,而反向微分则给出了全部的导数。

想象一个拥有百万个输入和一个输出的函数。前向微分须要百万次遍历计算图才能获得最终的导数,而反向微分仅仅须要遍历一次就能获得全部的导数!速度极快!

训练神经网络时,咱们将衡量神经网络表现的代价函数看作是神经网络参数的函数。咱们但愿计算出代价函数关于全部参数的偏导数,从而进行梯度降低(gradient descent)。如今,经常会遇到百万甚至千万级的参数的神经网络。因此,反向微分,也就是 BP,在神经网络中发挥了关键做用!因此,其实BP的本质就是链式法则。

(有使用前向微分更加合理的场景么?固然!由于反向微分获得一个输出关于全部输入的导数,前向微分获得了全部输出关于一个输入的导数。若是遇到了一个有多个输出的函数,前向微分确定更加快速)

BP 也是一种理解导数在模型中如何流动的工具。在推断为什么某些模型优化很是困难的过程当中,BP 也是特别重要的。典型的例子就是在 Recurrent Neural Network 中理解 vanishing gradient 的缘由。


有的时候,越是有效的算法,原理每每越是简单。


参考资料

[1] Who Invented the Reverse Mode of Differentiation?
[2] http://www.jianshu.com/p/0e9eea729476

相关文章
相关标签/搜索