反向传播与梯度下降:神经网络如何学习

摘要:神经网络的"学习"本质上是一个优化问题------找到一组参数让模型的预测误差最小。反向传播和梯度下降就是解决这个问题的核心算法。这篇文章从直观到数学,讲清楚神经网络训练的底层逻辑。


一、学习的本质:一个优化问题

上一篇文章我们知道了神经网络的结构:输入层 → 隐藏层 → 输出层,每层之间有带权重的连接。

但一个关键问题没回答:这些权重是怎么自动学出来的?

把问题拆开看:

复制代码
给定:一个训练数据集(输入 x,期望输出 y_true)
目标:找到一组权重 w,使得网络的预测 y_pred 和 y_true 尽可能接近
约束:权重 w 可能有数百万到数千亿个

这就是一个优化问题------在巨大的参数空间中,找到一组参数使误差最小。

问题 类比说明
参数空间 一座巨大的山(维度 = 参数数量)
当前位置 当前的参数组合(在山上的某个点)
误差 当前位置的海拔高度(越低越好)
目标 找到山谷的最低点(误差最小的参数)

梯度下降 就是在这个山上"下山"的算法,而反向传播是计算"往哪个方向走"的工具。


二、梯度下降:下山算法

核心思想

梯度下降的直觉非常简单:

在当前站着的位置,看看四周哪个方向是下坡,往那个方向迈一步。

到了新位置,再重复这个过程,直到走到谷底。

数学上:

复制代码
w_new = w_old - η × ∇L(w_old)

其中:
  w        = 参数(权重)
  η        = 学习率(步长大小)
  ∇L(w)    = 损失函数在 w 处的梯度(指向最陡上升方向)
  负号      = 朝梯度反方向走(下坡而不是上坡)

用一个参数的情况理解

假设网络只有一个参数 w,误差函数是 L(w) = w²:

复制代码
L(w) = w² 的图像是一个抛物线:
                      L
                      ↑
                     /\
                    /  \
                   /    \
              ----/------\----→ w
                 /        \
                /          \
          最小值点 (w=0, L=0)

如果 w 当前在 2 的位置:
  ∇L(2) = 4(梯度指向正方向,说明要往左走才能下坡)
  w_new = 2 - η × 4
     如果 η = 0.1:w_new = 2 - 0.1 × 4 = 1.6 ← 离谷底更近了
     
重复多次后 w 会逐渐接近 0(最低点)

学习率:步长的艺术

学习率 η 是最重要的超参数之一,控制每次调整的幅度:

复制代码
学习率太小(η = 0.001):
  每次只走一点点,需要很多步才能到谷底 → 训练极慢
  
学习率合适(η = 0.1):
  稳步下降,效率最高 → 训练顺利
  
学习率太大(η = 1.0):
  一步跨过谷底,跳到了对面的山坡上 → 震荡、发散

三种梯度下降方式

方式 每步用的数据 特点 适用场景
批量梯度下降(BGD) 全部数据 方向最准,但每步很慢 小数据集
随机梯度下降(SGD) 1 个样本 速度快但方向有噪声 大数据集,在线学习
小批量梯度下降(Mini-batch) N 个样本(如 32/64/128) 兼顾速度和稳定性 实际中最常用

现代深度学习几乎都用 Mini-batch SGD(通常简称为 SGD),batch size 通常取 32、64、128 或 256。


三、反向传播:链式法则的艺术

梯度下降告诉我们"往哪走",但没告诉我们"怎么计算梯度"。对于一个有数百万参数的深度网络,手动计算每个参数的梯度是不可能的。

反向传播(Backpropagation) 就是解决这个问题的算法。

直观理解

想象你在一个大型游乐园里迷路了,你想回到入口:

  • 正向传播(从入口到当前位置):你经过了 A → B → C → D 四个岔路口,每个路口做了一个选择,最后到了 D。

  • 反向传播(从当前位置回入口):从 D 开始,往回走,每经过一个路口就问自己"如果我在这个路口选了另一条路,会离入口更近吗?"

    正向传播:
    输入 x → 层1 → 层2 → ... → 层N → 输出 y_pred → 计算误差 L

    反向传播:
    误差 L → 计算 ∂L/∂w_N(最后一层的梯度)
    → 把误差"传回"上一层 → 计算 ∂L/∂w_{N-1}
    → 继续传 → ... → 计算 ∂L/∂w_1

