PyTorch普通赋值与增强赋值的requires_grad差异疑问
PyTorch中两种赋值操作的requires_grad差异解析
这不是PyTorch的框架Bug,而是两种赋值操作的本质逻辑不同导致的,具体原因如下:
1. 两种操作的核心区别
w = w - lr*w.grad:重新创建并赋值新张量
在torch.no_grad()上下文里,所有张量运算的结果都会被标记为requires_grad=False。执行这个语句时,右侧运算会生成一个全新的、不带梯度追踪的张量,随后将这个新张量赋值给变量w——相当于直接替换了原来那个requires_grad=True的张量,所以后续w的梯度追踪状态会变为False。w -= lr*w.grad:原地修改原有张量
这是原地(in-place)操作,它不会创建新的张量,而是直接在原来w的内存空间上修改数值。原来的w张量的requires_grad=True属性会被完整保留,只是因为处于torch.no_grad()上下文,这次数值修改不会被记录到计算图中,所以w依然具备梯度追踪能力。
2. 验证示例
修改测试代码,分别验证两种操作的结果:
import torch import numpy as np def test_stack(): np.random.seed(0) n = 50 feat1 = np.random.randn(n, 1) feat2 = np.random.randn(n, 1) X = torch.tensor(feat1).view(-1, 1) Y = torch.tensor(feat2).view(-1, 1) # 测试重新赋值 w1 = torch.tensor(1.0, requires_grad=True) lr = 0.001 y_pred = w1*X[0] loss = (y_pred - Y[0])**2 loss.backward() with torch.no_grad(): w1 = w1 - lr*w1.grad print("重新赋值后的w1:", w1) print("w1.requires_grad:", w1.requires_grad) # 测试原地操作 w2 = torch.tensor(1.0, requires_grad=True) y_pred = w2*X[0] loss = (y_pred - Y[0])**2 loss.backward() with torch.no_grad(): w2 -= lr*w2.grad print("\n原地操作后的w2:", w2) print("w2.requires_grad:", w2.requires_grad) test_stack()
运行后会输出:
重新赋值后的w1: tensor(0.9871) w1.requires_grad: False 原地操作后的w2: tensor(0.9871, requires_grad=True) w2.requires_grad: True
3. 推荐的参数更新方式
如果想用重新赋值的方式同时保留梯度追踪,可以直接操作张量的data属性:
with torch.no_grad(): w.data = w.data - lr*w.grad.data
不过更推荐使用原地操作(如-=、*=)或者PyTorch内置的优化器(比如torch.optim.SGD)来管理参数更新,这样代码逻辑更清晰,也能避免手动操作带来的属性丢失问题。
内容的提问来源于stack exchange,提问作者Tony Power
相关产品推荐
相关产品推荐

