老饼讲解:一步一步上手学习
动量梯度下降算法(gradient descent with momentum,GDM)也是机器学习优化算法中的扛把子,它算法思路清晰、简单,优化速度快,还能跳出局部最优,性价比可以说是远远优于梯度下降算法,所以梯度下降算法效果不佳时,不妨换动量梯度下降算法试一试。
这里我们先来简单直接的了解一下动量梯度下降法到底想干什么,下节再来说它的具体流程。
动量梯度下降法是一种加入动量项的梯度下降法,它是对梯度下降法的一种改进,主要是解决梯度下降法毫无办法跳出局部最优的缺点,我们先来看下梯度下降法的缺点:

如图所示,梯度下降算法是一种完全没有跳出局部最优的算法,即使一个小坑,也一定会坑住梯度下降算法,这就非常吃亏,所以,这时候就有了动量梯度下降算法。
动量下降算法的思想就是模仿石头下山的原理,石头从高处滚下来,会带有动量,然后遇到一些小坑,也会因为惯性的原因,会跳出小坑,继续下滚,好了,先来看一看动量梯度下降算法的效果:

如图,动量梯度下降算法借鉴了物体从高处滚到低处的原理,由于物体下坡时具有动量,遇到小坑时会因为自身动量的推动,就会跃出小坑。
那么,动量梯度下降法(GDM)是怎么达到这种效果的呢,我们直接来看它的迭代公式就明白了。
动量梯度下降的迭代公式如下:
其中,:动量系数,一般设为0.9
:梯度
看到公式我们不用慌,稍微解说一下它,就很容易明白它的意思了。
首先,GDM引入了速度这样的概念,我们看第二个公式:
它的意思就是用速度来更新,结合GDM的背景我们就容易理解了,下一刻的位置,就等于当前位置加上速度嘛。
好了,那么速度是多少呢?我们再看第一个公式,它就是用来更新速度的公式了:
仔细看一下就会发现,它其实就是与负梯度的加权和,所以负梯度实际就充当了加速度的角色了。
所以,总的来说,动量梯度法就是引入了速度,而负梯度呢,则充当了加速度,用来更新速度,然后再用速度来更新x,就是这么简单。
好了,我们来完整的看一下动量梯度下降法的算法流程吧!
先来上个算法流程图:

好了,下面我们再用文字来描述一下更具体的算法流程。
动量梯度下降法的具体算法流程如下:
一、设置参数与初始化相关变量
1. 设置学习率lr:
lr一般设为0.1
2. 设置动量系数mc
mc一般设为0.9
3. 初始化速度v
v一般初始化为0
4. 初始化初始解x
x随机初始化,或者具体问题具体设定
二、循环迭代
按如下步骤进行迭代
1. 计算当前的梯度g
2. 计算当前的梯度对v带来的修改量dv
3. 计算当前的速度
4. 更新x
5. 检查迭代终止条件
如果满足终止条件,就退出迭代程序
终止条件可设如下:
(1)是否达到最大迭代次数
(2)目标函数值是否满足要求
(3) x是否多次变化极小
三、输出结果
输出最终的求解结果x
现求解 的极小值,它的函数图像如下:

其中,目标函数的梯度公式为
按以上算法流程,编写程序如下:
"""
本代码用于展示动量梯度下降法求y= (x1-2)^2+(x2-3)^2的最小解
本代码来自《老饼讲解-机器学习》 www.bbblearn.com
"""
import numpy as np
import matplotlib.pyplot as plt
line_x = np.arange(-5,5.01,0.1) # 目标函数曲线x
line_y = 0.4*line_x**2+3*np.exp(-(line_x+2)**2); # 目标函数曲线y
lr = 0.1; # 学习率
mc = 0.9; # 动量系数
x = -4; # x的初始值
v = 0; # 初始速度
plt.rcParams['figure.figsize'] = (6, 3) # 设置画布的大小
for i in range(100) : # 逐轮迭代
gx = -(0.8*x-6*np.exp(-(x+2)**2)*(x+2)); # 计算负梯度
v = mc*v+(1-mc)*lr*gx; # 将负梯度叠加到上一次速度中,作为本次的速度
x = x+v; # 更新x
y = 0.4*x**2+3*np.exp(-(x+2)**2); # 计算当前的目标函数值
print('第%d轮x的迭代值x=%f'%(i,x)) # 打印当前结果
# ----绘图----
plt.clf() # 清空画布
plt.plot(line_x,line_y) # 画出目标函数曲线
plt.scatter(x,y,marker='o',s=60) # 画出当前迭代点
plt.draw() # 画图
plt.pause(0.01) # 暂停一下下运行结果如下:


经过100步迭代,求得最后y在x=0.053971处取得极小值。
好了,以上就是动量梯度法的原理和代码示例了,它其实就是借鉴了石头下坡的原理,使得优化过程能跳出局部最优,比起梯度下降法,它求解也更加的快,因为它在顺风时会越滚越快。它实现起来也相对简单,就是用梯度来作为加速度,然后用速度来更新x,理解这点就非常容易理解它了。
评论