【优化器】带动量 Momentum 的SGD算法
2026/4/14 16:30:48 网站建设 项目流程

思想:让参数更新具有惯性,每一步更新都是由前面梯度累积v vv和当前点梯度g gg组合而成

公式:

  1. 累计梯度(动量更新):v ← α v + ( 1 − α ) g v \leftarrow \alpha v + (1-\alpha) gvαv+(1α)g
  2. 参数更新:x ← x − η ⋅ v x \leftarrow x - \eta \cdot vxxηv

其中α \alphaα为动量参数,v vv为累计梯度,g gg为当前梯度,η \etaη为学习率

优点:

  1. 加快收敛能帮助参数在正确的方向上加速前进
  2. 可以帮助跳出局部最小值

实验一:

损失函数:f ( x ) = 0.1 x 1 2 + 2 x 2 2 f(x) = 0.1x_1^2 + 2x_2^2f(x)=0.1x12+2x22初始值:x 1 = − 5 x_1 = -5x1=5x 2 = − 2 x_2 = -2x2=2, 学习率:η = 0.4 \eta = 0.4η=0.4,我们使用不带动量的传统梯度下降法,观察下降过程

预期分析:因为x 1 x_1x1x 2 x_2x2的系数分别为 0.1 和 2。这就使得x 1 x_1x1x 2 x_2x2的梯度相差一个量级, 如果使用相同的学习率,x 2 x_2x2的更新幅度会较x 1 x_1x1的更大些

importnumpyasnpimportmatplotlib.pyplotaspltdefloss_func(x1,x2):# 定义目标函数return0.1*x1**2+2*x2**2x1,x2=-5,-2eta=0.4num_epochs=20result=[(x1,x2)]forepochinrange(num_epochs):gd1=0.2*x1 gd2=4*x2 x1-=eta*gd1 x2-=eta*gd2 result.append((x1,x2))plt.plot(*zip(*result),'-o',color='#ff7f0e')x1,x2=np.meshgrid(np.arange(-5.5,1.0,0.1),np.arange(-3.0,1.0,0.1))plt.contour(x1,x2,loss_func(x1,x2),colors='#1f77b4')plt.title('learning rate = {}'.format(eta))plt.xlabel('x1')plt.ylabel('x2')plt.show()

结果分析:与预想一致,使用相同的学习率,x 2 x_2x2的更新幅度会较x 1 x_1x1的更大些,变化快得多,而x 1 x_1x1收敛速度太慢

实验二:

依然使用不带动量的梯度下降算法,将学习率设置为 0.6

更新过程x 1 ← x 1 − 0.06 x 1 x_1 \leftarrow x_1 - 0.06x_1x1x10.06x1x 2 ← x 2 − 2.4 x 2 x_2 \leftarrow x_2-2.4x_2x2x22.4x2

更新过程如下:

这时我们会陷入一个两难的选择:

  • 如果我们选择小的学习率,x 1 x_1x1收敛速度慢
  • 如果我们选择大的学习率,x 1 x_1x1方向会收敛很快,但在x 2 x_2x2方向不会收敛

实验三:

我们使用带动量的梯度下降法,将历史的梯度考虑在内:动量参数设置为 0.5, 学习率设置为0.4

累计梯度更新:v ← α v + ( 1 − α ) g v \leftarrow \alpha v + (1-\alpha) gvαv+(1α)g
权重更新:x ← x − η ⋅ v x \leftarrow x - \eta \cdot vxxηv

importnumpyasnpimportmatplotlib.pyplotaspltdefloss_func(x1,x2):# 定义目标函数return0.1*x1**2+2*x2**2x1,x2=-5,-2v1,v2=0,0eta,alpha=0.4,0.5num_epochs=20result=[(x1,x2)]forepochinrange(num_epochs):v1=alpha*v1+(1-alpha)*(0.2*x1)v2=alpha*v2+(1-alpha)*(4*x2)x1-=eta*v1 x2-=eta*v2 result.append((x1,x2))plt.plot(*zip(*result),'-o',color='#ff7f0e')x1,x2=np.meshgrid(np.arange(-5.5,1.0,0.1),np.arange(-3.0,1.0,0.1))plt.contour(x1,x2,loss_func(x1,x2),colors='#1f77b4')plt.xlabel('x1')plt.ylabel('x2')plt.show()

即使我们将学习率设置为 0.6 ,x 2 x_2x2的梯度也不会发散了


参考连接:https://www.bilibili.com/video/BV1jh4y1q7ua/?spm_id_from=333.1387.favlist.content.click&vd_source=cf0b4c9c919d381324e8f3466e714d7a

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询