编程场景痛点训练深度学习模型时参数更新依赖损失函数对每个参数的导数。手动推导链式法则繁琐且容易出错数值微分计算量大不适合高维参数框架自动微分虽然常用但如果不理解计算图与反向传播就难以定位梯度异常、训练震荡和算子实现问题。微积分核心公式单个标量函数的导数定义为\(\frac{dy}{dx} \lim_{\Delta x \to 0} \frac{y(x\Delta x)-y(x)}{\Delta x}\)多元函数中某个输入变量的偏导数表示其他变量固定时该变量对输出的影响\(\frac{\partial y}{\partial x_i}\)链式法则是自动微分的核心。若中间变量 z 依赖 x输出 y 依赖 z则\(\frac{dy}{dx} \frac{dy}{dz}\cdot\frac{dz}{dx}\)反向传播从损失输出开始沿计算图反向累梯度。对参数 \(\theta\)梯度为\(\nabla_{\theta} L \frac{\partial L}{\partial \theta}\)参数更新采用\(\theta \leftarrow \theta - \alpha \cdot \nabla_{\theta} L\)代码实操示例import numpy as np class Tensor: def __init__(self, value, gradNone): self.value np.array(value, dtypenp.float64) self.grad grad class AutoGradScalar: def __init__(self): self.nodes [] def forward(self, x, w, b): x Tensor(x) w Tensor(w) b Tensor(b) z1 Tensor(x.value * w.value) a1 Tensor(np.tanh(z1.value)) z2 Tensor(a1.value * w.value b.value) loss Tensor(z2.value ** 2) self.nodes [x, w, b, z1, a1, z2, loss] return loss.value def backward(self, lr0.01): x, w, b, z1, a1, z2, loss self.nodes d_loss 1.0 d_z2 d_loss * 2.0 * z2.value d_b d_z2 * 1.0 d_w d_z2 * a1.value d_z2 * w.value * (1 - a1.value ** 2) * x.value d_x d_z2 * w.value * (1 - a1.value ** 2) * w.value w.value - lr * np.sum(d_w) b.value - lr * np.sum(d_b) return d_x, d_w, d_b model AutoGradScalar() loss model.forward(x0.5, w1.2, b0.1) dx, dw, db model.backward() print(loss:, loss) print(grad_x:, dx) print(grad_w:, dw) print(grad_b:, db)不同算法对比简表表格方法导数来源计算开销适用场景手动微分人工推导解析式低简单模型、算子验证数值微分有限差分近似高梯度校验、低维函数符号微分代数符号变换中高静态公式推导自动微分计算图链式累梯度低深度学习训练框架解读自动微分不是数值微分也不是纯符号微分它通过计算图记录前向过程并在反向时高效累积梯度。学习总结避坑区分导数、偏导数与梯度导数描述单变量变化率偏导数固定其他变量梯度是损失对参数向量的偏导数集合。计算图由算子组成每个基本算子都需要知道自身局部导数反向传播负责把上游梯度乘进去。数值微分适合校验不适合训练参数很多时数值微分开销随维度增长自动微分更稳定高效。反向传播本质是链式法则框架自动微分把链式法则工程化前向记录计算路径反向执行梯度累积。梯度异常先查算子边界梯度消失、爆炸或NaN通常与激活函数、损失函数、学习率和算子局部导数有关。
阅读完成 · 觉得有帮助?