目录
老饼讲解:一步一步上手学习

【优化】一篇入门之-动量梯度下降

作者 : 老饼 发表日期 : 2025-12-16 23:58:30 更新日期 : 2026-05-10 22:39:53
老饼讲解-简单易懂,干货满满,爽过嗦螺!


动量梯度下降算法(gradient descent with momentum,GDM)也是机器学习优化算法中的扛把子,它算法思路清晰、简单,优化速度快,还能跳出局部最优,性价比可以说是远远优于梯度下降算法,所以梯度下降算法效果不佳时,不妨换动量梯度下降算法试一试。

一、动量梯度下降法

这里我们先来简单直接的了解一下动量梯度下降法到底想干什么,下节再来说它的具体流程。

1.1. 动量梯度下降法是什么

动量梯度下降法是一种加入动量项的梯度下降法,它是对梯度下降法的一种改进,主要是解决梯度下降法毫无办法跳出局部最优的缺点,我们先来看下梯度下降法的缺点:

 梯度下降法的缺点

如图所示,梯度下降算法是一种完全没有跳出局部最优的算法,即使一个小坑,也一定会坑住梯度下降算法,这就非常吃亏,所以,这时候就有了动量梯度下降算法。

动量下降算法的思想就是模仿石头下山的原理,石头从高处滚下来,会带有动量,然后遇到一些小坑,也会因为惯性的原因,会跳出小坑,继续下滚,好了,先来看一看动量梯度下降算法的效果:

动量梯度法

如图,动量梯度下降算法借鉴了物体从高处滚到低处的原理,由于物体下坡时具有动量,遇到小坑时会因为自身动量的推动,就会跃出小坑。

1.2. 动量梯度下降法-迭代公式

那么,动量梯度下降法(GDM)是怎么达到这种效果的呢,我们直接来看它的迭代公式就明白了。

动量梯度下降的迭代公式如下:


 其中,:动量系数,一般设为0.9 
 
 :梯度           

看到公式我们不用慌,稍微解说一下它,就很容易明白它的意思了。

首先,GDM引入了速度这样的概念,我们看第二个公式:

它的意思就是用速度来更新,结合GDM的背景我们就容易理解了,下一刻的位置,就等于当前位置加上速度嘛。

好了,那么速度是多少呢?我们再看第一个公式,它就是用来更新速度的公式了:

仔细看一下就会发现,它其实就是与负梯度的加权和,所以负梯度实际就充当了加速度的角色了。

所以,总的来说,动量梯度法就是引入了速度,而负梯度呢,则充当了加速度,用来更新速度,然后再用速度来更新x,就是这么简单。

二、动量梯度下降法-算法流程

好了,我们来完整的看一下动量梯度下降法的算法流程吧!

2.1. 动量梯度下降法-算法流程图

先来上个算法流程图:

动量梯度下降法-算法流程图

好了,下面我们再用文字来描述一下更具体的算法流程。

2.2. 动量梯度下降法-算法流程

动量梯度下降法的具体算法流程如下:

一、设置参数与初始化相关变量

      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,理解这点就非常容易理解它了。



图标 评论
添加评论