想象你被困在雾气弥漫的深山里,天黑前必须下山。你看不清整座山的全貌,只能凭脚下的坡度判断方向——哪边陡就往哪边挪一步。山的海拔叫“损失”,你站的位置叫“参数”,而“沿着最陡方向往下走”这件事,在机器学习里叫梯度下降。问题是,山里藏着无数溪水冲刷出的 V 形深谷,轻装上阵的小石子会在陡壁之间来回弹跳,半天挪不动地方。有经验的向导会搓一个大雪球,让雪球带着自己往下滚:雪球越滚越大、越滚越快,小坑小坎直接碾过去,方向也不会被轻易带偏。动量法(Momentum)就是给优化器装上这个“雪球”:它记住历史梯度的方向,把来回震荡相互抵消,让认准的方向越走越快。这篇文章沿着这条下山路,把动量法的直觉、公式、流程和 PyTorch 实现一次讲透。

岗位关联

优化器是深度学习训练的“方向盘”,理解 SGD+Momentum 的物理直觉与代码细节,是复现论文、调参加速的基础能力,也是面试中的高频考点。

目录
  1. 可视化演示
  2. 优化器简介
  3. SGD存在问题
  4. 动量核心思想
  5. 数学公式推导
  6. 算法执行流程
  7. 超参数与调优
  8. PyTorch实现
  9. 变体与效果对比
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

在损失函数等高线图上对比标准SGD(红色虚线,震荡)与SGD+Momentum(青色实线,平滑)的收敛轨迹,展示动量法如何加速收敛并减少震荡。

本节配有交互动效(进入视口后自动加载,约 3KB)。

SGD+Momentum优化器 SGD(红色虚线):沿梯度方向直接更新,在狭长山谷中产生ZigZag震荡 Momentum(青色实线):累积历史梯度方向v=βv+η∇L,加速收敛并减少震荡 v_t = β·v_{t-1} + η·∇L(θ); θ = θ - v_t

优化器简介

想象你被困在雾气弥漫的山里,任务是天黑前下山。你看不清整座山的全貌,只能凭脚下的坡度判断方向——哪边陡就往哪边挪一步。山的海拔是“损失”,你站的位置是“参数”。机器学习里的“训练”,本质上就是在这样一座抽象的山上寻找最低点:最低点处的参数,能让模型在数据上的表现最好。这个寻找过程,就叫优化(optimization),而负责迈步子的算法,就是优化器(optimizer)。

沿着最陡的方向走,是最朴素也最重要的策略,它有个专门的名字:梯度下降(Gradient Descent)。每一次你都会算出一个梯度——它告诉你“海拔上升最快”的方向,然后朝它的反方向迈一步。迈步的幅度大小叫学习率(learning rate, η):步子太大,可能一步跨过谷底在对面摔一跤;步子太小,天黑了还在半山腰磨蹭。

标准随机梯度下降(SGD)把这一套写成简洁的迭代公式:

如果山势像一口圆滑的碗,这套方法已经够用。可惜真实世界的高维损失面从来不是温顺的碗,而是布满沟壑、溪谷和碎石坡的荒山。轻装上阵的小石子走到这里,麻烦才刚刚开始——这正是标准 SGD 的窘境。

θt+1=θt−η ∇L(θt)\displaystyle \theta_{t+1} = \theta_t - \eta\, \nabla L(\theta_t)
  1. 参数 θθ 是模型全部参数的集合,θ_t 表示第 t 步迭代时参数的当前位置,相当于你此刻在山上的坐标。
    θt∈Rd\theta_t \in \mathbb{R}^d
  2. 梯度 ∇L(θ_t)损失函数 L 在当前位置的梯度,是一个向量,指向“海拔上升最快”的方向,因此更新时要加负号。
    ∇L(θt)=(∂L∂θ1,∂L∂θ2,…,∂L∂θd)\nabla L(\theta_t) = \left( \frac{\partial L}{\partial \theta_1}, \frac{\partial L}{\partial \theta_2}, \dots, \frac{\partial L}{\partial \theta_d} \right)
  3. 学习率 η一个正数,控制每次迈步的步长,η 越大步子越猛,越小步子越稳。
    η>0\eta > 0
  4. 一次迭代从当前位置减去“步长 × 上升方向”,得到下一步的新位置,如此循环直到抵达谷底。
    θt+1=θt−η ∇L(θt)\theta_{t+1} = \theta_t - \eta\, \nabla L(\theta_t)

