梯度下降算法比较:SGD、Momentum、Adam在AI中的应用

梯度下降算法比较:SGD、Momentum、Adam在AI中的应用

关键词:梯度下降、随机梯度下降(SGD)、动量优化(Momentum)、Adam优化器、人工智能训练

摘要:在人工智能(尤其是深度学习)的世界里,“训练模型"就像教小机器人学习本领——需要不断调整它的"大脑参数”,让它越来越聪明。而调整参数的核心工具,就是今天要讲的"梯度下降家族"。本文将用通俗易懂的语言,结合生活案例、数学公式和代码实战,对比SGD(随机梯度下降)、Momentum(动量优化)、Adam(自适应矩估计)三种经典算法,帮你搞清楚它们的原理、优缺点和适用场景。


背景介绍:为什么需要梯度下降?

想象你在玩一个叫"参数调优"的游戏:你有一个小机器人(模型),它的"大脑"里有很多旋钮(参数),每个旋钮转一点,机器人的表现(比如识别图片的准确率)就会变化。你的目标是找到一组旋钮位置,让机器人表现最好。

但问题是:旋钮数量可能有成千上万个(比如深度学习模型的参数),直接暴力试所有组合是不可能的。这时候,梯度下降就像一个"智能指南针",能帮你快速找到最优的旋钮位置。

目的和范围

本文聚焦"梯度下降家族"中最常用的三种算法:SGD(基础款)、Momentum(带惯性的升级款)、Adam(带智能加速的旗舰款)。我们会从原理、数学公式、代码实现、实际效果四个维度对比,帮你在实际项目中选对工具。

预期读者

  • 对AI/深度学习感兴趣的初学者(懂基础Python和导数即可)
  • 正在训练模型但遇到"收敛慢""震荡"问题的开发者
  • 想深入理解优化算法底层逻辑的进阶学习者

文档结构概述

本文将按照"故事引入→核心概念→数学原理→代码实战→应用场景"的顺序展开。你会先通过生活案例理解抽象概念,再通过公式和代码掌握细节,最后学会根据需求选择算法。

术语表(用小学生能懂的话)

  • 梯度:可以想象成"下山的方向"。在数学里,梯度是函数上升最快的方向,取反就是下降最快的方向(我们要最小化损失函数,所以用负梯度)。
  • 学习率(η):“每一步跨多大”。太大容易跨过山脚(震荡),太小会走得慢(收敛慢)。
  • 损失函数(J):“机器人当前表现有多差”。我们的目标是让J尽可能小。
  • 参数(θ):“机器人的旋钮”。比如线性回归的斜率和截距,神经网络的权重和偏置。

核心概念与联系:从"下山"到"智能导航"

故事引入:三个小朋友的下山比赛

假设有三个小朋友要从山顶(初始参数)下到山谷(最优参数),山谷里藏着宝藏(最小损失)。他们的下山方式不同,对应三种梯度下降算法:

  1. 小明(SGD):每走一步都要停下来,仔细看脚下的坡度(计算当前点的梯度),然后朝着最陡的下坡方向走一步(学习率大小)。
  2. 小红(Momentum):不仅看当前坡度,还会记住之前走的方向(动量),像滑滑梯一样带着惯性走——如果之前一直往右下方走,即使现在坡度稍微变平,也会继续往右下方多走一点。
  3. 小刚(Adam):不仅带惯性,还会用智能手表记录自己每一步的步长(二阶矩),自动调整下一步该跨多大——如果之前经常小步走(梯度变化小),就跨大一点;如果之前经常乱跳(梯度变化大),就跨小一点。

核心概念解释(像给小学生讲故事)

1. SGD(随机梯度下降):一步一探的"谨慎者"

SGD的全称是Stochastic Gradient Descent(随机梯度下降)。这里的"随机"不是随便走,而是"随机选一个数据点计算梯度"(传统梯度下降用所有数据计算梯度,SGD用单个数据,速度更快)。

