QUESTION

反向传播做了什么,参数究竟在哪里更新?

A

反向传播负责计算梯度,优化器才真正修改参数;从一次训练迭代看清二者的分工。

DETAILED ANSWER

直接结论

loss.backward()根据链式法则计算损失对各参数的梯度,并写入参数的.gradoptimizer.step()读取这些梯度,才真正修改模型参数。反向传播和参数更新是前后相接但职责不同的两步。

完整训练链路

输入数据
→ 正向传播得到预测值
→ 预测值与真实标签计算Loss
→ loss.backward()计算梯度
→ optimizer.step()更新参数

最基础的参数更新可以写成:

新w = 旧w − 学习率 × w的梯度

PyTorch中的典型顺序是:

optimizer.zero_grad()
y_pred = model(x)
loss = loss_fn(y_pred, y)
loss.backward()
optimizer.step()
  • optimizer.zero_grad():清除上一轮保存在.grad中的梯度。
  • model(x):使用当前参数完成正向传播。
  • loss_fn(...):计算一个标量损失。
  • loss.backward():计算各参数梯度,但不修改参数。
  • optimizer.step():根据梯度和优化规则修改参数。

RNN中的BPTT为什么会累加梯度

RNN在多个时间步重复使用同一个W_hh。因此,每个时间步都会对同一个参数产生一部分梯度贡献,反向传播时这些贡献最终累加到同一个W_hh.grad

h1 = W
h2 = W²
h3 = W³

L = h1 + h2 + h3
  = W + W² + W³

dL/dW = 1 + 2W + 3W²

“多个时间步的梯度贡献”不是产生多套W,而是同一个共享参数的最终梯度由多条计算路径共同组成。

补充:交叉熵和argmax不能互换

训练:logits → CrossEntropyLoss → backward
预测:logits → argmax → 类别编号

交叉熵衡量预测分布与真实标签之间的差异,可以用于反向传播;argmax只选择分数最大的类别,不能代替训练损失。

面试口述

正向传播负责计算预测结果和损失,反向传播利用链式法则计算损失对各参数的梯度,并把梯度写入参数的.grad。真正修改参数的是optimizer.step()。RNN中同一套循环参数会在多个时间步重复使用,因此BPTT会把各时间步对共享参数的梯度贡献累加起来。