news 2026/2/27 23:41:17

机器学习算法:随机梯度下降算法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
机器学习算法:随机梯度下降算法

目录

动量法 是什么?

从数学上理解

案例:寻找最佳学习节奏

公式推导与解析

1. 基础梯度下降回顾

2. 引入动量项

3. 物理意义与优势

扩展:NAG (Nesterov Accelerated Gradient)

优缺点和适用场景

完整代码示例:在回归问题中对比SGD与动量法


有小伙伴在学优化算法时问,梯度下降已经有了随机版本,为什么还需要动量法?

它到底解决了什么问题?

今天,我们就来深入聊聊动量法(Momentum),看看它是如何让梯度下降变得更“聪明”、更稳定的。

首先,动量法是一种在梯度下降基础上引入“惯性”思想的优化算法。它的目标是加速收敛,并减少优化过程中的振荡,让参数更新更加平滑。

下面,我们从一个生活化的比喻开始,逐步展开。

动量法 是什么?

想象你在下山,目标是尽快到达山谷最低处。

普通的下山方式是:看眼前最陡的方向,直接迈一步。

  • 普通梯度下降(GD/SGD):就像每走一步都重新判断方向。如果地面坑洼不平(梯度有噪声),你的路径就会左摇右摆,走得很慢,甚至可能在沟壑里来回震荡。

  • 动量法(Momentum):给你一个带轮子的滑板。你当前要前进的方向,不仅由这一步看到的坡度决定,还会受到之前速度(动量)的影响。这样,在平缓地带你会加速,遇到反向坡度时,惯性也能帮你冲过去一部分,减少摆动,整体路径更平滑、更快地指向山谷。

从数学上理解

动量法旨在最小化目标函数 L(θ),其更新规则在梯度下降的基础上增加了动量项:

  • θ:模型参数。

  • ∇θL(θt):当前时刻的梯度。

  • η:学习率,控制当前梯度的影响。

  • β:动量系数(通常取0.9左右),控制历史动量(速度)的保留比例。

  • vt:当前时刻的更新速度,它累积了历史梯度的方向。

核心思想:当前的更新方向是“历史方向”与“当前梯度方向”的加权组合。这有助于在梯度方向连续一致的方向上加速,在梯度方向频繁变化的方向上抑制振荡。

案例:寻找最佳学习节奏

假设你在调整学习计划中“每日做题数”和“每日复习小时数”两个参数,目标是让学习效率最高。效率损失函数为:

理想状态是 题=20, 时=3,此时损失最小。

模拟计算(对比SGD和动量法)

为了对比,我们先看SGD的更新过程(学习率 η=0.1η=0.1):

  1. 初始化:题 = 5, 时 = 1。

  2. 计算梯度:∂L∂题=2(5−20)=−30∂题∂L​=2(5−20)=−30,∂L∂时=2(1−3)=−4∂时∂L​=2(1−3)=−4。

  3. SGD更新:题 = 5 - 0.1*(-30) = 8.0, 时 = 1 - 0.1*(-4) = 1.4。

接下来,我们使用动量法(设 β=0.9,η=0.1β=0.9,η=0.1):

  1. 初始化参数:题 = 5, 时 = 1。
    初始化速度:v题=0,v时=0v题​=0,v时​=0。

  2. 计算当前梯度(同上):g题=−30,g时=−4g题​=−30,g时​=−4。

  3. 更新速度:
    v题=0.9∗0+0.1∗(−30)=−3.0v题​=0.9∗0+0.1∗(−30)=−3.0
    v时=0.9∗0+0.1∗(−4)=−0.4v时​=0.9∗0+0.1∗(−4)=−0.4

  4. 更新参数:
    题 = 5 - (-3.0) = 8.0
    时 = 1 - (-0.4) = 1.4

第一步结果看似与SGD相同,因为初始速度为0。

进行第二步迭代:
当前参数:题=8.0, 时=1.4。

  1. 计算新梯度:
    g题=2(8.0−20)=−24.0g题​=2(8.0−20)=−24.0
    g时=2(1.4−3)=−3.2g时​=2(1.4−3)=−3.2

  2. SGD更新:题 = 8.0 - 0.1*(-24) = 10.4, 时 = 1.4 - 0.1*(-3.2) = 1.72。

  3. 动量法更新速度
    v题=0.9∗(−3.0)+0.1∗(−24.0)=−2.7−2.4=−5.1v题​=0.9∗(−3.0)+0.1∗(−24.0)=−2.7−2.4=−5.1
    v时=0.9∗(−0.4)+0.1∗(−3.2)=−0.36−0.32=−0.68v时​=0.9∗(−0.4)+0.1∗(−3.2)=−0.36−0.32=−0.68

  4. 动量法更新参数
    题 = 8.0 - (-5.1) = 13.1
    时 = 1.4 - (-0.68) = 2.08