生活类比:你在一个黑黢黢的山洞里下山(损失函数曲面复杂),手里只有一个手电筒(只能看到一个数据点的梯度)。每走一步,你用手电筒照一下脚下,确定下坡方向,然后走一步。这样虽然每次看得不全(可能走偏),但比用探照灯照整个山洞(全量数据)快得多。

2. Momentum(动量优化):带着惯性的"滑滑梯选手"

Momentum在SGD基础上加了一个"动量"(Momentum)项,相当于给梯度下降加了惯性。数学上,它会维护一个"速度"变量,这个速度不仅取决于当前梯度,还取决于之前的速度(乘以一个动量系数γ,通常设0.9)。

生活类比:你在玩滑滑梯,当滑梯变平缓时(梯度变小),你不会立刻停下来,而是因为惯性继续滑一段。Momentum的"动量"就像这种惯性,能帮你冲过局部小坑(平缓区域),更快接近山谷。

3. Adam(自适应矩估计):会"智能调速"的导航仪

Adam(Adaptive Moment Estimation)是目前深度学习最常用的优化器之一。它结合了Momentum的动量项(一阶矩估计)和RMSprop的自适应学习率(二阶矩估计),相当于同时维护"速度"和"步长调节器"。

生活类比:你开车下山,导航仪(Adam)会做两件事:

  • 记住你之前的行驶方向(动量,避免突然转向);
  • 记录你之前的车速变化(比如急刹车过,说明路况复杂),自动调整油门(学习率)——路况好(梯度稳定)就开快,路况差(梯度波动大)就开慢。

核心概念之间的关系:从基础到智能的进化链

三种算法的关系可以用"升级打怪"来理解:

  • SGD是基础:解决了"如何根据当前信息调整方向"的问题,但容易走偏或卡住;
  • Momentum是1.0升级:增加了"历史方向记忆",解决了SGD在平缓区域/局部最小值附近停滞的问题;
  • Adam是2.0旗舰:同时记忆"历史方向"和"历史步长变化",解决了Momentum学习率固定、对不同参数调整不均衡的问题。

核心概念原理和架构的文本示意图

梯度下降家族进化链:
全量梯度下降(BGD) → SGD(随机选数据) → Momentum(加动量) → Adam(动量+自适应学习率)

Mermaid 流程图:参数更新的通用流程

graph TD
    A[初始化参数θ] --> B[计算当前损失J(θ)]
    B --> C[计算梯度∇J(θ)]
    C --> D{选择优化器}
    D -->|SGD| E[θ = θ - η∇J(θ)]
    D -->|Momentum| F[计算速度v = γv_prev + η∇J(θ); θ = θ - v]
    D -->|Adam| G[计算一阶矩m = β1*m_prev + (1-β1)∇J(θ); 计算二阶矩v = β2*v_prev + (1-β2)(∇J(θ))²; 修正m_hat = m/(1-β1^t); 修正v_hat = v/(1-β2^t); θ = θ - η*m_hat/(√v_hat + ε)]
    E --> H[重复直到收敛]
    F --> H
    G --> H

核心算法原理 & 具体操作步骤

1. SGD:一步一探的数学表达

数学公式
参数更新规则为:
θ t + 1 = θ t − η ⋅ ∇ J ( θ t ) \theta_{t+1} = \theta_t - \eta \cdot \nabla J(\theta_t) θt+1=θtηJ(θt)
其中:

  • θ t \theta_t θt:第t步的参数;
  • η \eta η:学习率(步长);
  • ∇ J ( θ t ) \nabla J(\theta_t) J(θt):损失函数在 θ t \theta_t θt处的梯度(下山方向)。

关键特点

  • 每次只用1个样本计算梯度(随机选),计算快,但梯度噪声大(像用手电筒照路,可能看错方向);
  • 学习率固定,可能在接近山谷时仍大步走,导致震荡。

2. Momentum:带着惯性的数学表达

