十分钟看懂神经网络反向传输算法

昨天面试被问到如何推导BP(反向传输)算法,顿时蒙住了,大致是知道反向传输算法的过程的,可是用语言描述出来,确实有些困难。回来后看了些博文,发现有的博文中公式推导过于复杂,不易理解,遂综合了网络中其余博文和斯坦福大学CS231n课程中的内容,整理了一份反向传输算法的通俗解释,若有错误,请各位网友指出。html

1、反向传输(BP)算法的做用是什么?

首先咱们要知道咱们的优化目标是什么,对于神经网络模型的优化实质上就是对总体损失函数 L(成本函数) 的优化面试

其中 L为样本集中第 i 个样本的损失值,(xi,yi)为第i个样本。算法

损失函数 L 的自变量是网络中全部的参数,训练的目的是找到一组参数,使得损失函数 L 达到最小值(或者局部最小值)。一般使用梯度降低算法进行优化参数,对于具体的优化算法,这里再也不叙述,具体能够参看深度学习——优化器算法Optimizer详解BGDSGDMBGDMomentumNAGAdagradAdadeltaRMSpropAdam一文。这些算法都是阐述了如何更好的使用梯度信息来快速优化成本函数、找到最有解,但这些算法的前提都是得到了成本函数的梯度值,对于深度网络可能有上亿的参数须要优化,如何高效的求解出 L 对这上亿参数的偏导数,便成为一个难题,反向传输(BP)算法即用来高效的计算这些参数的偏导数,进而得出成本函数(损失函数L)的梯度。网络

补充:

对于欲优化的代价函数,为权重的函数C=C(W),是一个很是复杂的复合函数,直接使用链式法则对各参数求偏导很是复杂。若是使用导数定义进行树数值求导,一个很明显的计算方式是使用近似:机器学习

其中是一个大于零的小正数。换句话说,咱们能够经过计算两个差距很小的wj的代价,而后利用上式来估计。这个方法看起来很不错,使用的是导数的定义求法,可是计算过于复杂,设想咱们的神经网络中有100万个待优化的参数,计算一次梯度就要重复计算100万次。进而对于每个样本,都要在神经网络中向前传播100万次。并且还须要计算C(W),至关于要一百万零一次前向传播。函数

反向传播的优势在于他尽力用一次前向传播加一次反向传播就能够同时计算出全部的偏导数,大体来说,反向传播所须要的总计算量与前向传播的计算量基本相等,缘由在于前向传播时主要的计算量在于权重矩阵的乘法计算,反向传播时主要的计算量在于权重矩阵转置的乘法,很明显,它们的计算量差很少。利用反向传播算法求成本函数的梯度,大大减少了计算量,使神经网络优化更快!学习

举个例子:优化

2、反向传输算法过程

1.链式求导

首先咱们回顾一下微积分中对于复合函数的求导过程,对于任意复合函数,例如:spa

这就是咱们常说的链式求导法则。反向传输算法正是利用了这种链式求导法则。3d

2.用计算图来解释几种求导方法

2.1 计算图

式子 e=(a+b)*(b+1) 能够用以下计算图表达:

 

令a=2,b=1则有:

如何在计算图上表达“求导”呢? 导数的含义是因变量随自变量的变化率,例如 \frac{\partial y }{\partial x} = 3  表示当x变化1个单位,y会变化3个单位。 微积分中已经学过:加法求导法则是 \frac{\partial}{\partial a}(a+b) = \frac{\partial a}{\partial a} + \frac{\partial b}{\partial a} = 1 乘法求导法则是 \frac{\partial}{\partial u}uv = u\frac{\partial v}{\partial u} + v\frac{\partial u}{\partial u} = v 。 咱们在计算图的边上表示导数或偏导数:\frac{ \partial e }{ \partial c } , \frac{ \partial e }{ \partial d }, \frac{ \partial c }{ \partial a }, \frac{ \partial c }{ \partial b }, \frac{ \partial d }{ \partial b } 以下图

