深度学习中优化器的SGD with Polyak-Ruppert Averaging算法原理与收敛加速机制
1. 题目描述
本题目聚焦于SGD with Polyak-Ruppert Averaging(简称Polyak-Ruppert平均或Polyak平均),一种结合了随机梯度下降与迭代平均的优化算法。在深度学习的随机优化中,标准的随机梯度下降法(SGD)通常会在最优点附近产生振荡,这可能导致最终模型参数存在随机扰动,进而影响泛化性能。Polyak-Ruppert平均通过在训练过程中持续地对历史参数取平均值,能够平滑掉振荡,从而得到更接近理论最优值的参数,提升模型收敛的稳定性和最终性能。
我们将深入探讨:
- 核心问题:标准SGD在最优解附近的振荡问题。
- 算法核心思想:迭代平均(Polyak-Ruppert平均)如何解决此问题。
- 算法步骤:详细推导Polyak-Ruppert平均的公式与更新过程。
- 数学原理:解释其为何能加速收敛并提高稳定性。
- 在深度学习中的应用技巧。
2. 循序渐进解题过程
步骤1:理解背景与问题——标准SGD的振荡
在深度学习优化中,我们通常最小化经验风险函数 \(J(\theta)\)。标准SGD的参数更新规则为:
\[\theta_{t+1} = \theta_t - \eta_t g_t \]
其中,\(\theta_t\) 是第 \(t\) 步的参数,\(\eta_t\) 是学习率,\(g_t = \nabla J(\theta_t; \xi_t)\) 是基于小批量样本 \(\xi_t\) 计算的随机梯度。
- 问题所在:由于梯度 \(g_t\) 是基于随机抽取的小批量样本计算的,它是有噪声的。即使参数已接近理论最优解 \(\theta^*\),梯度估计 \(g_t\) 的期望可能是零,但其方差(噪声)依然存在。这导致 \(\theta_t\) 会在 \(\theta^*\) 附近不断跳动,无法稳定下来。最终,我们得到的“最终模型” \(\theta_T\) 实际上是最后一次迭代的参数,它可能偏离 \(\theta^*\) 较远,从而影响模型性能。
步骤2:引入核心思想——迭代平均
为了缓解随机噪声带来的影响,一个直观的想法是:既然最终的 \(\theta_T\) 是“不稳定的”,我们何不利用训练过程中产生的一系列参数 \(\{\theta_1, \theta_2, ..., \theta_T\}\) 来构造一个更稳定的估计量?
Polyak-Ruppert平均的核心思想是:计算从某个时刻 \(t_0\) 开始,到最终时刻 \(T\) 为止,所有迭代点 \(\theta_t\) 的简单算术平均。这个平均值被用作最终的模型参数。
- 直观理解:想象一个点在目标点附近随机跳动。虽然每一步的位置都带有噪声,但所有位置的平均值会更加接近目标点的中心,从而抵消了大部分随机扰动。在凸优化理论中,这被证明能显著提升收敛速度。
步骤3:算法步骤详解
设总迭代次数为 \(T\),我们通常不会从第一步开始平均,而是选择一个“平均开始点” \(t_0\)(例如,\(t_0 = T/2\)),以避开早期训练不稳定阶段。算法流程如下:
- 初始化:随机初始化参数 \(\theta_1\)。初始化“平均参数” \(\bar{\theta}_0 = 0\)(或一个零向量)。设置学习率序列 \(\{\eta_t\}\)(通常需要满足递减条件,如 \(\eta_t = O(1/\sqrt{t})\))。
- 迭代更新:
- SGD更新:对于 \(t = 1\) 到 \(T\),执行标准SGD步骤。
\[\theta_{t+1} = \theta_t - \eta_t g_t \]
* **在线平均**:从 $t = t_0$ 开始,我们**在线**地计算和更新平均参数 $\bar{\theta}_t$。这可以用一个递归公式高效实现,无需存储所有历史参数:
\[\bar{\theta}_t = \bar{\theta}_{t-1} + \frac{1}{t - t_0 + 1}(\theta_t - \bar{\theta}_{t-1}) \]
这个公式表明,新的平均值是旧平均值与新迭代点的加权平均。另一种等价的实现方式是:在训练结束后,计算 $\bar{\theta} = \frac{1}{T - t_0 + 1} \sum_{t=t_0}^{T} \theta_t$。
- 输出:训练结束后,不是输出最后一次迭代的参数 \(\theta_{T+1}\),而是输出平均参数 \(\bar{\theta}_T\) 作为最终的模型参数。
步骤4:算法原理与收敛性分析
Polyak-Ruppert平均的强大之处有其坚实的理论基础。
-
对强凸光滑问题:对于强凸且光滑的目标函数,当SGD的学习率满足 \(\eta_t = O(1/t)\) 时,SGD本身的最优收敛率是 \(O(1/\sqrt{t})\)。然而,其平均序列 \(\{\bar{\theta}_t\}\) 能以 \(O(1/t)\) 的速率收敛到最优解 \(\theta^*\)。这是一个最优的收敛率,意味着迭代平均在期望上消除了梯度方差带来的影响,显著加快了收敛。
-
对非凸问题(深度学习场景):虽然在非凸问题上没有如此强的理论保证,但实践和大量研究表明,Polyak-Ruppert平均依然非常有效:
- 平滑解轨迹:平均操作相当于对训练后期的参数做了一个低通滤波,滤掉了高频振荡,保留了参数的长期趋势。这使得最终模型对训练末期的噪声不敏感,提高了鲁棒性。
- 更靠近平坦最小值:在深度学习领域,一个被广泛接受的观点是,位于“平坦”区域的局部最小值(损失函数地形平坦、Hessian矩阵特征值小)通常具有更好的泛化能力。参数的振荡会使搜索在平坦区域徘徊,对其进行平均,更容易“落在”这个平坦区域的中心,从而可能得到泛化性更好的模型。
-
与Polyak平均的对比:需要注意,存在两种Polyak平均:
- “标准”Polyak平均:常用于理论分析,需要知道最优值 \(J(\theta^*)\) 的下界,然后对满足一定条件的迭代点取平均。在深度学习中不实用。
- Polyak-Ruppert平均:即本算法,是一种简单、无需任何先验信息的、纯粹的遍历平均,直接在训练路径上做平均。由于其易用性,是深度学习中的主流实现。
步骤5:在深度学习中的实现技巧
- 学习率策略:为获得最佳效果,学习率 \(\eta_t\) 不应衰减过快。常见的策略是:在训练前期使用一个较大的常数学习率,在后期缓慢衰减(如 \(1/\sqrt{t}\))。这与很多SGD变体(如Cosine Annealing)配合得很好。
- 平均起始点 \(t_0\) 的选择:一个常用的经验法则是 \(t_0 = T/2\) 或 \(t_0 = 0.75T\)。过早开始平均(\(t_0\) 太小)可能会将初始阶段不稳定的参数包含进来,影响平均质量;过晚开始(\(t_0\) 太大)则可能样本点不足。在深度学习中,由于早期迭代远离最优点,通常从训练后半程开始平均。
- 内存与计算:在线平均公式 \(\bar{\theta}_t = \bar{\theta}_{t-1} + \frac{1}{t - t_0 + 1}(\theta_t - \bar{\theta}_{t-1})\) 只需维护一个额外的平均参数变量 \(\bar{\theta}\),与模型参数量相同,计算开销几乎可以忽略不计,是一种零额外成本的“技巧”。
- 与优化器的结合:Polyak-Ruppert平均可以与任何基于迭代的优化器结合,如SGD、Adam、RMSProp等。在Adam等自适应优化器上应用时,它同样能起到平滑最终解的作用。
- 最终模型保存:在PyTorch等框架中实现时,只需在训练循环中维护平均参数,并在训练结束后将模型的状态字典用平均参数覆盖即可。
总结:SGD with Polyak-Ruppert Averaging 通过一个极其简单的思想——对训练后期的模型参数取平均值,有效地平滑了优化过程中的随机振荡,使得最终模型能收敛到更稳定、更可能具有良好泛化能力的区域。其实现简单、开销极低,是一种在实践中被广泛验证能稳定提升最终模型性能的强大技术。