SGD存在问题

你顺着溪水声走到一条被冲刷出的 V 形深谷:谷底窄、两壁陡。脚下的坡度在左右方向剧烈变化,沿谷底延伸的方向却几乎平缓。小石子在这里会怎样?它沿着陡壁被推过来、推过去,每一步都在左右横跳,真正朝谷底出口方向的前进却微乎其微——看起来忙忙碌碌,实际原地打转。

这个地形在深度学习里叫“病态曲率”:损失函数在某个方向变化极快(曲率大),在另一个方向变化极慢(曲率小)。标准 SGD 用同一个学习率应对所有方向,步子只能向最陡峭的方向妥协,于是出现三个典型问题:

1. 震荡严重:在陡峭方向来回摆动,轨迹呈剧烈锯齿状,如图表动效中红色路径所示,每一份“力气”都被左右横跳抵消大半。

2. 收敛缓慢:有效前进距离被来回摆动抵消,明明走了一百步,实际位移却只有十步,训练时间成倍拉长。

3. 局部极小与鞍点:山坡上有些浅浅的小坑(局部极小)和一片片平坦的鞍部(鞍点),在这些位置梯度接近零,小石子失去方向感,被永远困住。

轻石子的问题在于“没记性”——它完全不记得自己刚才从哪个方向来,每一次迈步都只看当下这一脚。如果让石子带上一点“记性”,把之前走过的方向也纳入判断,情况会不会完全不同?

动量核心思想

有经验的登山向导不会用轻石子开路,而是先搓一个大雪球。雪球在滚动中把一路上的新雪(新梯度)裹进身体,攒下厚厚的历史(过去的梯度信息)。遇到小凸起,雪球靠惯性碾过去;方向需要转弯时,笨重的雪球也不会猛地漂移。更妙的是:如果风一直从背后吹(梯度方向一致),雪球越滚越快;如果风忽左忽右(梯度来回变号),力量在雪球内部相互抵消,左右摇摆的幅度被平均掉。

动量法(Momentum)把这套物理直觉完整搬进了优化器。它不再让参数直接跟随“当前的瞬时梯度”移动,而是维护一个额外的速度向量 v,每一轮迭代做两件事:第一,把当前算出的梯度作为一股新推力,加入速度;第二,让旧速度按一个折扣系数保留下来,相当于雪球的惯性。最终,参数沿着速度方向移动——速度是历史与当下共同作用的结果。

具体来说,动量法有三个关键设计:

  • 速度向量 v:记录“雪球当前朝哪个方向冲、冲得多快”,维度与参数相同。
  • 历史梯度累积:速度的构成是“旧速度打折扣 + 新梯度”,数学上等价于把过去若干步的梯度按指数衰减的权重加在一起。
  • 指数衰减:越久远的梯度权重越小,就像雪球滚动时不断甩掉最外层的旧雪,保证它能及时适应地形的新变化,而不是死守一条过时的路。

这份“记性”就是雪球与石子的分水岭:石子每一步都被局部地形支配,雪球则用整段下坡路的经验做决策。那么,这份记忆到底如何写进公式?

数学公式推导

把雪球的两条规则翻译成数学,就是动量法的全部。规则一:更新速度——旧速度打 γ 折,加上新梯度的推力;规则二:更新参数——沿速度方向迈一步。先看速度更新式:

