You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 07:25:23