深度学习 --- BP算法详解(BP算法的优化)

版权声明:转载请注明出处: https://blog.csdn.net/weixin_42398658/article/details/83958133

上一节我们详细分析了BP网络的权值调整空间的特点,深入分析了权值空间存在的两个问题即平坦区和局部最优值,也详细探讨了出现的原因,本节将根据上一节分析的原因进行改进BP算法,本节先对BP存在的缺点进行全面的总结,然后给出解决方法和思路,好,下面正式开始本节的内容:

BP算法可以完成非线性问题,因此具有很大的优势,但是也存在很大的问题,下面我们就来总结一下:

             (1)易形成局部极小值而得不到全局最优

             (2)训练次数多,使的学习效率降低,收敛速度慢

             (3)隐节点的选取缺乏理论指导

             (4) 训练时学习新样本有遗忘旧样本的趋势

针对上面的问题,现已有多种解决方法,下面就看看有哪些解决方法:

1.增加动量项

        标准的BP算法在调整权值时,只按t时刻误差的梯度方向调整,而没有考虑t时刻以前的梯度方向,从而容易使训练过程发生振荡,收敛缓慢,为了提高网络的训练速度,可以在权值的调整公式增加一动量项,若用W代表某层权矩阵,x代表某层输入向量,则包含动量项的权值调整向量表达式为:

                                \Delta w(t)=\eta\cdot err\cdot x + \alpha \cdot \Delta w(t-1)

从上式可以看出,增加动量项即从前一次权值调整中取出一部分叠加到本次权值调整量中,\alpha称为动量系数,一般0< \alpha < 1。动量项代表的物理意义是反映了以前积累的经验,对于t时刻起到阻尼作用(不懂阻尼请看维基解释),当权值曲面出现骤然下降时,该动量项可减少振荡趋势,提高训练过程,目前BP算法中都增加了动量项,以至于具有动量项的BP算法称为一种新的标准算法。简单来说其实就是利用物理的惯性原理,当参数更新时,需要保持之前的方向趋势,因此可以看做惯性。

2.自适应调节学习率\eta

学习率\eta也称步长,在标准BP算法中设定为常数,然而在实际中,很难使用一个确定的值为最佳的学习率,如果可以动态调整学习率就很好了,从权值曲面我们希望在平坦区内\eta是增大的,因为太小会使得训练次数增加,\eta增大会加速脱离平坦区。而在误差变化很大的区域,\eta太大会容易跨过较窄的最低点,这个最低点可能是全局最优点,同时会产生振荡,反而是迭代次数增加,因此为了加速收敛,一个较好的解决思路就是让学习率\eta根据具体情况进行动态调整,这里介绍一种实现方法:

在这里需要给大家说明的是,自适应调节学习率的研究是一个领域,最初是从退火算法到最优退火算法进行探索的,最优退火算法提供了在线学习,为在线学习迈开了重要的一步,但是退火方案的缺点是时间常量\eta_{switch}为先验的,考虑到实际问题,不同的样本先验会发生改变,因此在1998年Murata首次提出了在线学习算法需要装备内在机制用于学习率的自适应控制,对学习算法的学习进行了适当的修正,第一个修正就是统计特性发生变化的情况,第二个就是增加了在线学习算法的泛化能力。因此解决了退火算法的先验问题。但是它是在考虑学习率参数的退火范围内的次优的解为代价的,其重要的优点在于扩大了在线学习在实际执行方式的适用性。在这里就不细讲这些知识了,有兴趣的朋友可以参考《神经网络与机器学习》这本书并结合相关的论文进行理解,在这里就不细讲了,在后面的文章中会详细讨论退火算法,这里给大家提一下并给出研究的总体思路。下面就简单的讲一下学习率的动态调整过程:

             设一初始学习率,若经过一批次权值调整后使总误差E增大了,说明这次调整没有效果,原因是学习率可能过大,发生振荡了,因此需要减小学习率:\eta (t+1) = \beta \eta (t)(\beta < 1);若经过一批次权值调整后使总误差E减少了,说明调整是有效的,同时可以加快迭代速度即增加学习率:\eta (t+1) = \Theta \eta (t)(\Theta > 1),下面简单的介绍几种具体的调节学习速率的方法。

