深度学习优化器与优化方法

一、优化器的核心目标与基础问题

1. 核心目标

优化器的本质是高效更新模型参数(如权重 w、偏置 b),通过最小化损失函数(如均方误差),让模型预测结果更接近真实值。

2. 基础问题:梯度下降的 "数据量困境"

传统梯度下降需计算所有样本的梯度均值更新参数,但实际场景中样本量常达数万至亿级,会导致两大问题:

  • 内存 / 显存不足(OOM):海量数据的存储与运算超出硬件承载能力;
  • 计算效率极低:全量数据迭代一次耗时极久,无法快速调整参数。

为解决此问题,++梯度下降衍生出++ 3 种核心变体,也是后续优化器的 "基础框架":

|---------------|----------------------------------------------|--------------------------|-------------------------------------|--------------------|
| 梯度下降变体 | 核心逻辑 | 优点 | 缺点 | 适用场景 |
| 批量梯度下降(BGD) | 每次迭代用全部样本算梯度更新 | 梯度准确,易收敛到全局最优解 | 大规模数据内存超限,计算开销大 | 小数据集(样本数 < 1 万) |
| 随机梯度下降(SGD) | 每次迭代用1 个样本算梯度更新 | 数据量极小,计算开销极低 | 梯度随机性大,训练震荡明显,迭代次数激增 | 超大规模数据(快速近似优化) |
| 小批量梯度下降(MBGD) | 每次迭代用固定大小的 mini-batch(如 32/64/128) 算梯度更新 | 兼顾效率与内存,可按硬件调 batch size | 需手动调 batch size,震荡程度介于 BGD 与 SGD 之间 | 深度学习主流场景(90% 以上模型) |

关键辨析:实际应用中常将 "MBGD" 误称为 "SGD",但严格来说二者不同 ------SGD 仅用 1 个样本,MBGD 用多个样本(mini-batch)。

3. 批量大小(batch_size)与更新次数的关系

1 个 "epoch" 指遍历全部训练样本的过程,更新次数由 batch_size 决定:

  • 例:总样本数 = 10
    • batch_size=10(BGD):1 个 epoch 仅需 1 次更新;
    • batch_size=2(MBGD):1 个 epoch 需 5 次更新(10÷2=5 个 mini-batch);
    • batch_size=1(SGD):1 个 epoch 需 10 次更新。

二、经典优化器详解(从基础到进阶)

1. 随机梯度下降(SGD):优化器的 "基石"

(1)核心原理

基于 MBGD/SGD 框架,参数更新公式为:

w = w - lr × dw

b = b - lr × db

  • lr(学习率):控制每次更新的 "步长",过大易震荡不收敛,过小收敛过慢(通常取 0.001/0.01);
  • dw/db:当前 mini-batch 样本对 w/b 的梯度(损失函数对参数的偏导数)。
(2)代码实现(含核心逻辑)
python 复制代码
import numpy as np

import matplotlib.pyplot as plt

# 1. 输入数据(散点样本,模拟线性回归任务)

points = np.array([[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7],

[-1.4, -37.3], [-1.8, -49.1], [1.5, 75.6], [0.4, 34.0], [0.8, 62.3]])

X = points[:, 0] # 特征(自变量)

Y = points[:, 1] # 标签(因变量)

# 2. 参数初始化(w初始为0,b初始为-1,学习率lr=0.001)

w = 0

b = -1

lr = 0.001

# 3. 损失函数(均方误差MSE):衡量预测值与真实值的差距

def loss_func(X, w, b):

pre_y = np.dot(X, w) + b # 前向传播:预测值=w×X + b

loss = np.mean((Y - pre_y) ** 2) # 均方误差

return loss

# 4. SGD优化器核心:按mini-batch更新参数

def SGD(points, w, b, lr, batch_size=1):

np.random.shuffle(points) # 每次迭代前打乱样本(避免顺序影响)

