PyTorch训练出现Trying to backward through the graph a second time错误如何解决
问题分析
错误原因
触发该报错的核心原因是作为输入和标签的张量错误携带了梯度计算关联的计算图:
- 输入张量
x被设置了requires_grad=True,但本次训练的优化目标仅为w和b,输入x是固定样本,无需参与梯度计算。 - 标签
y通过开启了梯度的x计算得到,自身也携带了关联的计算图节点,反向传播时会被纳入计算图的回溯链路。 - 仅在每次迭代中清空了优化器管理的
w、b的梯度,未处理x的梯度,第一次反向传播结束后关联x和y的计算图被默认释放,第二次迭代反向传播时尝试回溯已经被销毁的计算图节点,触发报错。
解决方法
根据使用场景选择对应方案即可:
常规训练场景(无需对输入x求梯度,适配当前代码需求)
直接关闭输入x的梯度即可,修改后可正常运行:
import torch # 关闭x的requires_grad,输入样本无需计算梯度 x = torch.rand(10) # 此时计算得到的y默认也不会开启梯度,符合标签属性要求 y = x * 15. + 10. optimizer = torch.optim.Adam loss = torch.nn.MSELoss() def train(x, y, loss, ep, opti): w = torch.rand(1, dtype=torch.float32, requires_grad=True) b = torch.rand(1, dtype=torch.float32, requires_grad=True) op = opti([w, b]) for e in range(ep): y_hat = x.multiply(w) + b l = loss(y_hat, y) print(f'Epoch: {e}, loss: {l}') l.backward() op.step() op.zero_grad() return w, b # 可将epoch调大至1000左右,可拟合得到接近15的w和接近10的b w_hat, b_hat = train(x, y, loss, 1000, optimizer) print(w_hat, b_hat)
特殊需求场景(需保留x的梯度)
如果业务逻辑需要保留x的requires_grad=True属性,做两处修改即可:
- 定义y时添加
.detach()截断计算图:y = (x * 15. + 10.).detach() - 每次调用
l.backward()后添加x.grad = None手动清空x的梯度
内容的提问来源于stack exchange,提问作者3nomis
相关产品推荐
相关产品推荐

