Bootstrap

梯度下降优化算法-Adam

Adam(Adaptive Moment Estimation)是一种结合了动量法(Momentum)和 RMSProp 的自适应学习率优化算法。它通过计算梯度的一阶矩(均值)和二阶矩(未中心化的方差)来调整每个参数的学习率,从而在深度学习中表现出色。


1. Adam 的数学原理

1.1 动量法和 RMSProp 的回顾

  • 动量法:通过引入动量变量,加速梯度下降并减少震荡。
  • RMSProp:通过指数加权移动平均计算历史梯度平方和,自适应调整学习率。

Adam 结合了这两种方法的优点,同时计算梯度的一阶矩和二阶矩。


1.2 Adam 的更新规则

Adam 的更新规则分为以下几个步骤:

1.2.1 梯度计算

首先,计算当前时刻的梯度:

g t = ∇ θ J ( θ t ) g_t = \nabla_\theta J(\theta_t) gt=θJ(θt)

其中:

  • g t g_t gt 是当前时刻的梯度向量,形状与参数 θ t \theta_t θt 相同。

1.2.2 一阶矩估计(动量)

Adam 使用指数加权移动平均来计算梯度的一阶矩(均值):

m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t mt=β1mt1+(1β1)gt

其中:

  • m t m_t mt 是梯度的一阶矩估计。
  • β 1 \beta_1 β1 是一阶矩的衰减率,通常取值在 [ 0.9 , 0.99 ) [0.9, 0.99) [0.9,0.99) 之间。
  • 初始时, m 0 m_0 m0 通常设置为 0。

1.2.3 二阶矩估计(RMSProp)

Adam 使用指数加权移动平均来计算梯度的二阶矩(未中心化的方差):

v t = β 2 ⋅ v t − 1 + ( 1 − β 2 ) ⋅ g t 2 v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g_t^2 vt=β2vt1+(1β2)gt2

其中:

  • v t v_t vt 是梯度的二阶矩估计。
  • β 2 \beta_2 β2 是二阶矩的衰减率,通常取值在 [ 0.99 , 0.999 ) [0.99, 0.999) [0.99,0.999) 之间。
  • g t 2 g_t^2 gt2 表示对梯度向量 g t g_t gt 逐元素平方。
  • 初始时, v 0 v_0 v0 通常设置为 0。

1.2.4 偏差校正

由于 m t m_t mt v t v_t vt 初始值为 0,在训练初期会偏向 0,因此需要进行偏差校正:

m ^ t = m t 1 − β 1 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t} m^t=1β1tmt

v ^ t = v t 1 − β 2 t \hat{v}_t = \frac{v_t}{1 - \beta_2^t} v^t=1β2tvt

其中:

  • m ^ t \hat{m}_t m^t 是校正后的一阶矩估计。
  • v ^ t \hat{v}_t v^t 是校正后的二阶矩估计。
  • t t t 是当前时间步。

1.2.5 参数更新

最后,Adam 的参数更新公式为:

θ t + 1 = θ t − η v ^ t + ϵ ⋅ m ^ t \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \cdot \hat{m}_t θt+1=θtv^t +ϵηm^t

其中:

  • η \eta η 是全局学习率。
  • ϵ \epsilon ϵ 是一个很小的常数(通常为 1 0 − 8 10^{-8} 108),用于避免分母为零。
  • v ^ t + ϵ \sqrt{\hat{v}_t} + \epsilon v^t +ϵ 是对校正后的二阶矩估计逐元素开平方。

2. Adam 的详细推导

2.1 一阶矩和二阶矩的意义

  • 一阶矩 m t m_t mt:类似于动量法,表示梯度的指数加权移动平均,用于加速收敛。
  • 二阶矩 v t v_t vt:类似于 RMSProp,表示梯度平方的指数加权移动平均,用于自适应调整学习率。

2.2 偏差校正的作用

偏差校正的目的是解决初始阶段 m t m_t mt v t v_t vt 偏向 0 的问题。通过除以 1 − β 1 t 1 - \beta_1^t 1β1t 1 − β 2 t 1 - \beta_2^t 1β2t,可以校正估计值,使其更接近真实值。


2.3 小常数 ϵ \epsilon ϵ 的作用

