我正在使用1d卷积网络进行二进制分类。出于研究目的,我必须实现自己的损失函数,该函数类似于BCELoss。因此,我开始尝试通过autograd实现自己的BCE损失功能:
class DiscriminatorLoss(torch.autograd.Function):
@staticmethod
def forward(ctx,d_out,labels):
loss = labels*torch.log(d_out)+(1-labels)*torch.log(1-d_out)
ctx.d_out,ctx.labels = input,labels
return loss
@staticmethod
def backward(ctx, grad_output):
d_out,labels = ctx.d_out,ctx.labels
grad_input = -labels/d_out + ((1-labels)/(1-d_out))
return grad_input,None
d_out
和labels
的张量如下:
d_out=tensor([[0.5412, 0.5225], | labels=tensor([[0, 1],
[0.5486, 0.5167], | [0, 1],
[0.5391, 0.5061],...])| [0, 1],...])
但是,这不能正常工作。问题在于,在训练过程的中间,网络(d_out
)的输出会变成奇怪的值,例如:
tensor([[9.9000e-08, 9.9000e-01],
[9.9000e-08, 9.9000e-01],
[9.9000e-08, 9.9000e-01],....])
在接下来的培训中,它会卡在那里。
我还从Pytorch nn.BCELoss()
(https://pytorch.org/docs/stable/nn.html#loss-functions)实现了BCELoss功能。有了这个功能,网络就可以工作了,所以我认为问题出在我的损失功能上。更确切地说,forward()可以很好地工作,因为它返回的损失与nn.BCELoss相同。因此问题出在 backward()。
有人可以帮助我吗?我在backward()函数中做错了什么?
谢谢!
PS .:为了避免在交叉熵损失中生成NaN
和-inf
值,网络的输出不完全为0或1。