对比可见:在第二步,动量法由于累积了第一步的梯度(速度-3.0),在参数“题”上的更新幅度(-5.1)远大于SGD的更新幅度(-2.4),从而更快地朝着最优值20靠近。这就是“动量”带来的加速效果。

公式推导与解析

1. 基础梯度下降回顾

标准梯度下降更新:
它只考虑当前时刻的梯度。

2. 引入动量项

为了模拟物理中的动量,我们引入速度变量 vt​,其更新是指数移动平均:

为了简化并与常见形式一致,令 α=η,并将(1−β)吸收进学习率或直接采用另一种常见表述:

参数更新为:

3. 物理意义与优势

将 vt 展开:

更新方向是当前梯度与历史梯度的加权和。越近的梯度权重越大。

  • 加速收敛:在损失函数曲面在某个方向持续下降(梯度方向一致)时,动量会不断累积,更新速度越来越快。

  • 抑制振荡:在梯度方向变化频繁(如峡谷形曲面)的方向上,正负梯度会部分抵消,使得更新幅度变小,路径更稳定。

扩展:NAG (Nesterov Accelerated Gradient)

动量法的一个改进版本是NAG,它“向前看”一步:

NAG先根据累积速度“预览”下一步的参数位置,然后计算该预览位置的梯度,再进行更新。

这使得它在面对即将变化的梯度时能更早地做出调整,理论上有更好的收敛性。

优缺点和适用场景

优点

  1. 加速收敛:在目标函数呈狭长峡谷状或存在平缓区域时,能显著加快训练速度。

  2. 减少振荡:平滑优化路径,使训练过程更稳定,有助于使用更大的学习率。

  3. 有助于跳出局部极小:动量带来的“惯性”可能帮助参数冲过一些狭窄的局部极小点。

缺点

  1. 引入超参数:需要调整动量系数 β,通常为0.9,但最优值可能因问题而异。

  2. 可能 overshooting:在极陡的梯度面前,过大的动量可能导致更新过头,在最优值附近震荡甚至发散。

适用场景

  1. 高维非凸优化:如深度学习,特别是网络层数较深时。

  2. 梯度噪声较大或方向不一致:当数据存在噪声或Mini-batch较小时,动量能起到平滑作用。

  3. 追求更快的训练速度:在资源有限的情况下,希望用更少的迭代次数达到可接受的损失。

完整代码示例:在回归问题中对比SGD与动量法

下面我们用一个简单的线性回归问题,来可视化对比普通SGD和带动量的SGD的优化轨迹。

import numpy as np import matplotlib.pyplot as plt # 1. 生成模拟数据 np.random.seed(42) # 真实参数:w_true = 2.5, b_true = 1.0 X = 2 * np.random.rand(100, 1) y = 2.5 * X + 1.0 + np.random.randn(100, 1) * 0.5 # 添加噪声 # 2. 定义损失函数(均方误差)和梯度 def compute_gradients(X, y, w, b): m = len(X) y_pred = X * w + b dw = (-2/m) * np.sum(X * (y - y_pred)) db = (-2/m) * np.sum(y - y_pred) return dw, db # 3. 定义优化器 def sgd_optimizer(w, b, dw, db, lr): w_new = w - lr * dw b_new = b - lr * db return w_new, b_new def momentum_optimizer(w, b, dw, db, lr, beta, v_w, v_b): v_w = beta * v_w + lr * dw v_b = beta * v_b + lr * db w_new = w - v_w b_new = b - v_b return w_new, b_new, v_w, v_b # 4. 训练参数设置 lr = 0.1 beta = 0.9 n_iterations = 50 # 初始化参数(两者起点相同) w_sgd, b_sgd = np.random.randn(2) * 5 # 随机初始化 w_mom, b_mom = w_sgd, b_sgd v_w, v_b = 0, 0 # 动量速度初始化为0 # 用于记录轨迹 path_sgd = [(w_sgd, b_sgd)] path_mom = [(w_mom, b_mom)] # 5. 执行训练 for i in range(n_iterations): # 计算梯度(使用全量数据简化演示) dw, db = compute_gradients(X, y, w_sgd, b_sgd) # SGD 更新 w_sgd, b_sgd = sgd_optimizer(w_sgd, b_sgd, dw, db, lr) path_sgd.append((w_sgd, b_sgd)) # 动量法更新 (需要重新计算当前参数的梯度) dw_m, db_m = compute_gradients(X, y, w_mom, b_mom) w_mom, b_mom, v_w, v_b = momentum_optimizer(w_mom, b_mom, dw_m, db_m, lr, beta, v_w, v_b) path_mom.append((w_mom, b_mom)) # 转换为数组方便绘图 path_sgd = np.array(path_sgd) path_mom = np.array(path_mom) # 6. 可视化优化轨迹 plt.figure(figsize=(12, 5)) # 子图1:参数空间轨迹 plt.subplot(1, 2, 1) # 绘制损失函数等高线(近似) W_grid, B_grid = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100)) Loss = np.zeros_like(W_grid) for i in range(W_grid.shape[0]): for j in range(W_grid.shape[1]): Loss[i,j] = np.mean((y - X * W_grid[i,j] - B_grid[i,j])**2) plt.contour(W_grid, B_grid, Loss, levels=30, alpha=0.5) plt.scatter(2.5, 1.0, c='red', s=100, marker='*', label='True Optimum (w=2.5, b=1.0)') plt.plot(path_sgd[:,0], path_sgd[:,1], 'o-', label='SGD Path', linewidth=2, markersize=4) plt.plot(path_mom[:,0], path_mom[:,1], 's-', label='Momentum Path', linewidth=2, markersize=4) plt.xlabel('Weight (w)') plt.ylabel('Bias (b)') plt.title('Optimization Path in Parameter Space') plt.legend() plt.grid(True, alpha=0.3) # 子图2:损失下降曲线 plt.subplot(1, 2, 2) loss_sgd = [np.mean((y - X * w - b)**2) for w, b in path_sgd] loss_mom = [np.mean((y - X * w - b)**2) for w, b in path_mom] plt.plot(range(len(loss_sgd)), loss_sgd, label='SGD Loss') plt.plot(range(len(loss_mom)), loss_mom, label='Momentum Loss') plt.xlabel('Iteration') plt.ylabel('Mean Squared Error Loss') plt.title('Loss Convergence Curve') plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show()