AdaGrad方法(Adaptive gradient 自适应梯度)

他为每个参数都设置了更新速率,先看表达式:

                               \Delta w_t = -\frac{\eta }{\sqrt{\sum_{k=1}^{t}g_k^2 + \varepsilon }}g_t

    其中g_t表示当前时刻的梯度,\eta是默认的学习速率,\varepsilon为常数。同过上式不难理解,在同一时刻对于不同的参数,权值更新是不同的,随着更新距离之和的增加,学习速率也越来越小,这也符合在模型训练初期的,希望参数变化更多更快,而在模型训练后期,希望参数变化的更慢且值更小。

Adadelta方法

Adadelta是对Adagrad的扩展,最初方案依然是对学习率进行自适应约束,但是进行了计算上的简化。 Adagrad会累加之前所有的梯度平方,由上面公式可以看出,仍依赖于人工设置一个全局学习率,η设置过大的话,会使regularizer过于敏感,对梯度的调节太大,中后期,分母上梯度平方的累加将会越来越大,使gradient→0,使得训练提前结束,因此为了解决后期梯度很小的弊端,提出了Adadelta方法,而Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。即:

                                    \Delta w_t = -\frac{\eta }{\sqrt{\lambda *\sum_{k=1}^{t-1}g_K^2+(1-\lambda )g_t^2 + \varepsilon }}*g_t

从上式来看,还是依赖全局的学习速率,后面人们就继续做了一定的处理,和近似牛顿迭代法后:

                                     E|g^2|_t = \lambda * E|g^2|_{t-1} + (1-\lambda )*g_t^2

这里是使用的均值进行处理的,进而可以得到:

                                       \Delta w_t = -\frac{\sqrt{\sum_{\varphi = 1}^{t-1}\Delta w_\varphi }}{\sqrt{E|g^2|_t+\varepsilon }}

上面就没有全局的学习速率了,这里不细讲原理了,以后会单独拿出来详细的讲。