有了速度,参数更新式就顺理成章:

展开式揭示了一个关键信息:γ=0.9 时,历史梯度的有效记忆窗口约为 1/(1−γ)=10 步;γ=0.99 时则拉长到约 100 步。调 γ 就是在调雪球“有多念旧”——记性太长,地形陡变时转不过弯;记性太短,又失去了惯性带来的平滑。

vt=γ vt−1+∇L(θt)\displaystyle v_t = \gamma\, v_{t-1} + \nabla L(\theta_t)
  1. 参数更新参数朝速度的反方向移动,因为速度的累积来源是“上升方向”,所以取负号。
    θt+1=θt−η vt\theta_{t+1} = \theta_t - \eta\, v_t
  2. η 的位置注意学习率 η 乘在整个速度上,而不是只乘当前梯度——最终步长由历史累积速度决定,这正是动量与普通 SGD 最直观的差异。
    Δθt=−η vt\Delta \theta_t = - \eta\, v_t

算法执行流程

雪球滚下山不是魔法,每一步都是固定的四拍:看清方向、记住来路、迈出步子、站稳后再看下一眼。动量法的训练循环也一样,是一个周而复始的固定流程:

1. 初始化:随机初始化参数 θ,并将速度向量 v 全部置零——雪球起步时是静止的。

2. 前向计算:用当前参数在训练数据上算一次预测,得到损失 L(θ)。

3. 反向求梯度:通过反向传播计算出损失对每个参数的梯度 ∇L(θ)。

4. 更新速度:执行 $v \leftarrow \gamma v + \nabla L(\theta)$,把新推力揉进旧速度。

5. 更新参数:执行 $\theta \leftarrow \theta - \eta v$,沿速度方向真正迈出一步。

6. 循环判断:回到第 2 步,直到损失收敛或达到预设的训练轮数。

与标准 SGD 相比,动量法只多维护了一个与参数同形状的速度向量 v,内存开销几乎可以忽略,代码也只多了两行。这正是动量法性价比极高的原因:几乎零成本,换来收敛速度和稳定性的双重提升。

如果只记住一句话,那就是:标准 SGD 用“瞬时梯度”迈步,动量法用“历史加权的速度”迈步。前者是被地形牵着鼻子走的小石子,后者是认准方向就停不下来的雪球。

超参数与调优

雪球能不能又快又稳地下山,取决于两件事:雪球裹得有多大(动量系数 γ),以及推它的力气有多大(学习率 η)。这两个超参数相互缠绕,是调参时的核心对象。

  • 动量系数 γ:默认值 0.9。γ 越大,记忆越长、速度累积越猛、越能碾过小坑,但转弯越困难,过大容易冲过最优点后在谷底绕圈,甚至发散。0.99 适合梯度噪声大、需要长时间平滑的场景。
  • 学习率 η 与 γ 配合:加入动量后有效步长变大,常见做法是保持原学习率或适当降低。二者同时调大极易发散——好比雪球本来就重,还越推越猛,直接冲下山坡。
  • 常见设置:图像分类任务中,CNN 常用 lr=0.1、γ=0.9 并配合余弦退火或阶梯式学习率衰减;训练初期可加 warmup,让学习率从零逐渐爬升,相当于让雪球先慢悠悠起步,再越滚越快。
  • 调参经验:如果损失曲线锯齿明显、下降迟缓,优先加大或加入动量,而不是一味调低学习率;如果曲线发散震荡,先降低学习率,再尝试减小 γ。动量是“治震荡”的药,学习率是“控步幅”的闸,两者要协同调整。

换回雪球的比喻:γ 决定雪球“多念旧”,η 决定每次“推多用力”。老练的向导从来不会只调其中一个——他先观察雪球是横跳(调 γ)还是冲过头(调 η),再对症下药。

PyTorch实现