数学公式
引入速度变量 v t v_t vt(类比物理中的动量),更新规则为:
v t + 1 = γ ⋅ v t + η ⋅ ∇ J ( θ t ) v_{t+1} = \gamma \cdot v_t + \eta \cdot \nabla J(\theta_t) vt+1=γvt+ηJ(θt)
θ t + 1 = θ t − v t + 1 \theta_{t+1} = \theta_t - v_{t+1} θt+1=θtvt+1
其中:

  • γ \gamma γ:动量系数(通常设0.9,代表保留90%的历史速度);
  • v t v_t vt:第t步的速度(历史方向的累积)。

关键特点

  • 梯度噪声会被动量"平滑"(因为历史速度是多个梯度的加权平均);
  • 能加速通过平缓区域(像滑滑梯的惯性),避免SGD在局部最小值附近来回震荡。

3. Adam:智能调速的数学表达

数学公式
同时维护一阶矩(动量,方向)和二阶矩(梯度平方的期望,步长调节器),更新规则为:
m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ ∇ J ( θ t ) (一阶矩,方向记忆) m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1) \cdot \nabla J(\theta_t) \quad \text{(一阶矩,方向记忆)} mt=β1mt1+(1β1)J(θt)(一阶矩,方向记忆)
v t = β 2 ⋅ v t − 1 + ( 1 − β 2 ) ⋅ ( ∇ J ( θ t ) ) 2 (二阶矩,步长记忆) v_t = \beta_2 \cdot v_{t-1} + (1-\beta_2) \cdot (\nabla J(\theta_t))^2 \quad \text{(二阶矩,步长记忆)} vt=β2vt1+(1β2)(J(θt))2(二阶矩,步长记忆)
m ^ t = m t 1 − β 1 t (偏差修正,初始阶段矩估计有偏) \hat{m}_t = \frac{m_t}{1 - \beta_1^t} \quad \text{(偏差修正,初始阶段矩估计有偏)} m^t=1β1tmt(偏差修正,初始阶段矩估计有偏)
v ^ t = v t 1 − β 2 t (偏差修正) \hat{v}_t = \frac{v_t}{1 - \beta_2^t} \quad \text{(偏差修正)} v^t=1β2tvt(偏差修正)
θ t + 1 = θ t − η ⋅ m ^ t v ^ t + ϵ (参数更新) \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \quad \text{(参数更新)} θt+1=θtηv^t +ϵm^t(参数更新)
其中:

  • β 1 \beta_1 β1 β 2 \beta_2 β2:分别控制一阶矩和二阶矩的衰减率(通常设0.9和0.999);
  • ϵ \epsilon ϵ:防止除零的小常数(如 1 e − 8 1e-8 1e8)。

关键特点

  • 自适应调整每个参数的学习率( m ^ t v ^ t \frac{\hat{m}_t}{\sqrt{\hat{v}_t}} v^t m^t相当于为每个参数定制步长);
  • 结合了Momentum的方向记忆和RMSprop的自适应步长,对稀疏数据(如自然语言处理中的词频)表现尤其好。

数学模型和公式 & 详细讲解 & 举例说明

用"下山"案例理解公式差异

假设我们要最小化一个简单的二次函数: J ( θ ) = θ 2 J(\theta) = \theta^2 J(θ)=θ2(山谷在 θ = 0 \theta=0 θ=0)。初始位置 θ 0 = 5 \theta_0=5 θ0=5,学习率 η = 0.1 \eta=0.1 η=0.1

SGD的表现:

梯度 ∇ J ( θ t ) = 2 θ t \nabla J(\theta_t) = 2\theta_t J(θt)=2θt,更新规则:
θ t + 1 = θ t − 0.1 ⋅ 2 θ t = 0.8 θ t \theta_{t+1} = \theta_t - 0.1 \cdot 2\theta_t = 0.8\theta_t θt+1=θt0.12θt=0.8θt

  • 第1步: θ 1 = 0.8 × 5 = 4 \theta_1 = 0.8 \times 5 = 4 θ1=0.8×5=4
  • 第2步: θ 2 = 0.8 × 4 = 3.2 \theta_2 = 0.8 \times 4 = 3.2 θ2=0.8×4=3.2
  • … 逐步逼近0,像小步走楼梯。