RMSProp方法(梯度的均方根 root mean squared (RMS)

RMSprop可以算作Adadelta的一个特例:

\lambda=0.5时E|g^2|_t = \lambda * E|g^2|_{t-1} + (1-\lambda )*g_t^2就变为了求梯度平方和的平均数。 

如果再求根的话,就变成了RMS(均方根): 

                                           RMS|g|_t = \sqrt{E|g^2|_t+\varepsilon }

此时,这个RMS就可以作为学习率η的一个约束:

                                          \Delta w_t = -\frac{\eta }{RMS|g|_t}*g_t

其实RMSprop依然依赖于全局学习率,RMSprop算是Adagrad的一种发展,和Adadelta的变体,效果趋于二者之间,并且适合处理非平稳目标,尤其对于RNN效果很好

Adam(Adaptive Moment Estimation)

Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。公式如下:

                                                                                    \Delta w_t = -\frac{\hat{m_t}}{\sqrt{\hat{n_t}}+\varepsilon }*\eta

其中,m_t,n_t分别是对梯度的一阶矩估计和二阶矩估计,可以看作对期望E|g_t|,E|g_t^2|的估计;\hat{m_t},\hat{n_t}是对m_t,n_t的校正,这样可以近似为对期望的无偏估计。 
可以看出,直接对梯度的矩估计对内存没有额外的要求,而且可以根据梯度进行动态调整,而\Delta w_t = -\frac{\hat{m_t}}{\sqrt{\hat{n_t}}+\varepsilon }*\eta对学习率形成一个动态约束,而且有明确的范围。

梯度优化方面的就先到这里,后面进入深度学习时,还会好好详细的深入理解这几个,当然这只是其中的几个优化,还有很多,后面会单独讲。

3.引入抖度因子

从上节的分析中我们知道,导致平坦区有三种可能情况(不知道的请看这篇文章),后两种是因为激活函数的输入进入到了激活函数的饱和区,我们知道饱和区的,激活函数的表达式如下:

                                               o_k = \frac{1}{1+e^{net_k}}

加入抖度因子后的表达式为:

                                                o_k = \frac{1}{1+e^{net_k/\lambda }}

\lambda的取值会影响激活函数的饱和区间,请看图:

从上节我们知道当\Delta E接近0时而d_k - o_k仍比较大,此时就进入平坦区了,这时我们令\lambda > 1;当退出平坦区后,再令\lambda =1,从上图我们看到,随着\lambda不断增大,net_k坐标被压缩了 \lambda,,因此可以有效的增加饱和区的范围,这种方法实际中提高BP收敛的速度十分有效。蓝色是原始的激活函数。

4.从梯度方面进行优化

          我们知道,误差函数是根据梯度进行调节的,写出等式可为如下:

                                    E_{err} (w(n)+\Delta w(n)) = E_{err}(w(n)) + g^T(n)\Delta w(n)

其中g^T(n)就是梯度了,其实上式就是平均误差函数的泰勒公式展开,这样大家就能理解了,至于梯度为什么和泰勒公式有联系,请参考我的这篇文章(这篇文章主要是讲梯度问题,最原始的请参考张贤达的矩阵那本书),我们前面的梯度都是基于上式进行更新的,但是我们只知道当前的梯度,无法预测下面的梯度情况,那么如果我们可以知道下面的梯度的走势就可以针对走势进行调整梯度,使其尽快脱离平坦区,因此,现在是如何参看梯度的变化情况,其实很自然的能想到,对梯度求导就可以了,也就是对原始求二阶导,因此可以通过泰勒公式展开保留二阶导的式子,展开如下:

                          E_{err} (w(n)+\Delta w(n)) = E_{err}(w(n)) + g^T(n)\Delta w(n) + \frac{1}{2}\Delta w^T(n)H(n)\Delta w(n)

其中H(n )是海森矩阵了,什么是海森矩阵呢?其实就是矩阵的二阶求导,不懂的建议学一下张贤达的矩阵论。为了大家更明白,我把梯度和海森矩阵的表达式单独写出来:

    局部梯度向量g(n),定义为:

                                             g(n)=\frac{\partial E(w)}{\partial w}\mid _{w=w(n)}

    局部海森矩阵(Hessian)矩阵H(n),表示误差性能曲面的“曲率”,定义为:

                                              H(n) = \frac{\partial^2 E(w)}{\partial w^2}\mid _{w = w(n)}

   现在我们再好好审视我们前面使用的梯度下降,权值更新如下:

                                              \Delta w(n) = -\eta g(n)x

在学习率和输入向量不变的情况下,更新权值只依赖于误差曲面的局部信息为唯一来源的梯度向量 g(n),这样做有好处也有坏处,好处是实现简单、坏处是收敛速度慢。特别在数据量很大的情况下,收敛想当面,计算量很大,为了更好的收敛,我们在权值更新中加入使用误差曲面的二阶信息进行处理,因此从新定义权值的更新:

                                            \Delta w^*(n) = H^{-1}(n)g(n)       

其中H^{-1}(n)是Hessian矩阵 H(n)的逆,假设逆是存在的,其实上式就是牛顿法的核心表达了。上式的代价函数保留了二次项,虽然迭代一次就可以达到最优值,但是需要考虑几个问题:

(1) 牛顿法要求计算Hessian矩阵的逆,这个计算量是很大的

(2)为了使H^{-1}(n)是可计算的,H(n)必须是非奇异矩阵,但是多层感知器误差曲面的海森矩阵并不总是符合要求的,这使得计算量更加繁琐

(3) 代价函数是非二阶的时候,牛顿法收敛得不到保证。

为了解决上面的问题,我们可以使用拟牛顿法进行求解,拟牛顿法的的修正主要是不经过计算矩阵的逆得到逆矩阵H^{-1}(n)的正定估计,通过这样的估计,拟牛顿法保证误差曲面是下降的,但是计算量还是很大,因此拟牛顿法只适合小型规模的数据。

      为了继续解决上面的问题,另一个方法就是共轭梯度方法,他被认为是介于梯度下降和牛顿法之间的方法,使用共轭梯度方法的动机是期望加速梯度下降法中特别缓慢的收敛速度,同时避免牛顿法要求海森矩阵的估计、存储和求逆。

牛顿法和共轭梯度法,这里不再深入讲解了,有兴趣的可以自行学习,以后用到了,我在深入的讲解,本节到此结束,有疑问请留言。

猜你喜欢

转载自blog.csdn.net/weixin_42398658/article/details/83958133