链式法则:数学基础

反向传播的数学基础是微积分中的链式法则

复制代码
如果有:z = f(y), y = g(x)
那么:dz/dx = dz/dy × dy/dx

在深度网络中:

复制代码
输出误差 L 依赖于 输出层的值 a_L
输出层的值 a_L 依赖于 最后一层的加权和 z_L
最后一层的加权和 z_L 依赖于 前一层的值 a_{L-1}
...一直追溯到输入层

所以:
∂L/∂w_1 = ∂L/∂a_L × ∂a_L/∂z_L × ∂z_L/∂a_{L-1} × ... × ∂a_2/∂z_2 × ∂z_2/∂a_1 × ∂a_1/∂z_1 × ∂z_1/∂w_1

这就是一个链式乘法。反向传播就是高效地计算这个乘积的过程------从输出层开始,逐层往前,把误差"传"回每一层。

为什么叫"反向"传播?

复制代码
正向传播(Forward):
  数据从输入层 → 经过各层变换 → 到达输出层 → 计算误差
  (信号前向流动)
  
反向传播(Backward):
  误差从输出层 → 逐层往回传 → 直到输入层
  → 在每一层计算该层参数的梯度
  (误差信号反向流动)

方向相反,计算效率极高------一次正向 + 一次反向,就能算出所有参数的梯度,无论网络有多深。


四、一个完整的训练循环

把梯度下降和反向传播组合起来,就得到了完整的训练循环:

复制代码
1. 前向传播(Forward Pass)
   输入一批数据 x → 通过网络计算 → 得到预测 y_pred → 计算损失 L
   
2. 反向传播(Backward Pass)
   从输出层开始 → 反向传播误差 → 计算每层参数的梯度
   
3. 参数更新(Gradient Descent Step)
   w = w - η × ∇L(w)  对网络中所有参数执行
   
4. 重复步骤 1-3,直到收敛或达到最大迭代次数

┌─────────────────────────────────────────────────────────┐
│                 一个训练步(Training Step)                │
│                                                         │
│   输入批次 ──→ 前向传播 ──→ 计算损失 ──→ 反向传播 ──→ 更新参数 │
│     ↑                                          │        │
│     └──────────────── 下一个批次 ──────────────┘        │
└─────────────────────────────────────────────────────────┘

时期(Epoch)和批次(Batch)

术语 含义 举例
Batch(批次) 一次训练步使用的样本数 32 张图像
Iteration(迭代) 一个 batch 前向+反向+更新 处理 32 张图算一次
Epoch(时期) 所有训练样本都过了一遍 10000 张图 / 32 = 313 次迭代

通常训练一个模型需要 几十到几百个 Epoch


五、优化器的演进

基础的 SGD 虽然简单有效,但有一些问题:

  • 在"峡谷"地形中容易震荡
  • 对学习率非常敏感
  • 在平坦区域停滞不前

研究者们提出了各种改进的优化器

优化器对比

优化器 核心思想 特点 2026年地位
SGD 原始梯度下降 简单,但需要手动调学习率 仍在使用,但很少单独用
Momentum 积累历史梯度方向(动量) 穿越峡谷更平稳,加速收敛 常用改进
AdaGrad 每个参数自适应学习率 稀疏梯度效果好 较少用了
RMSProp 梯度平方的滑动平均 处理非平稳目标 部分场景使用
Adam Momentum + RMSProp 结合 自适应学习率,几乎不用调参 最常用,默认选择
AdamW Adam + 权重衰减解耦 泛化性更好,训练更稳定 大模型训练首选

Adam 为什么这么流行?

Adam 是目前用得最广泛的优化器,原因很简单:

复制代码
对比 SGD:
  SGD:需要手动设置学习率、动量、学习率衰减策略...
  常见情况:学习率设大了发散,设小了太慢,改一次重训一次
  
  Adam:学习率默认 0.001,大多数情况直接 work
  常见情况:直接训练,效果已经很好

Adam 的缺点:在某些任务上泛化性不如精细调参的 SGD + Momentum。所以一个常见策略是先用 Adam 快速找到一个好的参数区域,然后切换回 SGD 做精细微调。


