摘要:神经网络的"学习"本质上是一个优化问题------找到一组参数让模型的预测误差最小。反向传播和梯度下降就是解决这个问题的核心算法。这篇文章从直观到数学,讲清楚神经网络训练的底层逻辑。
一、学习的本质:一个优化问题
上一篇文章我们知道了神经网络的结构:输入层 → 隐藏层 → 输出层,每层之间有带权重的连接。
但一个关键问题没回答:这些权重是怎么自动学出来的?
把问题拆开看:
给定:一个训练数据集(输入 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 最常用) |
| 过拟合 | 考试答案背得太熟,题目一变就懵 |
| 梯度消失/爆炸 | 梯度在传递过程中变得太大或太小 |
核心三句话:
- 正向传播 计算预测结果,反向传播计算梯度方向
- 梯度下降沿着梯度反方向更新参数
- 循环以上两步足够多次 → 网络学会完成任务
这就是深度学习的"学习"过程------不神秘,但极其优雅。