1

我发现 pytorch 对待张量赋值和加法赋值的方式不同。示例如下所示

x = torch.tensor(3.0)
print(id(x))
x = x + 5
print(id(x))

结果是

1647247869184
1647248066816

如果我们运行以下代码

x = torch.tensor(3.0)
print(id(x))
x += 5
print(id(x))

, 结果是

1647175563712
1647175563712

从这两个例子可以看出,使用加法赋值不会改变变量地址,而加法会改变地址。这对训练神经网络有影响。例如,在 pytorch 教程“什么是 torch.nn 真的?”中,有一段代码如下所示

from IPython.core.debugger import set_trace

lr = 0.5  # learning rate
epochs = 2  # how many epochs to train for

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        #         set_trace()
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        with torch.no_grad():
            weights -= weights.grad * lr
            bias -= bias.grad * lr
            weights.grad.zero_()
            bias.grad.zero_()

我们可以看到在 torch.no_grad() 上下文中,使用了减号赋值。如果我们将减号分配更改为如下所示的正常分配,则代码不起作用。

        with torch.no_grad():
            weights = weights - weights.grad * lr
            bias = bias - bias.grad * lr
            weights.grad.zero_()
            bias.grad.zero_()

现在,我知道如果我们不想更改变量,应该使用 += 或 -= 。但是,在python中,+=和=没有区别,两者都改变​​变量地址。示例如下所示:

x = 3
print(id(x))
x += 1
print(id(x))
x = x + 1
print(id(x))
140736084850528
140736084850560
140736084850592

我的问题是

  • 为什么 pytorch 中存在 += 和 = 之间的区别?是故意的吗?
  • 允许差异存在有什么好处?
4

1 回答 1

0

+=是一个就地操作,即它修改原始变量的内容而不复制它(保留相同的内存地址)。

其他示例:

  • x *= 3
  • X[…] = …</li>
  • X.add_(1)

weights = weights - weights.grad * lr中,它不起作用,因为您正在创建一个新变量(不同的地址,只是它也具有名称权重)。

顺便说一句,在 pytorch 的优化器中,它是这样实现的:

weights.add_(weights.grad, alpha=-lr)
于 2021-07-31T07:49:23.153 回答