# 遍历所有mini-batch:从0到样本数,步长=batch_size

for num_batch in range(0, len(points), batch_size):

batch_points = points[num_batch:num_batch + batch_size, :] # 取当前mini-batch

batch_X = batch_points[:, 0]

batch_Y = batch_points[:, 1]

# 计算当前batch的梯度(dw:w的梯度,db:b的梯度)

pre_y = np.dot(batch_X, w) + b

dw = np.mean((pre_y - batch_Y) * batch_X) # 损失对w的偏导数

db = np.mean(pre_y - batch_Y) # 损失对b的偏导数

# 更新参数(核心公式)

w = w - lr * dw

b = b - lr * db

return w, b

# 5. 训练过程(迭代1000次,观察损失下降)

loss_history = []

for epoch in range(1000):

w, b = SGD(points, w, b, lr, batch_size=2) # 用MBGD(batch_size=2)

loss = loss_func(X, w, b)

loss_history.append(loss)

# 6. 可视化损失下降(验证优化效果)

plt.plot(range(1000), loss_history)

plt.xlabel("Epoch")

plt.ylabel("Loss (MSE)")

plt.title("SGD Training Loss Curve")

plt.show()
(3)SGD 的缺陷
  • 震荡明显:每次更新仅依赖少量样本,梯度方向随机,参数更新路径 "忽左忽右";
  • 收敛慢:步长(学习率)固定,后期接近最优解时仍可能因步长问题反复震荡,无法快速收敛。

2. SGD+Momentum(动量法):解决 SGD 的 "震荡与慢收敛"

(1)核心思路

引入 "动量(Momentum)" 概念 ------ 模拟物理中的 "惯性",让参数更新时 "记住历史梯度方向",平滑当前梯度的随机性,减少震荡、加速收敛。

(2)数学公式(分框架差异)

|------------|-------------------------|--------------------------|
| 框架 | 动量计算(v_t:t 时刻动量) | 参数更新公式(P_t:t 时刻参数,如 w/b) |
| TensorFlow | v_t = η·v_{t-1} + α·g_t | P_{t+1} = P_t - v_t |
| PyTorch | v_t = η·v_{t-1} + g_t | P_{t+1} = P_t - α·v_t |

  • 符号说明:
    • η(动量系数):控制历史梯度的影响程度,默认 0.9(越大惯性越强,历史影响越大);
    • α(学习率):步长,同 SGD;
    • g_t:t 时刻参数的梯度(dw/db);
    • v_{t-1}:t-1 时刻的动量,初始值为 0(TensorFlow)或初始梯度(PyTorch)。
(3)核心优势:"平滑震荡,加速收敛"
  • 平滑震荡:当当前梯度方向与历史动量方向一致时,动量会 "叠加" 当前梯度,让更新步长变大;当方向相反时,动量会 "抵消" 部分当前梯度,减少震荡;
  • 加速收敛:在梯度方向稳定的区域(如损失函数的 "斜坡" 区域),动量会持续累积,让参数快速向最优解移动。
(4)直观理解(如图示)
  • A 点:记录当前梯度方向(水平向右),动量 v_{A} = η・0 + α・g_A(初始 v=0);
  • B 点:当前梯度方向为 "斜向左下",但 A 点的动量(水平向右)会与当前梯度叠加,最终更新方向指向 C 点(更平滑、更接近最优解);
  • 本质:"记着之前的路,别被当前梯度带偏"。

3. AdaGrad(自适应梯度):解决 "学习率固定" 问题

(1)核心思路

SGD 和 Momentum 用统一的学习率更新所有参数,但模型中不同参数的 "更新频率" 不同:

  • 高频更新参数(如高频特征对应的 w):需小学习率,避免被单次样本影响过大;
  • 低频更新参数(如低频特征对应的 w):需大学习率,从少量样本中多学信息。

AdaGrad 通过为每个参数适配独立的学习率,解决学习率固定的问题 ------ 引入 "二阶动量"(梯度平方累积和),动态调整学习率。

