【问题标题】:Why is PyTorch handling similar weight update assignments differently?为什么 PyTorch 以不同方式处理相似的权重更新分配?
【发布时间】:2020-07-30 18:28:30
【问题描述】:

以下代码确实可以使用以下代码更新权重:

w -= lr * w.grad

但是当使用更新权重时

w = w - lr * w.grad

它把我扔了:

张量的元素 0 不需要 grad 也没有 grad_fn

为什么会这样,两个分配不应该相等?

import torch

X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)
w = torch.tensor(0.0, dtype=torch.float32, requires_grad=True)
epochs = 10
lr = 0.002

for epoch in range(1, epochs + 1):
    y_pred = w * X
    loss = ((y_pred - y)**2).mean()
    loss.backward()
    
    print(w.grad)
    with torch.no_grad():
        ### Option 1 - doesn't work
        w = w - lr * w.grad

        ### Option 2 - does work
        w -= lr * w.grad
        
    w.grad.zero_()

【问题讨论】:

    标签: python pytorch


    【解决方案1】:

    不同之处在于-= 是就地操作,而替代方案不是。因此,当在 .no_grad() 上下文中使用 -= 时,变量将计算操作,但梯度不会考虑该操作。

    当您执行正常减法时,您会期望 SubBackwardgrad_fn

    import torch
    x = torch.tensor([3.], requires_grad=True)
    print(x)
    # >>> tensor([3.], requires_grad=True)
    
    x = x - 2
    print(x)
    # >>> tensor([1.], grad_fn=<SubBackward0>)
    

    确实,这就是我们得到的。但是,如果我们在 .no_grad() 上下文中尝试 -=

    with torch.no_grad():
        x -= 2
    
    print(x)
    # >>> tensor([1.], requires_grad=True)
    

    我们得到了预期的结果(即 2),但没有后向函数(ofc,我们用.no_grad() 指定)。 请注意,它仍然是requires_grad=True。但是,如果我们尝试在 .no_grad() 上下文之外运行这个就地操作,就会发生这种情况:

    x -= 2
    # >>> Traceback (most recent call last):
    # >>>   File "<stdin>", line 1, in <module>
    # >>> RuntimeError: a leaf Variable that requires grad has been used in an in-place operation.
    

    如果我们尝试在.no_grad() 上下文中运行正常的减法,我们将得到:

    x = x - 2
    print(x)
    # >>> tensor([-1.])
    

    一个没有requires_grad的张量;这就是您在使用此选项时收到错误的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2016-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      相关资源
      最近更新 更多