在 PyTorch 里给 SGD 裹上雪球,只需一行代码:torch.optim.SGD 中传入 momentum 参数。它默认是 0,表示纯标准 SGD;设为 0.9 就开启了动量法。

训练循环里几个 API 各司其职:

  • optimizer.zero_grad():把参数上的 .grad 属性清零,避免上一步的梯度与当前叠加。注意它不会清空优化器内部的动量速度。
  • loss.backward():反向传播,把损失对每个参数的梯度写入 param.grad。
  • optimizer.step():优化器的核心动作,内部对每个参数完成动量更新:先更新速度缓冲,再更新参数。

同一个类里还内置了 dampening(速度衰减的阻尼项)与 nesterov(Nesterov 动量开关),让实现细节全部收敛在一个 API 里。初学时建议自己动手对照公式写一遍手动的动量更新,再去用封装好的 torch.optim.SGD,这样对“优化器内部到底做了什么”才有实感。后面的 Python 演示部分,会给出一个可运行的手写版与 PyTorch 版对比实验。

python10 行
import torch optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9) for x_batch, y_batch in loader:    optimizer.zero_grad()          # 清空上一步的梯度 .grad    pred = model(x_batch)          # 前向计算    loss = criterion(pred, y_batch)  # 计算损失    loss.backward()                # 反向传播, 算出各参数梯度    optimizer.step()               # 内部执行 v = γv + g; θ = θ - ηv

变体与效果对比

雪球有了惯性之后,还有没有更聪明的滚法?Nesterov 提出:与其到了位置再闷头推,不如先探头看看前方一步的坡度——这就叫 Nesterov 动量(NAG)。它的速度更新式变成:

把目光放远一点,动量家族之外还有 Adam 等自适应优化器:Adam 为每个参数单独维护自适应学习率,训练初期稳、对学习率不敏感;而 SGD+Momentum 所有参数共享同一个学习率,看似“笨”,却在图像分类等任务上往往取得更好的泛化性能。因此在 CV 领域,SGD+Momentum 仍是众多论文的标准配置。

从收敛曲线看,标准 SGD 是锯齿状的缓慢爬行,动量法是平滑的加速冲刺——通常以更少的迭代到达更低的损失,且曲线更平稳。这正是山下那幅图景的完整版:轻石子左冲右撞,大雪球一往无前。

vt=γ vt−1+η ∇L(θt−γ vt−1)\displaystyle v_t = \gamma\, v_{t-1} + \eta\, \nabla L\left(\theta_t - \gamma\, v_{t-1}\right)
  1. 前瞻位置先用旧速度“预演”一步,得到前瞻位置 $\theta_t - \gamma v_{t-1}$,相当于雪球探头看看前方。
    θt−γ vt−1\theta_t - \gamma\, v_{t-1}
  2. 前瞻梯度在预演位置计算梯度,而不是在当前参数位置——提前感知前方坡度,避免冲过头后才反应。
    ∇L(θt−γ vt−1)\nabla L\left(\theta_t - \gamma\, v_{t-1}\right)
  3. 更新用前瞻梯度更新速度,参数仍沿速度方向移动,整体比标准动量更稳、收敛略快。
    θt+1=θt−vt\theta_{t+1} = \theta_t - v_t

AI 应用场景

ResNet 图像分类训练(CV 标准配置)

阶段:模型训练

解决的问题:图像分类网络的损失面充满狭长山谷,纯 SGD 震荡严重、收敛缓慢,手动调小学习率又拖慢整体进度。SGD+Momentum 用 0.9 的动量系数平滑震荡,让训练在合理时间内稳定收敛到可用精度。

具体案例:在 CIFAR-10 上训练 ResNet-18 时,使用 lr=0.1、momentum=0.9、weight_decay=5e-4 的标准配方,配合阶梯式学习率衰减,约 160 个 epoch 即可达到 95% 左右的测试精度;若去掉动量,同样的学习率下损失曲线锯齿明显,收敛 epoch 几乎翻倍。

