深度学习——梯度下降优化方法

一、梯度下降相关介绍:

概述:
梯度下降是结合 本次损失函数的导数(作为梯度) 基于学习率 来更新权重
公式:
W新 = W旧 - 学习率 * 梯度
存在的问题:
1. 遇到平缓区域,梯度下降(权重更新)可能会慢
2.可能会遇到鞍点(梯度为0)
3.可能会遇到 局部最小值
解决思路:
从上述的学习率 或者 梯度入手,进行优化,于是有了:动量法Momentum,自适应学习率AdaGrad,RMSProp,综合衡量ADam

1.梯度下降的优化方法-动量算法Momentum

梯度计算公式:

\[s_t=\beta s_{t-1} + (1-\beta)g_t \]

参数更新公式:

\[ w_t=w_{t-1} - \eta s_t \]

  • \(s_t\) 是当前时刻指数加权平均梯度值
  • \(s_{t-1}\) 是历史指数加权平均梯度值
  • \(g_t\) 是当前时刻的梯度值
  • \(\beta\) 是调节权重系数,通常取 0.9 或 0.99
  • \(\eta\) 是学习率
  • \(w_t\) 是当前时刻模型权重参数

2.梯度下降的优化方法-adaGrad

AdaGrad 通过对不同的参数分量使用不同的学习率,AdaGrad 的学习率总体会逐渐减小。

其计算步骤如下:

  1. 初始化学习率 \(\eta\)、初始化参数\(w\)、小常数 \(\sigma = 1\mathrm{e}{-10}\)
  2. 初始化梯度累计变量 \(s = 0\)
  3. 从训练集中采样 \(m\) 个样本的小批量,计算梯度\(g_t\)
  4. 累积平方梯度: \(s_t = s_{t-1} + g_t \odot g_t\)\(\odot\) 表示各个分量相乘
  5. 学习率 \(\eta\) 的计算公式如下:

\[\eta = \frac{\eta}{\sqrt{s_t}+\sigma} \]

  1. 权重参数更新公式如下:

\[w_t = w_{t-1} - \frac{\eta}{\sqrt{s_t}+\sigma} * g_t \]

  1. 重复 3-7 步骤

AdaGrad 缺点是可能会使得学习率过早、过量的降低,导致模型训练后期学习率太小,较难找到最优解。

3.梯度下降的优化方法RMSProp

RMSProp 优化算法是对 AdaGrad 的优化. 最主要的不同是,其使用指数加权平均梯度替换历史梯度的平方和。其计算过程如下:

  1. 初始化学习率 \(\eta\)、初始化权重参数\(w\)、小常数 \(\sigma = 1\mathrm{e}{-10}\)
  2. 初始化梯度累计变量 \(s = 0\)
  3. 从训练集中采样 \(m\) 个样本的小批量,计算梯度 \(g_t\)
  4. 使用指数加权平均累计历史梯度,\(\odot\) 表示各个分量相乘,公式如下:

\[s_t = \beta s_{t-1} + (1-\beta)g_t \odot g_t \]

  1. 学习率 \(\eta\) 的计算公式如下:

\[\eta = \frac{\eta}{\sqrt{s_t}+\sigma} \]

  1. 权重参数更新公式如下:

\[w_t = w_{t-1} - \frac{\eta}{\sqrt{s_t}+\sigma} * g_t \]

  1. 重复 3-7 步骤

4.梯度下降的优化方法-Adam

  • Momentum 使用指数加权平均计算当前的梯度值

  • AdaGrad、RMSProp 使用自适应的学习率

  • Adam优化算法(Adaptive Moment Estimation,自适应矩估计)将Momentum 和 RMSProp 算法结合在一起

    • 修正梯度:使用梯度的指数加权平均
    • 修正学习率:使用梯度平方的指数加权平均
  • 原理:Adam 是结合了 MomentumRMSProp 优化算法的优点的自适应学习率算法。它计算了梯度的一阶矩(平均值)和二阶矩(梯度的方差)的自适应估计,从而动态调整学习率。

  • 梯度计算公式:

