我有一个用 f()
表示的模型,
假设目标是t
、f(x1) = y1
和f(x2) = y2
,我的损失定义为
loss = mse(y1,y2) + mse(y2,t)
由于 y1
和 y2
都要求 grad,我收到了诸如
梯度计算所需的变量之一已被原位操作修改
我的理解是,假设我先评估 y1,图表在我评估 y2 时发生了变化。我应该修复一些张量,例如,y1_no_grad = y1.detach().numpy()
然后使用
loss = mse(y1_no_grad,y2) + mse(y2,t)
?
但是,我仍然收到错误 Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy()
,我不确定这是不是因为 y1_no_grad 是一个 numpy 数组而 y2 是一个张量。
更新:
后来我意识到了我的问题。这是因为我创建了多个损失张量,并且我先倒退了一个损失张量,从而就地更改了参数。当我想后退另一个损失张量时,这会导致错误。
例如
f(x1) = y1
f(x2) = y2
f(x3) = y3
...
f(xn) = yn
f(x) = y
for i in range(n):
optimizer.zero_grad()
loss = mse(y,yi) + mse(yi,t)
loss.backward()
optimizer.step()
对我来说,解决方案是:
1.在向后做之前累积损失张量,即
for i in range(n):
loss = mse(y,yi) + mse(yi,t)
loss.backward()
optimizer.step()
2.在每次向后之前再次求值,即:
for i in range(n):
optimizer.zero_grad()
y = f(x)
yi = f(xi)
loss = mse(y,yi) + mse(yi,t)
loss.backward()
optimizer.step()
答案 0 :(得分:1)
假设目标是t
、f(x1) = y1
和f(x2) = y2
,我的损失定义为
loss = mse(y1,y2) + mse(y2,t)
由于 y1
和 y2
都要求 grad,我收到了诸如
这个说法是错误的。您所描述的内容不需要就地分配错误。例如
import torch
from torch.nn.functional import mse_loss
def f(x):
return x**2
t = torch.ones(1)
x1 = torch.randn(1, requires_grad=True)
x2 = torch.randn(1, requires_grad=True)
y1 = f(x1)
y2 = f(x2)
loss = mse_loss(y1, y2) + mse_loss(y2, t)
loss.backward()
不会产生任何错误。您的问题可能出在其他地方。
对于你描述的一般情况,你应该得到一个可以可视化的计算图
这里唯一的问题可能是您的函数 f
不可微分或以某种方式无效(可能在就地分配中发生在 f
中)。