You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从零实现的MNIST分类ANN中Momentum梯度下降失效问题排查

问题原因分析及排查方向

1. 学习率未适配动量机制

动量的核心是累积历史梯度,会放大参数更新的有效步长。当momentum=0.9时,有效学习率相当于 Vanilla GD 的 1/(1-momentum)=10倍左右。如果仍使用原来适合 Vanilla GD 的学习率,参数更新幅度过大,会直接越过最优解,甚至导致模型发散,表现为损失骤增、准确率暴跌。

排查/解决:将学习率缩小至原来的 1/5~1/10(比如原学习率是0.1,就改成0.01),再重新训练观察效果。

2. 动量更新逻辑实现错误

标准动量更新的公式是:

# 初始化动量缓存(与参数同形状的零数组)
v_w1 = np.zeros_like(w1)
v_b1 = np.zeros_like(b1)
v_w2 = np.zeros_like(w2)
v_b2 = np.zeros_like(b2)

# 每轮参数更新
v_w1 = momentum * v_w1 + learning_rate * dw1
w1 -= v_w1
v_b1 = momentum * v_b1 + learning_rate * db1
b1 -= v_b1
# 输出层参数同理
v_w2 = momentum * v_w2 + learning_rate * dw2
w2 -= v_w2
v_b2 = momentum * v_b2 + learning_rate * db2
b2 -= v_b2

常见错误:

  • 错误地将学习率重复相乘,比如写成 w1 -= learning_rate * (momentum * v_w1 + dw1),这会让有效步长变成 learning_rate*(momentum*历史步长 + 梯度),和标准公式的 momentum*历史步长 + learning_rate*梯度 完全不同。
  • 动量缓存被错误重置(比如把初始化代码放在训练循环内部,导致每轮都从零开始累积动量)。

3. 梯度爆炸或数值计算不稳定

ReLU 激活层如果参数初始化过大,会导致大量神经元输出饱和,梯度值异常庞大;加上动量的累积效应,参数更新会越来越极端,最终引发数值溢出(比如损失变为无穷大)。另外,softmax 与交叉熵的计算如果没做数值稳定,也会在模型发散时出现异常。

排查点:

  • 训练时打印各层梯度的 L2 范数,如果梯度范数突然飙升至 1e3 以上,说明存在梯度爆炸。
  • 检查 softmax 实现是否做了数值稳定处理:
def softmax(x):
    # 减去最大值避免指数运算溢出
    x_stable = x - np.max(x, axis=1, keepdims=True)
    exp_x = np.exp(x_stable)
    return exp_x / np.sum(exp_x, axis=1, keepdims=True)

4. 参数初始化不合理

针对 ReLU 激活的隐藏层,若使用过大的初始化标准差(比如直接用 np.random.randn 默认的标准差1.0),会导致神经元输出过大,梯度被放大。Vanilla GD 可能靠小步长慢慢修正,但动量会加速这种不稳定,直接引发发散。

解决:改用 He 初始化(适配 ReLU):

hidden_size = 你的隐藏层节点数
# He初始化:标准差 = sqrt(2 / 输入维度)
w1 = np.random.randn(784, hidden_size) * np.sqrt(2 / 784)
w2 = np.random.randn(hidden_size, 10) * np.sqrt(2 / hidden_size)

5. 数据预处理不一致

虽然 Vanilla GD 时表现正常,但如果训练集和验证集的预处理流程不一致(比如训练集做了归一化,验证集没做),动量加速后的模型会更快暴露这种问题,导致验证集性能暴跌。

排查:检查训练、验证阶段的数据加载、归一化等逻辑是否完全一致。

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:01:03