PyTorch优化器对叶子变量的原地操作为何不报错?
问题:叶子变量原地操作触发报错,但Optimizer.step()无报错的原因
当对叶子变量执行原地操作时会触发报错,示例代码如下:
import torch x = torch.tensor([2.0, 10.0], requires_grad=True) y = x[0]**2 + x[1]**2 y.backward() x.add_(0.2, alpha=0.2) # RuntimeError: a leaf Variable that requires grad is being used in an in-place operation.
但在训练循环中的optim.step()方法里,对同为叶子变量的神经网络参数执行原地操作却不会报错。查看step()函数的代码,并未发现with no_grad()语句,其中的原地操作为param.add_(grad, alpha=-lr),且中间未进行梯度分离,因此想知道该方法中的原地操作为何不会引发错误。
解答
你手动操作叶子张量报错的核心原因是:执行y.backward()后,计算图仍处于保留状态,PyTorch需要依赖叶子变量的原始值来维护梯度追踪的完整性,原地修改会直接破坏计算图结构,导致后续若有梯度计算需求时出现错误,因此触发报错。
而Optimizer.step()里的原地操作不会报错,主要有两个关键原因:
- 网络参数属于
nn.Parameter类型,这是PyTorch专为模型参数设计的特殊张量,框架对这类叶子变量的原地更新做了兼容处理。参数更新是训练的标准流程,更新完成后旧的计算图已经完成梯度计算的使命,下一轮迭代会重新构建全新的计算图,不会再依赖旧的参数值,因此允许原地修改。 - 虽然你没在
step()的代码里看到显式的with torch.no_grad(),但PyTorch的优化器内部会隐式地禁用参数更新操作的梯度追踪——也就是说,param.add_()的操作不会被记录到计算图中,自然不会触发叶子变量原地操作的报错。
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