\[\begin{align*} m_t &= \beta_1 m_{t-1} + (1 - \beta_1)g_t \\ s_t &= \beta_2 s_{t-1} + (1 - \beta_2)g_t^2 \\ \hat{m}_t &= \frac{m_t}{1-\beta_1^t},\quad \hat{s}_t = \frac{s_t}{1-\beta_2^t} \end{align*} \]

  • 权重参数更新公式:

\[w_t = w_{t-1} - \frac{\eta}{\sqrt{\hat{s}_t}+\epsilon}\hat{m}_t \]

其中,\(m_t\) 是梯度的一阶矩估计,\(s_t\) 是梯度的二阶矩估计,\(\hat{m}_t\)\(\hat{s}_t\) 偏差校正后的估计。

二、梯度下降方法的代码演示

导包

import torch
import torch.nn as nn

1. 定义函数,演示:梯度下降优化方法 ——> 动量法(Momentum)

def dm01_momentum():
    # 1. 初始化权重参数
    w = torch.tensor([0,1], requires_grad=True, dtype=torch.float)
    # 2. 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 3. 创建优化器(函数对象),基于SGD(随机梯度下降),加入参数 momentum,就是动量法
    # 参1:(待)优化的参数列表;参2:学习率;参3:动量参数
    optimizer = torch.optim.SGD(params=[w], lr=0.01, momentum=0.9) # 细节:momentum=0(默认),只考虑本此梯度
    # 4. 计算梯度值:梯度清零+反向传播+参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    print(f'动量法:\nw:{w},w.grad:{w.grad}')

    # 5. 重复上述的步骤,第2次 更新权重
    # 5.1 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 5.2 计算梯度值:梯度清理 + 反向传播 + 参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    # 5.3 打印结果
    print(f'动量法:\nw:{w},w.grad:{w.grad}')

2. 定义函数,演示:梯度下降优化方法 ——> AdaGrad自适应学习率

def dm02_adagrad():
    # 1. 初始化权重参数
    w = torch.tensor([0,1], requires_grad=True, dtype=torch.float)
    # 2. 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 3. 创建优化器(函数对象),
    #思路1:基于SGD(随机梯度下降),加入参数 momentum,就是动量法
    # 参1:(待)优化的参数列表;参2:学习率;参3:动量参数
    # optimizer = torch.optim.SGD(params=[w], lr=0.01, momentum=0.9) # 细节:momentum=0(默认),只考虑本此梯度
    #思路2:基于AdaGrad(自适应学习率),加入参数 momentum,就是动量法
    optimizer = torch.optim.Adagrad(params=[w], lr=0.01)
    # 4. 计算梯度值:梯度清零+反向传播+参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    print(f'AdaGrad:\nw:{w},w.grad:{w.grad}')

    # 5. 重复上述的步骤,第2次 更新权重
    # 5.1 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 5.2 计算梯度值:梯度清理 + 反向传播 + 参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    # 5.3 打印结果
    print(f'AdaGrad:\nw:{w},w.grad:{w.grad}')

3. 定义函数,演示:梯度下降优化方法 ——> RMSProp自适应学习率

def dm03_rmsprop():
    # 1. 初始化权重参数
    w = torch.tensor([0,1], requires_grad=True, dtype=torch.float)
    # 2. 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 3. 创建优化器(函数对象),
    #思路1:基于SGD(随机梯度下降),加入参数 momentum,就是动量法
    # 参1:(待)优化的参数列表;参2:学习率;参3:动量参数
    # optimizer = torch.optim.SGD(params=[w], lr=0.01, momentum=0.9) # 细节:momentum=0(默认),只考虑本此梯度
    #思路2:基于AdaGrad(自适应学习率),加入参数 momentum,就是动量法
    # optimizer = torch.optim.Adagrad(params=[w], lr=0.01)
    #思路3:基于RMSProp
    optimizer = torch.optim.RMSprop(params=[w], lr=0.01,alpha=0.99)
    # 4. 计算梯度值:梯度清零+反向传播+参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    print(f'RMSProp:\nw:{w},w.grad:{w.grad}')

    # 5. 重复上述的步骤,第2次 更新权重
    # 5.1 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 5.2 计算梯度值:梯度清理 + 反向传播 + 参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    # 5.3 打印结果
    print(f'RMSProp:\nw:{w},w.grad:{w.grad}')