大规模分布式训练中的通信平滑

阶段:分布式训练/系统优化

解决的问题:分布式训练中,每轮梯度需要在多卡之间做 all-reduce 通信,梯度方向来回震荡会浪费通信带宽、拖慢整体收敛。动量法累积历史梯度后,送往通信的梯度方向更加稳定,相当于在源头做了“信号平滑”。

具体案例:在 8 卡 GPU 上同步训练分类模型时,启用 momentum=0.9 后,梯度在两次同步之间的方向一致性明显提升,通信量不变但收敛步数减少约 20%,训练吞吐与精度的平衡显著改善。

人脸识别模型的度量学习训练

阶段:模型训练(度量学习)

解决的问题:人脸识别常用三元组损失或 ArcFace 训练,嵌入空间的优化对稳定性要求极高,参数稍一震荡就会破坏类间距离的度量结构。SGD+Momentum 的平滑更新能稳定地推进嵌入空间的分离。

具体案例:FaceNet 等经典人脸识别模型在训练时采用 SGD 配合动量,设定 lr=0.1、momentum=0.9,在千万级人脸数据上稳定收敛,最终在 LFW 等评测集上达到 99% 以上的准确率。

Python 演示

python43 行
import numpy as npimport torchimport torch.nn as nn torch.manual_seed(0) # 1) 手写动量法, 在长条形山谷地形上对比有无疑问def momentum_descent(theta0, mu, lr=0.3, steps=50):    theta = theta0.copy()    v = np.zeros_like(theta)    path = [theta.copy()]    for _ in range(steps):        g = np.array([0.02 * theta[0], theta[1]])  # 山谷: y 方向陡峭        v = mu * v + g           # 核心第 1 步: 速度累积        theta = theta - lr * v   # 核心第 2 步: 参数沿速度走        path.append(theta.copy())    return np.array(path) start = np.array([-8.0, 3.0])p_sgd = momentum_descent(start, 0.0)   # 无动量p_mom = momentum_descent(start, 0.9)   # 带动量print("SGD 终点:", np.round(p_sgd[-1], 3))print("MOM 终点:", np.round(p_mom[-1], 3)) # 2) PyTorch 版: 线性回归训练, 对比有无动量x = torch.linspace(-1, 1, 64).reshape(-1, 1)y = 2 * x + 1 + 0.1 * torch.randn_like(x) def train(momentum):    model = nn.Linear(1, 1)    opt = torch.optim.SGD(model.parameters(), lr=0.05, momentum=momentum)    loss_list = []    for _ in range(200):        pred = model(x)        loss = ((pred - y) ** 2).mean()        opt.zero_grad()        loss.backward()        opt.step()        loss_list.append(loss.item())    return loss_list[-1] print("SGD 最终 loss:", round(train(0.0), 5))print("MOM 最终 loss:", round(train(0.9), 5))
目的:先用手写方式在长条形山谷上演示动量更新的两行核心代码,再用 PyTorch 自带 torch.optim.SGD 在真实线性回归任务上对比有无动量的收敛效果。
  1. g = np.array([0.02 * theta[0], theta[1]])构造一个“山谷地形”:y 方向梯度大、x 方向梯度小,模拟病态曲率。
  2. v = mu * v + g动量核心第一行:旧速度打折扣,再加上新梯度推力。
  3. theta = theta - lr * v动量核心第二行:参数沿累积速度走,而非瞬时梯度。
  4. opt = torch.optim.SGD(model.parameters(), lr=0.05, momentum=momentum)PyTorch 一行创建 SGD,momentum 传 0.9 即为动量法。
  5. opt.zero_grad()只清空参数上的 .grad,不影响优化器内部速度。
  6. loss.backward()反向传播计算当前梯度。
  7. opt.step()优化器内部完成速度更新与参数更新。

常见误区

误区“momentum 从 0.9 调到 0.99,惯性更猛,收敛肯定更快。”

