
人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载导读RMSProp 算法是《动手学深度学习》d2l-zh优化算法章节中承上启下的关键一节它用“泄漏平均值”修复了 Adagrad 因累加梯度平方而导致的过猛学习率衰减同时保留了按坐标自适应的缩放能力。本文将以 chapter_optimization/rmsprop.md 为主体从问题动机、数学推导、超参数直觉出发完整给出 MXNet、PyTorch、TensorFlow、PaddlePaddle 四种框架下的从零实现与简洁实现并对照仓库源码d2l/torch.py、d2l/paddle.py 等解析训练辅助函数的内部调用链。读完本文你将能独立推导 RMSProp 更新方程、读懂泄漏平均的指数加权本质并在真实数据集上完成从状态初始化到收敛监控的完整训练流程。动机Adagrad 的学习率衰减困境在阅读 chapter_optimization/adagrad.md 时我们看到Adagrad 将历史梯度平方累加成状态矢量$$\mathbf{s}t \mathbf{s}{t-1} \mathbf{g}_t^2$$并用它按坐标缩放学习率$$\mathbf{w}t \mathbf{w}{t-1} - \frac{\eta}{\sqrt{\mathbf{s}_t \epsilon}} \cdot \mathbf{g}_t$$问题在于$\mathbf{s}_t$ 是无界累加。由于缺乏归一化随着训练进行$\mathbf{s}_t$ 持续增长几乎以线性速率递增。这导致有效学习率 $\eta / \sqrt{\mathbf{s}_t \epsilon}$ 按 $\mathcal{O}(t^{-\frac{1}{2}})$ 的速度显著衰减——在凸问题上这通常足够但在深度学习中常见的非凸问题上学习率衰减过快会让参数在算法后期移动极其缓慢甚至停滞。Adagrad 的可取之处在于它作为“预处理器”的坐标自适应能力较大梯度的坐标被显著缩小较小梯度的坐标得到更平滑的处理。RMSProp 的目标正是把“速率调度”与“坐标自适应学习率”这两件事分离开来各管各的。算法用泄漏平均值修复累加从 $\mathbf{s}_t / t$ 到泄漏平均一个直观的修复方案是使用 $\mathbf{s}_t / t$ 做归一化对合理的梯度分布它会收敛。但遗憾的是这种“记忆完整轨迹”的方式需要很长时间才能让极限行为起作用因为 $\mathbf{s}_t$ 记住了全部历史值。更好的替代方案来自动量法见 chapter_optimization/momentum.md中的泄漏平均值leaky average技巧$$\mathbf{s}t \leftarrow \gamma \mathbf{s}{t-1} (1-\gamma) \mathbf{g}_t^2, \quad \gamma 0$$保持其余部分不变就得到了 RMSProp 算法。这一思想最早由 Tieleman 与 Hinton 提出:cite:Tieleman.Hinton.2012。完整更新方程RMSProp 的两步更新如下$$\begin{aligned} \mathbf{s}t \leftarrow \gamma \mathbf{s}{t-1} (1 - \gamma) \mathbf{g}_t^2, \ \mathbf{x}t \leftarrow \mathbf{x}{t-1} - \frac{\eta}{\sqrt{\mathbf{s}_t \epsilon}} \odot \mathbf{g}_t. \end{aligned}$$其中$\mathbf{s}_t$ 是平方梯度的指数加权移动平均EWMA即每坐标的“二阶矩估计”$\gamma \in (0, 1)$ 是衰减系数控制历史信息的记忆长度$\eta$ 是全局学习率与坐标缩放完全解耦可自由控制$\epsilon 0$ 通常设为 $10^{-6}$用于防止除以零或步长过大造成的数值不稳定$\odot$ 表示逐元素按坐标相乘。对比 Adagrad 的 $\mathbf{s}t \mathbf{s}{t-1} \mathbf{g}_t^2$RMSProp 用 $(1-\gamma)$ 加权的泄漏项替代了简单累加使 $\mathbf{s}_t$ 不再无界增长。权重总和与半衰期将 $\mathbf{s}_t$ 的定义递归展开可得$$ \mathbf{s}t (1 - \gamma) \left(\mathbf{g}t^2 \gamma \mathbf{g}{t-1}^2 \gamma^2 \mathbf{g}{t-2}^2 \ldots \right) $$利用几何级数求和 $1 \gamma \gamma^2 \ldots \frac{1}{1-\gamma}$可知历史梯度的权重总和被标准化为 1而观测值的半衰期为 $\gamma^{-1}$。也就是说$\gamma$ 越大历史信息衰减越慢有效窗口越长$\gamma$ 越小算法越“短视”越接近对最近梯度的即时反应。原文档用 40 个时间步长的权重分布图直观演示了这一性质设置gammas [0.95, 0.9, 0.8, 0.7]绘制 $(1-\gamma) \cdot \gamma^x$ 随时间的曲线可以清楚看到不同 $\gamma$ 下历史权重衰减速度的差异对应代码位于 chapter_optimization/rmsprop.md 的“算法”小节。从零开始实现二维实验RMSProp 在条件不佳问题上的轨迹原文档沿用经典的二次函数 $f(\mathbf{x}) 0.1 x_1^2 2 x_2^2$ 观察优化轨迹。回忆 chapter_optimization/adagrad.md 中的结论Adagrad 在 $\eta 0.4$ 时因学习率衰减过快变量在后期移动极慢RMSProp 因为 $\eta$ 单独控制不会发生这种情况。二维演示的核心代码如下#tab all def rmsprop_2d(x1, x2, s1, s2): g1, g2, eps 0.2 * x1, 4 * x2, 1e-6 s1 gamma * s1 (1 - gamma) * g1 ** 2 s2 gamma * s2 (1 - gamma) * g2 ** 2 x1 - eta / math.sqrt(s1 eps) * g1 x2 - eta / math.sqrt(s2 eps) * g2 return x1, x2, s1, s2 def f_2d(x1, x2): return 0.1 * x1 ** 2 2 * x2 ** 2 eta, gamma 0.4, 0.9 d2l.show_trace_2d(f_2d, d2l.train_2d(rmsprop_2d))其中d2l.train_2d与d2l.show_trace_2d是仓库中通用的 2D 可视化辅助函数。以 d2l/torch.py 为例train_2d从 $(x_1, x_2) (-5, -2)$ 出发、状态变量 $s_1 s_2 0$迭代 20 步并打印每步轨迹show_trace_2d则在等高线图上叠加优化轨迹。这里 $x_2$ 方向的梯度$4x_2$远大于 $x_1$ 方向$0.2x_1$是典型的条件不佳问题恰好能检验 RMSProp 的坐标自适应能力。状态初始化RMSProp 需要为每个参数维护一个与梯度同形状的状态变量 $\mathbf{s}$。原文档给出各框架的初始化#tab mxnet, pytorch def init_rmsprop_states(feature_dim): s_w d2l.zeros((feature_dim, 1)) s_b d2l.zeros(1) return (s_w, s_b)#tab paddle def init_rmsprop_states(feature_dim): s_w d2l.zeros((feature_dim, 1)) s_b d2l.zeros([1]) return (s_w, s_b)#tab tensorflow def init_rmsprop_states(feature_dim): s_w tf.Variable(d2l.zeros((feature_dim, 1))) s_b tf.Variable(d2l.zeros(1)) return (s_w, s_b)注意 TensorFlow 版本需要把状态变量包装成tf.Variable以便后续用assign原地更新MXNet、PyTorch、Paddle 版本则直接使用张量并原地切片赋值s[:] ...。核心更新逻辑四个框架对照从零实现的rmsprop函数逐参数完成“更新 $\mathbf{s}$ → 按缩放后更新 $\mathbf{p}$”两步MXNetchapter_optimization/rmsprop.mddef rmsprop(params, states, hyperparams): gamma, eps hyperparams[gamma], 1e-6 for p, s in zip(params, states): s[:] gamma * s (1 - gamma) * np.square(p.grad) p[:] - hyperparams[lr] * p.grad / np.sqrt(s eps)PyTorchdef 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_()TensorFlowdef rmsprop(params, grads, states, hyperparams): gamma, eps hyperparams[gamma], 1e-6 for p, s, g in zip(params, states, grads): s[:].assign(gamma * s (1 - gamma) * tf.math.square(g)) p[:].assign(p - hyperparams[lr] * g / tf.math.sqrt(s eps))PaddlePaddledef rmsprop(params, states, hyperparams): a [] gamma, eps hyperparams[gamma], 1e-6 for p, s in zip(params, states): with paddle.no_grad(): s[:] gamma * s (1 - gamma) * paddle.square(p.grad) p[:] - hyperparams[lr] * p.grad / paddle.sqrt(s eps) p.grad.zero_() a.append(p) return a实现要点状态更新严格对应 $\mathbf{s}t \leftarrow \gamma \mathbf{s}{t-1} (1-\gamma) \mathbf{g}_t^2$参数更新严格对应 $\mathbf{x}t \leftarrow \mathbf{x}{t-1} - \frac{\eta}{\sqrt{\mathbf{s}_t \epsilon}} \odot \mathbf{g}_t$PyTorch 用torch.no_grad()包裹原地更新并显式清零梯度Paddle 同样用paddle.no_grad()并调用p.grad.zero_()TensorFlow 通过tf.Variable.assign完成原地赋值Paddle 版本额外返回参数列表a这是train_ch11接口约定的一部分。在真实数据集上训练原文档使用d2l.get_data_ch11(batch_size10)加载翼型噪声airfoil数据集做回归实验。以 d2l/torch.py 为例该函数从仓库数据仓库下载 airfoil 数据、做标准化减均值除标准差取前 1500 条样本构成小批量迭代器data_iter返回的特征维数为data.shape[1] - 1即 5 个特征。将初始学习率设为0.01、加权项 $\gamma$ 设为0.9此时 $\mathbf{s}$ 累加了过去 $1/(1-\gamma) 10$ 次平方梯度观测值的平均值#tab all data_iter, feature_dim d2l.get_data_ch11(batch_size10) d2l.train_ch11(rmsprop, init_rmsprop_states(feature_dim), {lr: 0.01, gamma: 0.9}, data_iter, feature_dim);d2l.train_ch11见 d2l/torch.py完成了标准的线性回归训练闭环用torch.normal(mean0.0, std0.01, size(feature_dim, 1))初始化权重、torch.zeros(1)初始化偏置构造net lambda X: d2l.linreg(X, w, b)与平方损失随后迭代data_iter完成前向、l.backward()反传再调用trainer_fn([w, b], states, hyperparams)执行优化器更新每隔 200 个样本通过Animator记录一次损失曲线最终打印收敛损失与平均耗时。你可以从该实现中清楚地看到优化器只负责“根据梯度改参数”前向传播与反向传播都由外层训练循环承担。简洁实现调用框架内置 RMSProp由于 RMSProp 是主流深度学习框架的内置优化器我们可以用一行代码替换整套从零实现#tab mxnet d2l.train_concise_ch11(rmsprop, {learning_rate: 0.01, gamma1: 0.9}, data_iter)#tab pytorch trainer torch.optim.RMSprop d2l.train_concise_ch11(trainer, {lr: 0.01, alpha: 0.9}, data_iter)#tab tensorflow trainer tf.keras.optimizers.RMSprop d2l.train_concise_ch11(trainer, {learning_rate: 0.01, rho: 0.9}, data_iter)#tab paddle trainer paddle.optimizer.RMSProp d2l.train_concise_ch11(trainer, {learning_rate: 0.01, rho: 0.9}, data_iter)各框架对同一个超参数 $\gamma$ 的命名不同迁移时注意对应框架优化器入口$\gamma$ 参数名学习率参数名MXNetrmspropTrainer 名称gamma1learning_ratePyTorchtorch.optim.RMSpropalphalrTensorFlowtf.keras.optimizers.RMSproprholearning_ratePaddlePaddlepaddle.optimizer.RMSProprholearning_rate以 PyTorch 为例train_concise_ch11见 d2l/torch.py先构造nn.Sequential(nn.Linear(5, 1))并用标准差 0.01 初始化权重然后执行optimizer trainer_fn(net.parameters(), **hyperparams)直接实例化框架优化器训练循环中调用optimizer.zero_grad()、loss.backward()、optimizer.step()三个标准步骤。可以看到简洁实现与从零实现共享同一套数据与训练框架二者轨迹应高度一致唯一的区别是参数/超参数命名映射。实验对照为什么 RMSProp 不再“卡住”在二维二次函数实验中Adagrad 使用 $\eta 0.4$ 时由于 $\mathbf{s}_t$ 线性增长导致有效学习率急剧下降变量在后期几乎停滞而 RMSProp 在同样学习率 $\eta 0.4$、$\gamma 0.9$ 下不会出现该问题因为 $\eta$ 与坐标缩放解耦、由实验者自由调度。这正是 RMSProp 相对 Adagrad 的核心改进把“学习率随时间衰减”的调度责任从算法中剥离出来交给实验者通过 $\eta$ 显式控制可配合 chapter_optimization/lr-scheduler.md 中的学习率调度策略使用。小结RMSProp 与 Adagrad 非常相似两者都使用梯度的平方来缩放系数区别在于 RMSProp 用泄漏平均值取代了无界累加。RMSProp 与动量法都使用泄漏平均值但用途不同动量法用它平滑梯度方向RMSProp 用它调整按坐标顺序的预处理器。在实验中学习率 $\eta$ 需要由实验者主动调度算法本身不再强制按 $\mathcal{O}(t^{-\frac{1}{2}})$ 衰减。系数 $\gamma$ 决定调整每坐标比例时历史记录的有效时长半衰期为 $\gamma^{-1}$有效窗口约为 $1/(1-\gamma)$。练习与思考如果设置 $\gamma 1$实验会发生什么为什么提示此时 $\mathbf{s}t \mathbf{s}{t-1}$RMSProp 退化为 Adagrad 的累加行为。旋转优化问题最小化 $f(\mathbf{x}) 0.1 (x_1 x_2)^2 2 (x_1 - x_2)^2$。收敛会发生什么变化这能说明坐标自适应对旋转的敏感性吗在真实机器学习问题上例如 Fashion-MNIST 分类应用 RMSProp试验不同的学习率取值观察收敛曲线差异。随着优化进展是否需要调整 $\gamma$RMSProp 对 $\gamma$ 的敏感度如何结合半衰期公式与权重分布图思考。本章完整脉络可参考 chapter_optimization/index.md 的目录结构RMSProp 位于 Adagrad 之后、Adadelta 与 Adam 之前是理解 chapter_optimization/adam.md 中 Adam 算法动量 RMSProp 缩放组合的必要前置知识。赞分享人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载相关推荐动手学深度学习稠密连接网络DenseNet原理与四框架实现指南动手学深度学习稠密连接网络DenseNet原理与四框架实现指南 本篇技术指南以《动手学深度学习》d2l zh仓库的 densenet.md https人工智能深度学习机器学习教程《动手学深度学习》之汇聚层池化层从原理到四大框架实战《动手学深度学习》之汇聚层池化层从原理到四大框架实战 汇聚层Pooling Layer也译作池化层是卷积神经网络中与卷积层并肩的基石组件。本篇基于《人工智能深度学习机器学习教程《动手学深度学习》AdaGrad 算法全解析逐坐标自适应学习率的前沿原理与多框架实战《动手学深度学习》AdaGrad 算法全解析逐坐标自适应学习率的前沿原理与多框架实战 AdaGradAdaptive Subgradient Methods人工智能深度学习机器学习教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考