Momentum的表现(γ=0.9):

速度 v t = 0.9 v t − 1 + 0.1 ⋅ 2 θ t v_t = 0.9v_{t-1} + 0.1 \cdot 2\theta_t vt=0.9vt1+0.12θt,初始 v 0 = 0 v_0=0 v0=0

  • 第1步: v 1 = 0.9 × 0 + 0.1 × 10 = 1 v_1 = 0.9 \times 0 + 0.1 \times 10 = 1 v1=0.9×0+0.1×10=1 θ 1 = 5 − 1 = 4 \theta_1 = 5 - 1 = 4 θ1=51=4
  • 第2步: v 2 = 0.9 × 1 + 0.1 × 8 = 0.9 + 0.8 = 1.7 v_2 = 0.9 \times 1 + 0.1 \times 8 = 0.9 + 0.8 = 1.7 v2=0.9×1+0.1×8=0.9+0.8=1.7 θ 2 = 4 − 1.7 = 2.3 \theta_2 = 4 - 1.7 = 2.3 θ2=41.7=2.3
  • 第3步: v 3 = 0.9 × 1.7 + 0.1 × 4.6 = 1.53 + 0.46 = 1.99 v_3 = 0.9 \times 1.7 + 0.1 \times 4.6 = 1.53 + 0.46 = 1.99 v3=0.9×1.7+0.1×4.6=1.53+0.46=1.99 θ 3 = 2.3 − 1.99 ≈ 0.31 \theta_3 = 2.3 - 1.99 ≈ 0.31 θ3=2.31.990.31
    可以看到,Momentum的速度逐渐累积,后期下降更快(像滑滑梯越来越快)。
Adam的表现(β1=0.9, β2=0.999, η=0.1):

初始 m 0 = 0 m_0=0 m0=0, v 0 = 0 v_0=0 v0=0, t = 1 t=1 t=1

  • 第1步:
    m 1 = 0.9 × 0 + 0.1 × 10 = 1 m_1 = 0.9 \times 0 + 0.1 \times 10 = 1 m1=0.9×0+0.1×10=1
    v 1 = 0.999 × 0 + 0.001 × 100 = 0.1 v_1 = 0.999 \times 0 + 0.001 \times 100 = 0.1 v1=0.999×0+0.001×100=0.1
    m ^ 1 = 1 / ( 1 − 0.9 1 ) = 10 \hat{m}_1 = 1/(1 - 0.9^1) = 10 m^1=1/(10.91)=10
    v ^ 1 = 0.1 / ( 1 − 0.999 1 ) ≈ 100 \hat{v}_1 = 0.1/(1 - 0.999^1) ≈ 100 v^1=0.1/(10.9991)100
    θ 1 = 5 − 0.1 × ( 10 / 100 + 1 e − 8 ) ≈ 5 − 0.1 × 1 = 4.9 \theta_1 = 5 - 0.1 \times (10/\sqrt{100} + 1e-8) ≈ 5 - 0.1 \times 1 = 4.9 θ1=50.1×(10/100 +1e8)50.1×1=4.9
  • 第2步(t=2):
    m 2 = 0.9 × 1 + 0.1 × 9.8 = 0.9 + 0.98 = 1.88 m_2 = 0.9 \times 1 + 0.1 \times 9.8 = 0.9 + 0.98 = 1.88 m2=0.9×1+0.1×9.8=0.9+0.98=1.88
    v 2 = 0.999 × 0.1 + 0.001 × 96.04 ≈ 0.0999 + 0.096 = 0.1959 v_2 = 0.999 \times 0.1 + 0.001 \times 96.04 ≈ 0.0999 + 0.096 = 0.1959 v2=0.999×0.1+0.001×96.040.0999+0.096=0.1959
    m ^ 2 = 1.88 / ( 1 − 0.9 2 ) ≈ 1.88 / 0.19 ≈ 9.89 \hat{m}_2 = 1.88/(1 - 0.9^2) ≈ 1.88/0.19 ≈ 9.89 m^2=1.88/(10.92)1.88/0.199.89
    v ^ 2 = 0.1959 / ( 1 − 0.999 2 ) ≈ 0.1959 / 0.001999 ≈ 97.99 \hat{v}_2 = 0.1959/(1 - 0.999^2) ≈ 0.1959/0.001999 ≈ 97.99 v^2=0.1959/(10.9992)0.1959/0.00199997.99
    θ 2 = 4.9 − 0.1 × ( 9.89 / 97.99 ) ≈ 4.9 − 0.1 × 1 ≈ 4.8 \theta_2 = 4.9 - 0.1 \times (9.89/\sqrt{97.99}) ≈ 4.9 - 0.1 \times 1 ≈ 4.8 θ2=4.90.1×(9.89/97.99 )4.90.1×14.8
    早期Adam调整较保守(因为偏差修正项大),但后期会根据梯度变化自动加速。