六、训练中的常见问题与解决

问题 1:梯度消失(Vanishing Gradient)

表现:网络深层(靠近输入)的参数几乎不更新,训练停滞。

原因:链式法则中连乘了太多小于 1 的梯度(尤其是 Sigmoid 激活函数的导数最大只有 0.25)。

复制代码
∂L/∂w_1 = ∂L/∂a_L × (≤0.25) × (≤0.25) × ... × (≤0.25)
                   └─ 连乘 L-1 次 ─┘
如果 L=50:梯度 ≈ 0.25⁵⁰ ≈ 10⁻³⁰ → 几乎为零

解决方案

  • 使用 ReLU 激活函数(梯度恒为 1)
  • 残差连接(ResNet,让梯度有"捷径")
  • 层归一化(Layer Normalization)

问题 2:梯度爆炸(Exploding Gradient)

表现:参数突然变得非常大,损失变为 NaN。

原因:梯度连乘了大量大于 1 的值。

解决方案

  • 梯度裁剪(Gradient Clipping):设置梯度的最大值
  • 权重初始化更加小心
  • 使用 Batch/Layer Normalization

问题 3:过拟合(Overfitting)

表现:在训练集上表现完美,但在新数据上表现很差。

解决方案

方法 核心思路 效果
Dropout 训练时随机"关掉"部分神经元 防止共适应,强制鲁棒性
L1/L2 正则化 在损失函数中加入权重大小的惩罚 防止权重过大
数据增强 对训练数据做随机变换(翻转、旋转等) 增加有效数据量
早停(Early Stopping) 验证集不再提升时停止训练 防止过度训练

七、现代训练技巧速览

技巧 作用 怎么做
学习率预热(Warmup) 开始用很小的学习率,逐渐增加到目标值 前 1000-2000 步线性增加
学习率衰减 训练后期减小步长,精细调整 Cosine 衰减、Step 衰减
权重初始化 初始参数选得好,训练快几倍 Kaiming Init(ReLU)、Xavier Init(Sigmoid)
Batch Normalization 让每层输入分布稳定 每层后加 BN 层
混合精度训练 用 FP16 训练,快 2-3 倍 现代 GPU 都支持
梯度累积 模拟更大的 Batch Size 多次前向后再更新

八、总结

概念 一句话理解
梯度下降 沿着坡度往谷底走的优化算法
学习率 每一步走多远
反向传播 从输出到输入,逐层计算每个参数的梯度
优化器 改进了的"下山"策略(Adam 最常用)
过拟合 考试答案背得太熟,题目一变就懵
梯度消失/爆炸 梯度在传递过程中变得太大或太小

核心三句话

  1. 正向传播 计算预测结果,反向传播计算梯度方向
  2. 梯度下降沿着梯度反方向更新参数
  3. 循环以上两步足够多次 → 网络学会完成任务

这就是深度学习的"学习"过程------不神秘,但极其优雅。

相关推荐
指尖的爷1 小时前
C++头文件的作用
开发语言·c++
winlife_1 小时前
全程用 AI 做一款商业级手游 · EP0 立项:能做到吗、怎么做、边界在哪
人工智能·unity·ai编程·游戏开发·商业化·mcp·funplay
晚笙coding1 小时前
从零讲透 LangChain 提示词模板:不只是 Prompt,而是“可复用的 AI 指令工厂”
人工智能·langchain·prompt
吴可可1231 小时前
系统装在移动硬盘的利与弊
机器学习·计算机外设·电脑
码农杂谈00071 小时前
AI + 制造,正在从“能用“迈向“好用“ !网易创新企业大会回顾
人工智能
烟雨江南7851 小时前
地铁越江隧道盾构机控制室大功率液压马达强低频共振降噪与离线智能参数抄报 ASR 方案
人工智能·语音识别·ai质检
RD_daoyi1 小时前
GEO优化能为企业带来哪些价值?
大数据·人工智能·学习·搜索引擎·chatgpt
鲲鹏AI探索局1 小时前
大模型问答里的品牌信息一致性检查:先做定位,再做内容
人工智能·大模型·aigc
Jun6261 小时前
QT(5)-第三方日志系统
开发语言·数据库·qt