小常数 ϵ \epsilon ϵ 的作用是避免分母为零。具体来说:

  • v ^ t \hat{v}_t v^t 很小时, v ^ t + ϵ \sqrt{\hat{v}_t} + \epsilon v^t +ϵ 接近于 ϵ \epsilon ϵ,避免学习率过大。
  • v ^ t \hat{v}_t v^t 很大时, ϵ \epsilon ϵ 的影响可以忽略不计。

3. PyTorch 中的 Adam 实现

在 PyTorch 中,Adam 通过 torch.optim.Adam 实现。以下是 torch.optim.Adam 的主要参数:

参数名含义
params需要优化的参数(通常是模型的参数)。
lr全局学习率(learning rate),即 η \eta η,默认值为 1 0 − 3 10^{-3} 103
betas一阶矩和二阶矩的衰减率,即 ( β 1 , β 2 ) (\beta_1, \beta_2) (β1,β2),默认值为 (0.9, 0.999)。
eps分母中的小常数 ϵ \epsilon ϵ,用于避免除零,默认值为 1 0 − 8 10^{-8} 108
weight_decay权重衰减(L2 正则化)系数,默认值为 0。
amsgrad是否使用 AMSGrad 变体,默认值为 False

3.1 使用 Adam 的代码示例

以下是一个使用 Adam 的完整代码示例:

import torch
import torch.nn as nn
import torch.optim as optim

# 定义一个简单的线性模型
model = nn.Linear(10, 1)

# 定义损失函数
criterion = nn.MSELoss()

# 定义优化器,使用 Adam
optimizer = optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.01)

# 模拟输入数据和目标数据
inputs = torch.randn(32, 10)  # 32 个样本,每个样本 10 维
targets = torch.randn(32, 1)  # 32 个目标值

# 训练过程
for epoch in range(100):
    # 前向传播
    outputs = model(inputs)
    loss = criterion(outputs, targets)

    # 反向传播
    optimizer.zero_grad()  # 清空梯度
    loss.backward()        # 计算梯度

    # 更新参数
    optimizer.step()       # 更新参数

    # 打印损失
    if (epoch + 1) % 10 == 0:
        print(f"Epoch [{epoch+1}/100], Loss: {loss.item():.4f}")

3.2 参数设置说明

  1. 学习率 (lr)

    • 学习率 η \eta η 控制每次参数更新的步长。
    • 在 Adam 中,学习率会自适应调整,因此初始学习率可以设置得稍小一些。
  2. 衰减率 (betas)

    • 一阶矩衰减率 β 1 \beta_1 β1 和二阶矩衰减率 β 2 \beta_2 β2 分别控制一阶矩和二阶矩的衰减速度。
    • 默认值为 (0.9, 0.999),适用于大多数情况。
  3. 小常数 (eps)

    • 小常数 ϵ \epsilon ϵ 用于避免分母为零,通常设置为 1 0 − 8 10^{-8} 108
  4. 权重衰减 (weight_decay)

    • 权重衰减系数用于 L2 正则化,防止过拟合。
  5. AMSGrad (amsgrad)

    • 如果设置为 True,则使用 AMSGrad 变体,解决 Adam 在某些情况下的收敛问题。

4. 总结

  • Adam 的核心思想:结合动量法和 RMSProp,通过计算梯度的一阶矩和二阶矩,自适应调整学习率。
  • Adam 的更新公式
    m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t mt=β1mt1+(1β1)gt
    v t = β 2 ⋅ v t − 1 + ( 1 − β 2 ) ⋅ g t 2 v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g_t^2 vt=β2vt1+(1β2)gt2
    m ^ t = m t 1 − β 1 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t} m^t=1β1tmt
    v ^ t = v t 1 − β 2 t \hat{v}_t = \frac{v_t}{1 - \beta_2^t} v^t=1β2tvt
    θ t + 1 = θ t − η v ^ t + ϵ ⋅ m ^ t \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \cdot \hat{m}_t θt+1=θtv^t +ϵηm^t
  • PyTorch 实现:使用 torch.optim.Adam,设置 lrbetaseps 等参数。
  • 优缺点
    • 优点:自适应学习率,适合非凸优化问题,收敛速度快。
    • 缺点:需要手动调整超参数(如 β 1 \beta_1 β1 β 2 \beta_2 β2)。
;