项目实战:用Python代码对比三种算法效果

开发环境搭建

  • 安装Python 3.8+、numpy、matplotlib
  • 代码示例在Jupyter Notebook中运行更直观

源代码详细实现和代码解读

我们以拟合一条直线(线性回归)为例,比较三种优化器的训练效果。假设真实数据满足 y = 2 x + 1 + ϵ y = 2x + 1 + \epsilon y=2x+1+ϵ ϵ \epsilon ϵ是噪声),我们需要用模型 y = w x + b y = wx + b y=wx+b拟合,损失函数用均方误差(MSE)。

import numpy as np
import matplotlib.pyplot as plt

# 生成模拟数据
np.random.seed(42)
x = np.random.rand(100, 1) * 10  # 100个0-10的随机数
y = 2 * x + 1 + np.random.randn(100, 1) * 1  # 真实值=2x+1+噪声

# 初始化参数
w = np.random.randn(1)  # 斜率
b = np.random.randn(1)  # 截距
lr = 0.01  # 学习率(Adam可能需要更大,比如0.001)
epochs = 200  # 训练轮数

# 定义损失函数(MSE)
def compute_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 定义梯度计算函数
def compute_gradients(x, y_true, w, b):
    y_pred = w * x + b
    dw = -2 * np.mean(x * (y_true - y_pred))  # dL/dw
    db = -2 * np.mean(y_true - y_pred)  # dL/db
    return dw, db

# 定义三种优化器的参数更新函数
def sgd_update(w, b, dw, db, lr):
    new_w = w - lr * dw
    new_b = b - lr * db
    return new_w, new_b

def momentum_update(w, b, dw, db, lr, v_w, v_b, gamma=0.9):
    v_w = gamma * v_w + lr * dw
    v_b = gamma * v_b + lr * db
    new_w = w - v_w
    new_b = b - v_b
    return new_w, new_b, v_w, v_b

def adam_update(w, b, dw, db, lr, m_w, m_b, v_w, v_b, t, beta1=0.9, beta2=0.999, eps=1e-8):
    # 计算一阶矩(动量)
    m_w = beta1 * m_w + (1 - beta1) * dw
    m_b = beta1 * m_b + (1 - beta1) * db
    # 计算二阶矩(梯度平方的期望)
    v_w = beta2 * v_w + (1 - beta2) * (dw ** 2)
    v_b = beta2 * v_b + (1 - beta2) * (db ** 2)
    # 偏差修正
    m_w_hat = m_w / (1 - beta1 ** t)
    m_b_hat = m_b / (1 - beta1 ** t)
    v_w_hat = v_w / (1 - beta2 ** t)
    v_b_hat = v_b / (1 - beta2 ** t)
    # 参数更新
    new_w = w - lr * m_w_hat / (np.sqrt(v_w_hat) + eps)
    new_b = b - lr * m_b_hat / (np.sqrt(v_b_hat) + eps)
    return new_w, new_b, m_w, m_b, v_w, v_b

