随机梯度降低法(SGD)是训练深度学习模型最经常使用的优化方法。在前期文章中咱们讲了梯度是如何计算的,主要采用BP算法,或者说利用链式法则。可是深度学习模型是复杂多样的,你不大可能每次都要本身使用链式法则去计算梯度,而后采用硬编程的方式实现。算法
而目前的深度学习框架其都是实现了自动求梯度的功能,你只关注模型架构的设计,而没必要关注模型背后的梯度是如何计算的。不过,咱们仍是想说一说自动求导是如何实现的。编程
这里咱们会讲几种常见的方法,包括数值微分(Numerical Differentiation),符号微分(Symbolic Differentiation),前向模式(Forward Mode)和反向模式(Reverse Mode)网络
数值微分架构
数值微分方式应该是最直接并且简单的一种自动求导方式。从导数的定义中,咱们能够直观看到:框架
当h接近0时,导数是能够近似计算出来的。能够看到上面的计算式几乎适用全部状况,除非该点不可导。但是数值微分却有两个问题,第一个就是求出的导数可能不许确,这毕竟是近似表示,好比要求f(x)=x^2在零点附近的导数,若是h选取不当,你可能会获得符号相反的结果,此时偏差就比较大了。第二个问题是对于参数比较多时,对深度学习模型来讲,上面的计算是不够高效的,由于每计算一个参数的导数,你都须要从新计算f(x+h)。可是数值运算有一个特殊的用武之地就是在于能够作梯度检查(Gradient check),你能够用这种不高效但简单的方法去检查其余方法获得的梯度是否正确。函数
符号模式学习
符号微分适合符号表达式的自动求导,符号微分技术普遍应用在数学软件如Matlab、Maple及Mathematica等。符号微分的原理是基于下面的简单求导规则:优化
当咱们将符号表达式用表达式树表示时,能够利用加法规则和乘法规则进行自动求导。好比咱们要求符号表达式f(x)=2x+x^2,能够展开成以下图的表达式树:spa
利用求导规则,能够求出:设计
基于表达式树和求导规则,咱们能够获得最终的导数。有一点要注意的是,符号微分不必定会获得简化的导数,由于计算机可能并不能进行智能的简化。因此,若是表达式树结构较复杂时,获得的导数表达式会至关复杂,也许出现表达式爆炸现象。
前向模式
前向模式最简单明了,其基于的是二元数(dual numbers)。咱们先来说解一下二元数,其基本格式以下所示:
其中a和b都是实数,而
是无穷小量,你能够认为其无限接近0,可是并不等于0,而且
,这是借鉴了微积分中的概念。因此,你能够认为
是一个接近5的数。对于二元数,其知足简单的加法和乘法规则:
对于二元数,其更重要的一个特性是:
这意味着,咱们只须要计算出
,就能够获得
以及其对应的导数
。因此,一个前向计算过程能够同时获得函数值与其导数,这就是前向模式的原理。举例来讲,若是要计算f(x)=2x+x^2在x=2处的函数值与导数,其计算过程以下所示:
反向模式
最后要说的就是反向模式,反向模式就是咱们常说的BP算法,其基于的原理是链式法则。咱们仅须要一个前向过程和反向过程就能够计算全部参数的导数或者梯度,这对于拥有大量训练参数的神经网络模型梯度的计算特别适合,因此经常使用的深度学习框架如Tensorflow其自动求导就是基于反向模式。方向模式具体的实现细节能够参考以前的文章。
参考资料
1. Automatic Differentiation in Machine Learning: a Survey, https://arxiv.org/pdf/1502.05767.pdf
2. Hands-On Machine Learning with Scikit-Learn and TensorFlow, Aurélien Géron, 2017.