问题与目标
前向传播将输入变成预测,损失函数将预测误差压缩为一个可优化的标量,反向传播再计算每个参数对损失的影响。这三步构成了神经网络学习的主干。
本篇不展开复杂矩阵求导,而是通过一个两参数模型,对照解析梯度与数值梯度。输入是一组 x、y,输出是更新前后的损失和参数。

实线表示前向计算从参数到损失的数据流,虚线表示梯度按链式法则逐步返回。
核心概念
计算图记录运算关系
对线性模型 prediction = weight * x + bias,一次计算可拆成:
weight, x --乘法--> weighted
weighted, bias --加法--> prediction
prediction, y --减法--> error
error --平方与平均--> loss
前向计算保留 weighted、prediction、error 等中间结果。反向计算从 loss 开始,沿相反方向使用局部导数。
链式法则连接局部变化
如果 loss 依赖 prediction,prediction 又依赖 weight,则:
d(loss) / d(weight)
= d(loss) / d(prediction) * d(prediction) / d(weight)
神经网络层数增多后,本质仍是从后向前反复应用链式法则。反向传播的效率来自复用已经计算的中间梯度,而不是为每个参数从头求导。
损失与指标有不同职责
| 任务 | 常用训练损失 | 常用报告指标 |
|---|---|---|
| 回归 | MSE、Smooth L1 | MAE、RMSE、R² |
| 二分类 | 二元交叉熵 | 精确率、召回率、F1、PR-AUC |
| 多分类 | 多类交叉熵 | Accuracy、Macro-F1、混淆矩阵 |
损失需要能稳定地产生梯度,指标则需要表达真实任务目标。准确率等离散指标不适合直接用梯度优化。
梯度不是参数更新值
梯度表示“参数增加一点时,损失如何变化”。梯度下降沿反方向更新:
parameter = parameter - learning_rate * gradient
学习率控制步长。步长过大可能跨过低点甚至发散,过小则损失下降缓慢。
可运行实现
import numpy as np
x = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([3.0, 5.0, 7.0, 9.0])
weight = 0.5
bias = 0.0
learning_rate = 0.05
def mse(current_weight: float, current_bias: float) -> float:
prediction = current_weight * x + current_bias
return float(np.mean((prediction - y) ** 2))
before = mse(weight, bias)
prediction = weight * x + bias
error = prediction - y
weight_gradient = 2 * np.mean(error * x)
bias_gradient = 2 * np.mean(error)
epsilon = 1e-5
numeric_weight_gradient = (
mse(weight + epsilon, bias) - mse(weight - epsilon, bias)
) / (2 * epsilon)
numeric_bias_gradient = (
mse(weight, bias + epsilon) - mse(weight, bias - epsilon)
) / (2 * epsilon)
print("analytic:", round(float(weight_gradient), 6), round(float(bias_gradient), 6))
print("numeric:", round(numeric_weight_gradient, 6), round(numeric_bias_gradient, 6))
weight -= learning_rate * weight_gradient
bias -= learning_rate * bias_gradient
after = mse(weight, bias)
print("loss:", round(before, 6), "->", round(after, 6))
print("parameters:", round(float(weight), 3), round(float(bias), 3))
两组梯度应该非常接近,一次更新后损失应下降。数值梯度需要对每个参数多运行两次前向计算,大网络中成本过高,因此主要用于梯度检查,不是日常训练方法。
一次更新不代表训练完成
完整训练会在多个批次和多个 epoch 中重复:
前向传播 -> 计算损失 -> 清空旧梯度
-> 反向传播 -> 更新参数 -> 进入下一批
不能只检查最后损失。训练与验证曲线、梯度范围、输入分布和独立指标都是诊断信号。
常见问题与排查
- 损失持续增大:先降低学习率,再检查梯度符号、数据尺度和损失实现。
- 数值梯度与解析梯度不同:检查平均系数、转置、广播和
epsilon大小。 - 每次反向都累加旧梯度:PyTorch 默认累加
.grad,每个优化步要明确清空。 - 修改参数后损失没有下降:单步不保证所有学习率都下降,可用更小步长验证方向。
- 认为反向传播就是优化器:反向传播计算梯度,优化器使用梯度更新参数。
小结
计算图描述运算依赖,链式法则将局部导数连成参数梯度,优化器再根据梯度和学习率更新参数。能用数值梯度验证一个小模型,就能把“模型在学习”还原成可检查的计算步骤。
License: CC BY-NC 4.0
Updated 2 hours ago
Was this article helpful? Give it a like.
0 comments