4. 定义函数,演示:梯度下降优化方法 ——> 自适应矩估计

def dm04_adam():
    # 1. 初始化权重参数
    w = torch.tensor([0,1], requires_grad=True, dtype=torch.float)
    # 2. 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 3. 创建优化器(函数对象),
    #思路1:基于SGD(随机梯度下降),加入参数 momentum,就是动量法
    # 参1:(待)优化的参数列表;参2:学习率;参3:动量参数
    # optimizer = torch.optim.SGD(params=[w], lr=0.01, momentum=0.9) # 细节:momentum=0(默认),只考虑本此梯度
    #思路2:基于AdaGrad(自适应学习率),加入参数 momentum,就是动量法
    # optimizer = torch.optim.Adagrad(params=[w], lr=0.01)
    #思路3:基于RMSProp
    # optimizer = torch.optim.RMSprop(params=[w], lr=0.01,alpha=0.99)
    #思路4:基于Adam
    optimizer = torch.optim.Adam(params=[w], lr=0.01,betas=(0.9,0.999)) # betas = (梯度用的衰减系数,学习率用的衰减系数)
    # 4. 计算梯度值:梯度清零+反向传播+参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    print(f'RMSProp:\nw:{w},w.grad:{w.grad}')

    # 5. 重复上述的步骤,第2次 更新权重
    # 5.1 定义损失函数
    criterion = ((w ** 2) / 2.0)
    # 5.2 计算梯度值:梯度清理 + 反向传播 + 参数更新
    optimizer.zero_grad()
    criterion.sum().backward() # 执行这段代码后,会自动求导,把梯度写到 w 的 grad 里,只算梯度,不改权重
    optimizer.step() # 优化器读取已经算好的 w.grad,按照算法公式(SGD / 动量 / Adam 等)直接修改 w 的数值。
    # 5.3 打印结果
    print(f'RMSProp:\nw:{w},w.grad:{w.grad}')

5.测试

if __name__ == '__main__':
    # dm01_momentum()
    # dm02_adagrad()
    dm03_rmsprop()

小结

优化算法 优点 缺点 适用场景
SGD 简单、容易实现。 收敛速度较慢,容易震荡,特别是在复杂问题中。 用于简单任务,或者当数据特征分布相对稳定时。
Momentum 可以加速收敛,减少震荡,特别是在高曲率区域。 需要手动调整动量超参数,可能会在小步长训练中过度更新。 用于非平稳优化问题,尤其是深度学习中的应用。
AdaGrad 自适应调整学习率,适用于稀疏数据。 学习率会在训练过程中逐渐衰减,可能导致早期停滞。 适合稀疏数据,如 NLP 或推荐系统中的特征。
RMSProp 解决了 AdaGrad 学习率过早衰减的问题,适应性强。 需要选择合适的超参数,更新可能会过于激进。 适用于动态问题、非平稳目标函数,如深度学习训练。
Adam 结合了 Momentum 和 RMSProp 的优点,适应性强且稳定。 需要调节更多的超参数,训练过程中可能会产生较大波动。 广泛适用于各种深度学习任务,特别是非平稳和复杂问题。
  • 简单任务和较小的模型:SGD 或 Momentum

  • 复杂任务或有大量数据:Adam 是最常用的选择,因其在大部分任务上都表现优秀

  • 需要处理稀疏数据或文本数据:Adagrad 或 RMSProp

posted @ 2026-07-16 17:25  王新文  阅读(4)  评论(0)    收藏  举报