代码解读与分析

  • SGD:每次直接用当前梯度乘以学习率更新参数(new_w = w - lr * dw)。
  • Momentum:维护速度变量v_wv_b,每次更新时结合历史速度(v_w = gamma * v_w + lr * dw)。
  • Adam:同时维护一阶矩(m_w)和二阶矩(v_w),并通过偏差修正(m_w_hatv_w_hat)解决初始阶段矩估计的偏差问题。

训练过程对比(画图展示)

# 训练SGD
w_sgd, b_sgd = np.random.randn(1), np.random.randn(1)
losses_sgd = []
for epoch in range(epochs):
    dw, db = compute_gradients(x, y, w_sgd, b_sgd)
    w_sgd, b_sgd = sgd_update(w_sgd, b_sgd, dw, db, lr=0.001)  # SGD需要更小学习率防震荡
    loss = compute_loss(y, w_sgd * x + b_sgd)
    losses_sgd.append(loss)

# 训练Momentum
w_mom, b_mom = np.random.randn(1), np.random.randn(1)
v_w, v_b = 0, 0
losses_mom = []
for epoch in range(epochs):
    dw, db = compute_gradients(x, y, w_mom, b_mom)
    w_mom, b_mom, v_w, v_b = momentum_update(w_mom, b_mom, dw, db, lr=0.01, v_w=v_w, v_b=v_b)
    loss = compute_loss(y, w_mom * x + b_mom)
    losses_mom.append(loss)

# 训练Adam
w_adam, b_adam = np.random.randn(1), np.random.randn(1)
m_w, m_b, v_w, v_b = 0, 0, 0, 0
losses_adam = []
for t in range(1, epochs+1):  # t从1开始计算偏差修正
    dw, db = compute_gradients(x, y, w_adam, b_adam)
    w_adam, b_adam, m_w, m_b, v_w, v_b = adam_update(w_adam, b_adam, dw, db, lr=0.001, 
                                                     m_w=m_w, m_b=m_b, v_w=v_w, v_b=v_b, t=t)
    loss = compute_loss(y, w_adam * x + b_adam)
    losses_adam.append(loss)

# 画图对比损失下降曲线
plt.figure(figsize=(12, 6))
plt.plot(losses_sgd, label='SGD')
plt.plot(losses_mom, label='Momentum')
plt.plot(losses_adam, label='Adam')
plt.xlabel('Epochs')
plt.ylabel('Loss (MSE)')
plt.title('Loss Convergence Comparison')
plt.legend()
plt.show()

实验结果分析

  • SGD的损失下降最慢,且后期有小幅震荡(因为梯度噪声大);
  • Momentum的损失下降更快,震荡更小(动量平滑了噪声);
  • Adam的损失下降最快,早期就接近最小值(自适应学习率和动量的双重优势)。

实际应用场景

1. SGD:适合小数据/简单模型

  • 场景:数据量小(如几百条样本)、模型简单(如逻辑回归)。
  • 原因:SGD计算简单,内存占用小(每次只用1个样本),但需要仔细调学习率。
  • 案例:学生用小数据集做课程作业时,SGD足够且容易实现。

2. Momentum:适合梯度有噪声的场景

  • 场景:数据有噪声(如传感器采集的时序数据)、损失函数曲面不平滑(有局部最小值)。
  • 原因:动量能平滑梯度噪声,帮助模型冲过局部最小值。
  • 案例:训练时间序列预测模型(如LSTM预测股价),Momentum比SGD更稳定。

3. Adam:适合大数据/复杂模型

  • 场景:数据量大(如百万级图像)、模型复杂(如ResNet、Transformer)。
  • 原因:Adam自适应调整学习率,对稀疏特征(如自然语言中的低频词)友好,无需手动调参。
  • 案例:训练BERT模型做文本分类时,Adam是默认优化器(PyTorch的torch.optim.Adam)。