正解γ 越大记忆越长,转向越困难,参数容易冲过最优点后绕着谷底绕圈,学习率稍不配合就会直接发散。雪球裹得太大,遇到需要急转弯的地形反而停不下来。0.9 是久经考验的基线,调参时应与学习率协同小幅尝试,而不是单方拉满。

为何常见:“惯性越大速度越快”的生活直觉太强,忽略了动量法依赖 γ<1 提供阻尼、依赖 η 控制步幅这一整套配合。

误区“反正最后都收敛到同一个最低点,动量只是跑得快一点,最终模型精度没差别。”

正解动量改变的是整条训练轨迹,不同轨迹会落入不同的局部极小,泛化性能随之不同。实践中 SGD+Momentum 在图像分类上常比很多“更快”的优化器取得更好的测试精度——终点与路径有关,雪球滚过的路线决定了它最后停在哪里。

为何常见:教材里的收敛图通常只画 loss 下降,让人误以为所有优化器殊途同归,忽略了轨迹对泛化的影响。

误区“速度公式里乘了 η,那我把 η 调大,效果不就和加动量一样?”

正解η 只放大“当前这一步梯度”的推力,γ 放大的是“整段历史梯度”的权重。在震荡方向上梯度正负交替,调大 η 会同步放大每一步的横跳;而 γ 让正负历史相互抵消,二者数学角色完全不同。雪球的“个头”(γ)和“推力”(η)是两码事。

为何常见:速度和参数两个公式里各有一个系数,初学者容易望文生义,把它们混为一谈。

误区“每次迭代都要 zero_grad 清空梯度,那优化器维护的动量速度肯定也被清零了吧?”

正解zero_grad() 只把参数的 .grad 属性归零,优化器内部的动量缓冲(速度向量)在 step() 之间持续保留。如果每次迭代都清零速度,动量就名存实亡,雪球永远没法“越滚越大”。

为何常见:“清零”两个字太宽泛,初学者没有区分“计算图上的梯度”与“优化器内部维护的状态”这两套完全不同的存储。

面试题

Q1. 动量法能够缓解标准 SGD 在山谷中来回震荡,其根本原因是?

单选题 · easy

  • A.增大了每一步梯度的强度
  • B.累积了历史梯度的方向信息← 正确答案
  • C.减少了参与计算的训练样本
  • D.提高了损失函数的平滑程度

答案:B。动量法维护速度向量,等价于对历史梯度做指数加权求和。方向一致的梯度被累积放大,方向来回变化的梯度相互抵消,从而抑制震荡。增大梯度强度、减少样本、平滑损失都不是动量的机制。

Q2. 标准 SGD 在狭长山谷地形中收敛缓慢,直接表现为?

单选题 · easy

  • A.梯度在每一步都完全消失不见了
  • B.学习率被网络层数自动摊薄了
  • C.陡峭方向来回震荡而平缓方向龟速← 正确答案
  • D.损失值在训练一开始就发散了

答案:C。狭长山谷意味着一个方向曲率大、另一个方向曲率小,同一个学习率只能迁就陡峭方向,于是陡峭方向来回摆动、平缓方向几乎不动,这正是标准 SGD 的病态曲率困境,与梯度消失、层数摊薄无关。

Q3. 当动量系数 γ=0.9 时,历史梯度的有效记忆窗口约为多少步?

单选题 · mid

  • A.大约 1 步以前的梯度
  • B.大约 10 步以前的梯度← 正确答案
  • C.大约 100 步以前的梯度
  • D.大约 1000 步以前的梯度

答案:B。速度展开式中历史梯度权重按 γ^k 指数衰减,有效记忆窗口约为 1/(1−γ)=1/(1−0.9)=10 步。γ=0.99 时才接近 100 步,1 步则等于没有动量。这道题考的是“指数衰减窗口”的量化直觉。

