【问题标题】:binary_cross_entropy_with_logits produces negative outputbinary_cross_entropy_with_logits 产生负输出
【发布时间】:2021-10-06 23:41:43
【问题描述】:

我正在开发一种机器学习模型来检测骨骼图像中的骨骼。 我正在使用pytorch,我使用的模型是hourglass model

当我使用 binary_cross_entropy_with_logits 时,我可以看到损失减少,但是当我尝试测试模型时,我注意到:

  1. 输出永远不会大于零
  2. 输出不正确(未检测到骨骼)。

这就是我调用 binary_cross_entropy_with_logits 的方式

  • loss = F.binary_cross_entropy_with_logits(ouputs[i], Y, weight=Mask, reduction='sum') / Mask.sum()

这就是我正在做的测试

ouput = model(X)
ouput_sig = torch.sigmoid(ouput)
plot_voxel2d(ouput_soft1)

如果我像这样使用 mse 损失,完全相同的模型、输入、目标可以工作:

loss = torch.sum(((ouputs[i] -  Y) ** 2) * Mask) / torch.sum(Mask)

我确保目标在 0 和 1 之间。 感谢您的帮助。

【问题讨论】:

  • 是模型的输出是负数还是损失​​?
  • 它自己的实际输出,我尝试使用权重初始化,我可以让输出在几次迭代中为正,但它会回到 -ve。 nn.init.normal_(m.weight, 0, 1)
  • 你的模型是什么,它是如何定义的?你在输出上应用 sigmoid 吗?我认为这与您的优化器和权重初始化无关。
  • 我注意到,只要涉及 Sigmoid,我就不会收敛,所以如果我使用 MSELoss,它就可以工作。但是如果我使用带有 sigmoid 的 MSELoss 作为最后一层,它就不起作用。最后一层之前的层看起来像:Conv3d -> BatchNorm3d -> ReLU -> Dropout3d -> Conv3d

标签: pytorch loss-function


【解决方案1】:

以下代码块是 G. Hinton 在他的课程中提出的:http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf

optimizer = optim.RMSprop(net.parameters(), lr=0.005, weight_decay=1e-8)
if net.n_classes > 1:
    criterion = nn.CrossEntropyLoss()
else:
    criterion = nn.BCEWithLogitsLoss()

然后你需要使用 sigmoid(Torch 函数式:F.sigmoid),方式与下面的代码示例类似:

for isample, sample in enumerate(ds):
    
    mask_torch = net2(sample['image'][None, :, :, :].type(torch.cuda.FloatTensor))
    mask = (F.sigmoid(mask_torch.type(torch.cuda.FloatTensor)) > 0.4925099).type(torch.FloatTensor)
    print(mask)
 
    for ichan in range(3):
        ax[isample, ichan].imshow(sample['image'][ichan].cpu())
        
    ax[isample, 3].imshow(sample['mask'][0].cpu())
    ax[isample, 4].imshow(mask[0, 0].cpu().detach().numpy())

将 sigmoid 放在所有层之后的末尾。它看起来像这样:

对于 sigmoid,它看起来像这样:

def forward(self, x):
    #print(x.shape)
    x = self.layer_1(x)
    x = self.layer_2(x)
    x = self.layer_3(x)
   
    logits = F.sigmoid(self.outc(x))
    
    return logits

【讨论】:

  • 嗨,Joe,感谢您的建议,将尝试使用 RMSprop,看看它是否有效
  • 我注意到,只要涉及 Sigmoid,我就不会收敛,所以如果我使用 MSELoss,它就可以工作。但是如果我使用带有 sigmoid 的 MSELoss 作为最后一层,它就不起作用。最后一层之前的层看起来像:Conv3d -> BatchNorm3d -> ReLU -> Dropout3d -> Conv3d
  • Sigmoid 应该只出现一次并且在所有层之后持续。
  • 我编辑了上面的代码来提供你的前向传递可能看起来像,如果你只有 3 层。
  • @whyme:你解决了吗?
【解决方案2】:

我已经多次遇到这种情况,每次都是因为标签不在 0 和 1 之间

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 2016-10-19
    • 2017-07-25
    • 2012-01-07
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多