工具和资源推荐

  • PyTorch优化器:直接调用torch.optim.SGDtorch.optim.SGD(momentum=0.9)torch.optim.Adam
  • TensorFlow优化器tf.keras.optimizers.SGDtf.keras.optimizers.Momentumtf.keras.optimizers.Adam
  • 可视化工具:用matplotlib画损失曲线,或用tensorboard实时监控训练过程。
  • 论文推荐
    • SGD原始论文:《Large-Scale Machine Learning with Stochastic Gradient Descent》
    • Momentum原始论文:《A Method for Solving the Convex Programming Problem with Convergence Rate O(1/k^2)》
    • Adam原始论文:《Adam: A Method for Stochastic Optimization》

未来发展趋势与挑战

趋势1:自适应优化器的改进

Adam虽然好用,但在某些场景(如GAN训练)中可能出现"过冲"问题。近年研究提出了AdamW(加入权重衰减)、RAdam(动态调整二阶矩修正)等改进版本,进一步提升稳定性。

趋势2:与二阶方法结合

梯度下降是一阶方法(只用一阶导数),而牛顿法等二阶方法(用二阶导数)收敛更快,但计算复杂。未来可能出现"一阶+二阶"混合优化器,平衡速度和计算量。

挑战:超参数调优

即使是Adam,也需要调学习率( η \eta η)、动量系数( β 1 \beta_1 β1)等超参数。如何自动调参(如贝叶斯优化)是工业界的重要问题。


总结:学到了什么?

核心概念回顾

  • SGD:基础梯度下降,用单个样本计算梯度,速度快但噪声大;
  • Momentum:加动量项,利用历史梯度方向,平滑噪声、加速收敛;
  • Adam:结合动量和自适应学习率,为每个参数定制步长,适合复杂模型。

概念关系回顾

三种算法是"基础→改进→智能"的进化链:
SGD解决了"如何用少量数据更新参数"的问题;
Momentum解决了"SGD在平缓区域停滞"的问题;
Adam解决了"Momentum学习率固定、参数调整不均衡"的问题。


思考题:动动小脑筋

  1. 为什么SGD需要更小的学习率?如果学习率太大,会发生什么?(提示:梯度噪声大,大步走容易跨过最小值)
  2. Momentum的动量系数 γ \gamma γ设为0.9和0.5,效果会有什么不同?(提示: γ \gamma γ越大,越依赖历史速度)
  3. 如果你训练一个图像分类模型(如ResNet),数据量很大(百万张图),应该选SGD、Momentum还是Adam?为什么?

附录:常见问题与解答

Q:SGD是"随机"的,那它和"全量梯度下降(BGD)"有什么区别?
A:BGD用所有样本计算梯度(准确但慢),SGD用单个样本(快但噪声大)。还有"小批量梯度下降(Mini-batch GD)",用一批样本(如32个),是SGD的改进版(PyTorch的SGD优化器默认是Mini-batch)。

Q:Adam的学习率为什么通常设0.001,而SGD设0.01?
A:Adam的自适应学习率会自动缩放梯度,所以需要更小的初始学习率防止过冲;SGD的学习率直接控制步长,需要更大才能有效下降。

Q:训练时loss突然上升,可能是优化器的问题吗?
A:可能!如果学习率太大(SGD/Momentum),或二阶矩估计不稳定(Adam早期),都可能导致参数更新过大,loss上升。可以尝试降低学习率,或检查数据是否有异常。


扩展阅读 & 参考资料

  • 《深度学习》(花书)第8章:优化算法
  • 李宏毅机器学习课程:《Optimization for Deep Learning》
  • 论文链接:
    • SGD:https://www.cs.utoronto.edu/~gdahl/papers/sgdTR.pdf
    • Momentum:https://www.math.ucla.edu/~wotaoyin/momentum.pdf
    • Adam:https://arxiv.org/abs/1412.6980
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值