代码说明与结果解读:

  1. 左图(参数空间轨迹)

    • 背景等高线代表损失函数值,中心红五星为全局最优点。

    • SGD(圆点线)的更新路径曲折,呈“锯齿状”缓慢靠近最优点。

    • 动量法(方块线)的路径明显更加平滑、直接,更快地指向最优点,体现了动量在一致梯度方向上的加速效果。

  2. 右图(损失下降曲线)

    • 动量法(橙色)的损失值下降速度整体快于普通SGD(蓝色),尤其是在初期,收敛更快。

通过这个对比实验,可以直观地看到动量法如何优化梯度下降的过程,使其更高效、更稳定

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/26 14:24:15

从零搭建量子计算开发环境:镜像缓存构建的4个核心原则与实操技巧

第一章:量子计算开发环境概述量子计算作为下一代计算范式的前沿领域,其开发环境的搭建是进入该领域的第一步。与传统软件开发不同,量子计算依赖于特定的量子编程框架和模拟器,以支持量子比特操作、量子线路构建以及结果测量等核心…

作者头像 李华
网站建设 2026/2/25 19:07:33

针对一个嵌入式AI视觉http后端系统的设计

AI视觉后端系统详细设计文档 个人专著《C++元编程与通用设计模式实现》由清华大学出版社出版。该书内容源于工业级项目实践,出版后市场反馈积极(已加印)。其专业价值获得了图书馆系统的广泛认可:不仅被中国国家图书馆作为流通与保存本收藏,还被近半数省级公共图书馆及清华…

作者头像 李华
网站建设 2026/2/18 23:59:48

HTTP 无状态与 Cookie 状态保持机制详解

HTTP 无状态与 Cookie 状态保持机制详解 一、背景:HTTP 真的是“无状态”吗? HTTP 被称为无状态协议,并不是说它完全无法“记住”用户,而是: 每一次 HTTP 请求在协议层面都是相互独立的服务器不会天然保存客户端的上下…

作者头像 李华
网站建设 2026/2/26 18:09:18

计算机网络基础

网络定义 多台设备通过连接介质,能互相传数据,共享资源的集合 协议:设备之间的沟通规则 拓扑结构 网络设备的物理连接方式 星型:就是有一个中间的设备转一下 总线型:学校机房那种所有设备连着一台设备 环型&#xff1a…

作者头像 李华
网站建设 2026/2/25 16:08:18

AI智能体(Agent)开发全攻略:概念、设计到安全运行,程序员必学

本文详解AI智能体的本质区别、三大核心特征及落地路径,涵盖模型选型、工具定义、指令配置等关键组件,解析单智能体与多智能体编排模式,并强调安全护栏体系的重要性,为开发者提供从0到1构建智能体的完整路线图,助力抢占…

作者头像 李华
网站建设 2026/2/25 18:26:54

LLM RAG开发进阶:多查询检索技术详解与实战代码

本文详细介绍了LLM应用中RAG开发的三个关键步骤和六个优化阶段,重点阐述了多查询检索策略如何提升检索准确性。通过生成多个角度的子问题进行检索并合并结果,有效克服传统相似性搜索的局限。文章提供了LangChain中MultiQueryRetriever的具体实现代码和优…

作者头像 李华