Q4. 在 PyTorch 中构造带动量的 SGD 优化器,正确的写法是?

单选题 · mid

  • A.optim.SGD(params, lr=0.1, momentum=0.9)← 正确答案
  • B.optim.SGD(params, lr=0.1, alpha=0.9)
  • C.optim.SGD(params, lr=0.1, beta=0.9)
  • D.optim.SGD(params, lr=0.1, decay=0.9)

答案:A。PyTorch 的 torch.optim.SGD 使用 momentum 关键字传入动量系数,默认值为 0。alpha、beta 是 Adam 等其他优化器的参数命名,decay 常指权重衰减,都不是动量参数。

Q5. 与标准 SGD 相比,动量法带来的改进包括哪些?

多选题 · mid

  • A.减少梯度方向的来回震荡← 正确答案
  • B.平坦区域也能积累前进速度← 正确答案
  • C.完全可以避开所有局部极小
  • D.不再需要设置任何超参数了

答案:AB。动量通过历史梯度累积实现“同向加速、反向抵消”,既缓解震荡,又能在平坦区域让速度逐渐积攒起来。但它既不能保证跳出所有局部极小,也不能免除学习率和动量系数等超参数设置。

Q6. Nesterov 动量与标准动量最大的区别在于?

单选题 · mid

  • A.先到前瞻位置再计算梯度← 正确答案
  • B.每次使用两倍学习率更新
  • C.梯度计算前先做数据增强
  • D.使用二阶导数修正更新方向

答案:A。Nesterov 动量先用当前速度“预演”一步,在前瞻位置计算梯度,相当于提前感知前方坡度;标准动量在当前参数位置计算梯度。它不改变学习率、不做数据增强,也不使用二阶导数。

Q7. 动量法中的速度向量 v 通常初始化为?

单选题 · easy

  • A.与第一个梯度相等的向量
  • B.随机生成的小数值向量
  • C.所有分量均为零的向量← 正确答案
  • D.单位长度的固定方向向量

答案:C。训练开始时雪球应该是静止的,因此速度向量初始化为全零。若初始化为第一个梯度、随机值或单位向量,都会给优化引入人为的初始方向偏差,破坏动量“从零累积”的设计。

Q8. 关于动量系数 γ 的调参说法,正确的有?

多选题 · hard

  • A.γ 越大历史梯度影响越持久← 正确答案
  • B.γ 过大会导致参数冲过头← 正确答案
  • C.γ 必须严格小于学习率 η
  • D.实践中常从 0.9 附近起步← 正确答案

答案:ABD。γ 越大记忆窗口越长,累积速度越猛,也就越容易冲过最优点。0.9 是广泛使用的经验基线。γ 与 η 的取值范围和含义完全不同,没有“必须小于”的约束关系,故 C 错。

Q9. 标准 SGD 一次迭代的参数更新公式是?

单选题 · mid

  • A.θ 减去 η 与梯度的乘积← 正确答案
  • B.θ 加上 η 与梯度的乘积
  • C.θ 减去梯度与 η 的商
  • D.θ 加上梯度与 η 的商

答案:A。梯度指向损失上升最快的方向,参数应朝反方向更新,即 θ←θ−η∇L(θ)。B 会让损失增大,C、D 把乘法换成除法且方向错误,均不符合梯度下降的定义。

Q10. 在 PyTorch 官方训练循环中,关于动量机制的说法正确的是?

多选题 · hard

  • A.backward() 算出当前梯度← 正确答案
  • B.step() 内部更新速度参数← 正确答案
  • C.zero_grad() 只清空参数梯度← 正确答案
  • D.动量速度每轮都会被重置为零

答案:ABC。backward() 计算梯度写入 .grad,step() 在优化器内部完成 v=γv+g 与 θ=θ−ηv,zero_grad() 只清 .grad 不清动量缓冲。动量速度跨迭代持续保留,否则累积无从谈起,故 D 错。