(2)数学公式
  1. 二阶动量计算(S_t:t 时刻参数的梯度平方累积和):

S_t = S_{t-1} + g_t · g_t

  1. 参数更新公式:

P_{t+1} = P_t - (α / √(S_t + ε)) · g_t

  • 符号说明:
    • ε:防止分母为 0 的微小值(通常取 1e-7);
    • √(S_t + ε):随迭代次数增大,分母变大,学习率自动衰减。
(3)优势与缺陷

|---------------------------------------------------------------|--------------------------------------------------|
| 优势 | 缺陷 |
| 1. 前期学习率高,更新快;后期自动衰减,稳定训练;. 为不同参数适配独立学习率,适合稀疏数据(如 NLP 中的低频词)。 | 历史梯度平方持续累积,分母越来越大,学习率衰减过快,可能导致训练 "过早停滞"(参数不再更新)。 |

4. RMSProp:改进 AdaGrad 的 "学习率衰减过快"

(1)核心思路

针对 AdaGrad "二阶动量持续累积" 的缺陷,RMSProp 引入指数加权移动平均(EMA),让二阶动量仅 "关注近期梯度",减缓学习率衰减速度。

(2)数学公式
  1. 二阶动量计算(用 EMA 替代直接累积):

S_t = η·S_{t-1} + (1 - η)·g_t · g_t

  1. 参数更新公式(同 AdaGrad):

P_{t+1} = P_t - (α / √(S_t + ε)) · g_t

  • 符号说明:
    • η(衰减系数):控制历史梯度的遗忘程度,默认 0.9(仅保留近期 10% 的梯度信息);
    • 例:t=100 时,S_100 = 0.9・S_99 + 0.1・g_100²,仅保留 S_99 的 90% 和 g_100² 的 10%,避免累积过大。
(3)核心优势
  • 克服 AdaGrad 的 "学习率衰减过快" 问题,让训练后期仍能保持合理的学习率,持续更新参数;
  • 比 AdaGrad 更稳定,调参难度更低,适合中大型模型训练。

5. Adam(自适应矩估计):当前主流优化器

(1)核心思路

融合Momentum(一阶动量,关注梯度方向)RMSProp(二阶动量,关注梯度大小) 的优势,同时跟踪梯度的 "均值(方向)" 和 "方差(大小)",实现更智能的参数更新 ------ 既解决震荡问题,又适配独立学习率,且无学习率衰减过快问题。

(2)数学公式(三步核心)
第一步:计算一阶矩和二阶矩(分别对应方向和大小)
  • 一阶矩(m_t:梯度均值,模拟 Momentum 的惯性):

m_t = β₁·m_{t-1} + (1 - β₁)·g_t

  • 二阶矩(v_t:梯度方差,模拟 RMSProp 的自适应学习率):

v_t = β₂·v_{t-1} + (1 - β₂)·g_t · g_t

  • 默认参数:β₁=0.9(一阶矩衰减系数),β₂=0.999(二阶矩衰减系数),ε=1e-7。
第二步:偏差修正(解决 "初始矩估计不准确" 问题)

初始时 m_0=0、v_0=0,前几次迭代的 m_t 和 v_t 会 "低估" 真实梯度的均值和方差,需修正:

  • 一阶矩修正:m_t^hat = m_t / (1 - β₁^t)
  • 二阶矩修正:v_t^hat = v_t / (1 - β₂^t)
  • 说明:t 为迭代次数,当 t 增大时,β₁^t 和 β₂^t 趋近于 0,修正项趋近于 1,无需额外调整。
第三步:参数更新

P_{t+1} = P_t - (α / √(v_t^hat + ε)) · m_t^hat