那么 \frac{ \partial e  }{ \partial b } 如何求呢? \frac{\partial c }{ \partial b} = 1 告诉咱们1个单位的b变化会引发1个单位的c变换,\frac{\partial e }{ \partial c} = 2告诉咱们 1 个单位的c变化会引发2个单位的e变化。因此 \frac{ \partial e  }{ \partial b } =   \frac{ \partial c }{ \partial b } * \frac{ \partial e  }{ \partial c }   = 1*2 =2 吗? 答案必然是错误。由于这样作只考虑到了下图橙色的路径,全部的路径都要考虑:\frac{ \partial e  }{ \partial b } =   \frac{ \partial c }{ \partial b } * \frac{ \partial e  }{ \partial c }  +  \frac{ \partial d  }{ \partial b }  *  \frac{ \partial e  }{ \partial d }  =1*2 + 1 * 3 = 5

因此上面的求导方法总结为一句话就是: 路径上全部边相乘,全部路径相加。不过这里须要补充一条颇有用的合并策略:

例如:下面的计算图若要计算\frac{\partial Z}{\partial X}就会有9条路径:\frac{\partial Z}{\partial X} = \alpha\delta + \alpha\epsilon + \alpha\zeta + \beta\delta + \beta\epsilon + \beta\zeta + \gamma\delta + \gamma\epsilon + \gamma\zeta

若是计算图再复杂一些,层数再多一些,路径数量就会呈指数爆炸性增加。可是若是采用合并策略:\frac{\partial Z}{\partial X} = (\alpha + \beta + \gamma)(\delta + \epsilon + \zeta) 就不会出现这种问题。这种策略不是 对每一条路径都求和,而是 “合并同类路径”,“分阶段求解”。先求X对Y的总影响 (\alpha + \beta + \gamma) 再求Y对Z的总影响 (\delta + \epsilon + \zeta) 最后综合在一块儿。

2.2 两种求导模式:前向模式求导( forward-mode differentiation) 反向模式求导(reverse-mode differentiation)

上面提到的求导方法都是前向模式求导( forward-mode differentiation) :从前向后。先求X对Y的总影响 (\alpha + \beta + \gamma) 再乘以Y对Z的总影响 (\delta + \epsilon + \zeta) 。

另外一种,反向模式求导(reverse-mode differentiation) 则是从后向前。先求Y对Z的影响再乘以X对Y的影响。

前向求导模式追踪一个输入如何影响每个节点(对每个节点进行 \frac{\partial}{\partial X}操做)反向求导模式追踪每个节点如何影响一个输出(对每个节点进行 \frac{\partial Z}{\partial}操做)。通俗点理解,前向求导模式和反向求导模式只是求导顺序的不一样,可是顺序不一样运算复杂度也不相同。

2.3 反向求导模式(反向传播算法)的重要性

让咱们再次考虑前面的例子:

若是用前向求导模式:关于b向前求导一次

 

 

若是用反向求导模式:向后求导

前向求导模式只获得了关于输入b的偏导 \frac{\partial e}{\partial b} ,还须要再次求解关于输入a的偏导\frac{\partial e}{\partial a} (运算2遍)。而反向求导一次运算就获得了e对两个输入a,b的偏导\frac{\partial e}{\partial a}, \frac{\partial e}{\partial b} (运算1遍)。上面的比较只看到了2倍的加速。但若是有1亿个输入1个输出,意味着前向求导须要操做1亿遍才获得全部关于输入的偏导,而反向求导则只需一次运算,1亿倍的加速。

当咱们训练神经网络时,把“损失“ 看做 ”权重参数“ 的函数,须要计算”损失“关于每个”权重参数“的偏导数(而后用梯度降低法学习)。 神经网络的权重参数能够是百万甚至过亿级别。所以反向求导模式(反向传播算法)能够极大的加速学习。

用更通俗易懂的话来描述反向传输算法,从目标函数开始,逐层向前求解每一层每一个结点(运算)的局部梯度,根据链式法则可知,整个网络中成本函数对于某一个参数的偏导数,从成本函数流经本参数全部指路上的偏导数乘积叠加,这样一次运算就能够得到全部参数的偏导数,即成本函数的梯度。梯度从后向前逐层传递。

经过计算流图对该算法进行简要解释:


 

 附录:机器学习经常使用求导公式

 X是向量,W是与X无关的矩阵

后两个很重要!!!

相关文章
相关标签/搜索