Skip to content

RMSProp算法

RMSProp 是 Adagrad 的 “改进升级版”—— 专门解决 Adagrad 学习率衰减太快、后期步长太小走不动的问题,核心是 “只保留近期的路况记录”,让登山者一直保持合适的步长下山,是深度学习非凸问题中常用的自适应优化算法。

一、核心逻辑:为啥需要 “选择性记路况”?

1. Adagrad 的痛点

Adagrad 的问题在于一直累加所有梯度的平方和 随着训练推进, 会越来越大,学习率 会越来越小,后期步长小到几乎走不动,就像登山者一直背着所有走过的路况记录,越走越重,最后迈不开步子。

这在非凸问题(比如深度学习的 CNN、Transformer)里尤其致命 —— 还没走到最优值,就已经 “走不动了”。

2. RMSProp 的解决方案

RMSProp 给登山者加了 “选择性遗忘” 的能力:只保留近期的梯度平方和,用 “泄漏平均值” 替代累加 其中 是 “遗忘系数”,控制保留的历史梯度长度:

  • 时,相当于只保留最近 10 步的梯度平方和( );

  • 越大,保留的历史越长,遗忘越慢;

  • 越小,保留的历史越短,遗忘越快。

简单说:RMSProp 让登山者 “只记最近的路况,不用背所有历史”,步长不会一直衰减,能一直保持合适的速度下山。

二、RMSProp 的核心原理

1. 核心公式

RMSProp 的更新公式分为两步:

其中:

  • :近期梯度平方的泄漏平均值,相当于 “近期路况复杂度记录”;

  • :遗忘系数,常用值 0.9,控制保留的历史长度;

  • :全局学习率,可单独调整,不像 Adagrad 那样被梯度平方和限制;

  • :极小常数(比如 ),防止除以 0;

  • :按元素相乘,每个参数用自己的自适应步长更新。

2. 公式解读

把泄漏平均值展开看, 是过去梯度平方的加权和,越近的梯度权重越大:

  • 时,10 步前的梯度权重只有 ,相当于慢慢遗忘更早的路况;

  • 时,RMSProp 退化为 Adagrad 的 “瞬时版本”,只保留当前梯度平方。

3. 与 Adagrad 的核心区别

特性AdagradRMSProp
梯度平方和计算 (累加所有历史) (泄漏平均值,保留近期)
学习率衰减不断衰减,后期步长极小不会一直衰减,可单独调整全局学习率
适用场景凸优化、稀疏数据非凸优化(深度学习)、稀疏数据
参数调整只需要调整 需要调整

三、实战对比:RMSProp vs Adagrad

用二维函数 平缓、 陡峭)测试:

  • Adagrad( ):前期步长正常,20 轮后 还在 - 0.1 左右,因为 太大,学习率太小,移动缓慢;

  • RMSProp( ):20 轮后 接近 0, 已经收敛到 0,步长一直保持合适的大小,收敛更快更稳定。

这就像 Adagrad 登山者背着所有历史记录,越走越慢;RMSProp 登山者只记最近的路况,一直保持合适的步长,快速下山。

四、PyTorch 实战:选择性记路况的登山流程

1. 从零开始实现

手动实现 RMSProp 的参数更新逻辑,适合理解原理:

python
import torch
from torch import nn
from d2l import torch as d2l

# 1. 初始化RMSProp状态(每个参数对应一个梯度平方泄漏平均值,初始为0)
def init_rmsprop_states(feature_dim):
    s_w = torch.zeros((feature_dim, 1))  # 权重的梯度平方泄漏平均值
    s_b = torch.zeros(1)                 # 偏置的梯度平方泄漏平均值
    return (s_w, s_b)

# 2. RMSProp更新函数
def rmsprop(params, states, hyperparams):
    gamma, eps = hyperparams['gamma'], 1e-6
    for p, s in zip(params, states):
        with torch.no_grad():
            # 计算泄漏平均值:保留历史,加入当前梯度平方
            s[:] = gamma * s + (1 - gamma) * torch.square(p.grad)
            # 自适应步长更新参数
            p[:] -= hyperparams['lr'] * p.grad / torch.sqrt(s + eps)
        p.grad.data.zero_()  # 清空梯度

# 3. 训练函数
def train_rmsprop(lr, gamma, num_epochs=2):
    # 加载数据
    data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
    # 定义模型
    net = nn.Sequential(nn.Linear(feature_dim, 1))
    nn.init.normal_(net[0].weight, std=0.01)
    # 训练
    d2l.train_ch11(
        rmsprop,
        init_rmsprop_states(feature_dim),
        {'lr': lr, 'gamma': gamma},
        data_iter, feature_dim, num_epochs
    )

# 启动训练(lr=0.01,gamma=0.9,经典搭配)
train_rmsprop(lr=0.01, gamma=0.9)

2. 框架简洁实现

用 PyTorch 内置的optim.RMSprop直接调用,更简洁:

python
# 直接使用框架内置的RMSProp
trainer = torch.optim.RMSprop
d2l.train_concise_ch11(
    trainer,
    {'lr': 0.01, 'alpha': 0.9},  # alpha对应公式里的gamma
    data_iter
)

五、优缺点:什么时候用 RMSProp?

1. 优点

  • 解决 Adagrad 的痛点:学习率不会一直衰减,后期也能保持合适的步长;

  • 自适应步长:每个参数有自己的步长,对稀疏数据友好;

  • 适合非凸问题:深度学习的非凸优化(比如 CNN、Transformer)中表现比 Adagrad 好;

  • 参数灵活:可单独调整全局学习率 ,遗忘系数 可根据任务调整。

2. 缺点

  • 参数更多:需要调整 两个参数,比 Adagrad 多一个参数;

  • 选择敏感 太大(比如 0.99),保留的历史太长,学习率还是会衰减; 太小(比如 0.5),噪声太大,步长不稳定。

3. 适用场景

  • 深度学习的非凸问题:比如图像分类、自然语言处理的模型训练;

  • 稀疏数据的优化:比如推荐系统、计算广告学;

  • 替代 Adagrad 的场景:当 Adagrad 后期收敛太慢时,用 RMSProp 替代。

六、常见误区:避开这 2 个坑

  1. 设置太大 时,保留的历史太长, 还是会慢慢变大,学习率衰减,和 Adagrad 一样后期走不动;

  2. 全局学习率设置太大:RMSProp 的自适应步长是 太大的话,前期步长太大,会震荡。

七、核心总结

  1. RMSProp 本质:带遗忘的 Adagrad,用泄漏平均值替代累加,只保留近期的梯度平方和,避免学习率衰减太快;

  2. 关键参数: (遗忘系数,默认 0.9)、 (全局学习率,默认 0.01);

  3. 核心优势:解决了 Adagrad 后期步长太小的问题,适合深度学习的非凸优化;

  4. 一句话记忆:登山时只记最近的路况,不用背所有历史,一直保持合适步长,高效下山~

(注:文档部分内容可能由 AI 生成)

京ICP备2024093538号-1