(3)核心优势(为何成为主流?)
  1. 收敛快:融合一阶矩的惯性和平滑性,加速参数向最优解移动;
  1. 鲁棒性强:二阶矩的自适应学习率适配不同参数,避免震荡和衰减过快;
  1. 调参简单:默认参数(β₁=0.9、β₂=0.999、lr=0.001)在 90% 以上的任务中表现优异,无需频繁调整。

三、知识点串联:优化器的 "演进逻辑"

从基础到进阶,优化器的发展始终围绕 "解决前一代的缺陷" 展开,形成清晰的演进链:

各优化器核心差异对比

|--------------|----------------------|-----------------------------|----------------------|
| 优化器 | 核心改进点 | 适用场景 | 缺点 |
| SGD | 基础框架,按 mini-batch 更新 | 简单模型、小数据集 | 震荡明显,收敛慢 |
| SGD+Momentum | 加惯性(一阶矩),平滑震荡 | 中大型模型,需加速收敛 | 仍用统一学习率,不适应稀疏数据 |
| AdaGrad | 自适应学习率(二阶矩) | 稀疏数据(如 NLP 低频词) | 学习率衰减过快,易停滞 |
| RMSProp | EMA 优化二阶矩,减缓衰减 | 中大型模型,避免训练停滞 | 未利用梯度方向,部分场景适配性差 |
| Adam | 融合一阶矩 + 二阶矩 + 偏差修正 | 几乎所有场景(CNN、RNN、Transformer) | 极端稀疏数据下,AdaGrad 可能更优 |

四、实验实操:从虚拟仿真到代码运行

1. 实验流程(基于 "华清远见人工智能虚拟仿真平台")

  1. 启动服务:打开 "虚拟仿真本地服务管理平台",启动后无需重复启动;
  1. 进入实验:点击 "优化器与优化方法实验",若已在其他实验页面,点击右上角 "返回" 回到主页;
  1. 组件连线:根据优化器原理(如 SGD 需 "数据输入→参数初始化→损失计算→SGD 更新"),拖出组件并按逻辑连线;
  1. 验证逻辑:点击 "验证" 按钮,显示 "校验成功" 说明组件连线无误;
  1. 运行实验:点击 "运行",观察参数更新过程与损失下降曲线;
  1. 生成代码:点击左下角 "生成代码",复制代码到 Jupyter 中运行(需先通过 CMD 启动 Jupyter:python -m jupyterlab --notebook-dir ./learn)。

2. 实验关键观察点

  • 损失曲线:优质优化器(如 Adam)的损失曲线应 "快速下降并趋于平稳",无明显震荡;
  • 参数更新速度:对比 SGD 与 Adam 的迭代次数,Adam 通常能在更少迭代次数内达到较低损失;
  • 学习率影响:当 lr 过小时,所有优化器收敛都会变慢;当 lr 过大时,SGD 会剧烈震荡,Adam 则更稳定(因二阶矩修正步长)。
相关推荐
Yeats_Liao2 小时前
模型选型指南:7B、67B与MoE架构的业务适用性对比
前端·人工智能·神经网络·机器学习·架构·deep learning
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章10-中值滤波
图像处理·人工智能·opencv·算法·计算机视觉
百***24372 小时前
GLM-4.7底层技术拆解与落地避坑:开源大模型编码实战指南
人工智能·gpt·开源
予枫的编程笔记2 小时前
【Spring Security】Spring Boot 与 Spring Security 核心版本的对应表
人工智能
星浩AI2 小时前
从0到1:用LlamaIndex工作流构建Text-to-SQL应用完整指南
人工智能·后端·python
Elastic 中国社区官方博客2 小时前
Elasticsearch:Jina Reader
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索·jina
TAICHIFEI2 小时前
Hugging Face 的 Transformers库
人工智能·深度学习·学习·自然语言处理
s09071362 小时前
【计算机视觉】详解立体匹配算法:原理、公式与核心策略
人工智能·算法·计算机视觉·立体匹配
山科智能信息处理实验室2 小时前
SDS-Complete: 利用预训练文生图模型进行点云补全
人工智能·深度学习