torch.nn.BCELoss() 两个参数的导数
Derivative in both arguments of torch.nn.BCELoss()
在两个参数上使用 torch.nn.BCELoss()
时,这两个参数都是一些早期计算的结果,我得到一些奇怪的错误,这个问题是关于:
RuntimeError: the derivative for 'target' is not implemented
MCVE如下:
import torch
import torch.nn.functional as F
net1 = torch.nn.Linear(1,1)
net2 = torch.nn.Linear(1,1)
loss_fcn = torch.nn.BCELoss()
x = torch.zeros((1,1))
y = F.sigmoid(net1(x)) #make sure y is in range (0,1)
z = F.sigmoid(net2(y)) #make sure z is in range (0,1)
loss = loss_fcn(z, y) #works if we replace y with y.detach()
loss.backward()
事实证明,如果我们在 y
上调用 .detach()
,错误就会消失。但这会导致不同的计算,现在在 .backward()
-pass 中,不会计算关于 BCELoss
的第二个参数的梯度。
谁能解释一下我在这种情况下做错了什么?据我所知 torch.nn
中的所有 pytorch 模块都应该支持计算梯度。这个错误消息似乎告诉我导数没有为 y
实现,这有点奇怪,因为你 可以 计算 y
的梯度,但是不是 y.detach()
这似乎是矛盾的。
看来我误解了错误信息。不是 y
不允许计算梯度,而是 BCELoss()
没有能力计算关于第二个参数的梯度。讨论了类似的问题 here。
我也遇到了同样的问题。据我所知,BCELoss(input, target)
、target
的第二个参数应该是没有梯度属性的张量。这意味着 target.requires_grad
应该是 False。但是不知道为什么。
通常,target
(我们也可以称它为Ground Truth
)没有渐变属性。但是target
(你代码中的y
)是由F.sigmoid(net1(x))
计算出来的,也就是说target
(net1的输出)已经是一个具有梯度属性的张量了。
所以,你应该试试:
loss = loss_fcn(z, y.detach())
或:
loss = loss_fcn(z, y.data)
也许是这个?
import torch
import torch.nn.functional as F
net1 = torch.nn.Linear(1,1)
net2 = torch.nn.Linear(1,1)
loss_fcn = torch.nn.BCELoss()
x = torch.zeros((1,1))
y = F.sigmoid(net1(x)) #make sure y is in range (0,1)
z = F.sigmoid(net2(y)) #make sure z is in range (0,1)
y.retain_grad()
a = y
loss = loss_fcn(z, a.detach()) #works if we replace y with y.detach()
loss.backward()
print(y.grad)
在两个参数上使用 torch.nn.BCELoss()
时,这两个参数都是一些早期计算的结果,我得到一些奇怪的错误,这个问题是关于:
RuntimeError: the derivative for 'target' is not implemented
MCVE如下:
import torch
import torch.nn.functional as F
net1 = torch.nn.Linear(1,1)
net2 = torch.nn.Linear(1,1)
loss_fcn = torch.nn.BCELoss()
x = torch.zeros((1,1))
y = F.sigmoid(net1(x)) #make sure y is in range (0,1)
z = F.sigmoid(net2(y)) #make sure z is in range (0,1)
loss = loss_fcn(z, y) #works if we replace y with y.detach()
loss.backward()
事实证明,如果我们在 y
上调用 .detach()
,错误就会消失。但这会导致不同的计算,现在在 .backward()
-pass 中,不会计算关于 BCELoss
的第二个参数的梯度。
谁能解释一下我在这种情况下做错了什么?据我所知 torch.nn
中的所有 pytorch 模块都应该支持计算梯度。这个错误消息似乎告诉我导数没有为 y
实现,这有点奇怪,因为你 可以 计算 y
的梯度,但是不是 y.detach()
这似乎是矛盾的。
看来我误解了错误信息。不是 y
不允许计算梯度,而是 BCELoss()
没有能力计算关于第二个参数的梯度。讨论了类似的问题 here。
我也遇到了同样的问题。据我所知,BCELoss(input, target)
、target
的第二个参数应该是没有梯度属性的张量。这意味着 target.requires_grad
应该是 False。但是不知道为什么。
通常,target
(我们也可以称它为Ground Truth
)没有渐变属性。但是target
(你代码中的y
)是由F.sigmoid(net1(x))
计算出来的,也就是说target
(net1的输出)已经是一个具有梯度属性的张量了。
所以,你应该试试:
loss = loss_fcn(z, y.detach())
或:
loss = loss_fcn(z, y.data)
也许是这个?
import torch
import torch.nn.functional as F
net1 = torch.nn.Linear(1,1)
net2 = torch.nn.Linear(1,1)
loss_fcn = torch.nn.BCELoss()
x = torch.zeros((1,1))
y = F.sigmoid(net1(x)) #make sure y is in range (0,1)
z = F.sigmoid(net2(y)) #make sure z is in range (0,1)
y.retain_grad()
a = y
loss = loss_fcn(z, a.detach()) #works if we replace y with y.detach()
loss.backward()
print(y.grad)