我在使用Sigmoid和BCELoss时实现了用于二进制分割的UNet。问题是,在几次迭代之后,网络尝试预测每个像素的非常小的值,而对于某些区域,它应该预测接近1的值(对于地面实况掩模区域)。它是否对错误的行为有任何直觉?
此外,存在用于像素丢失的NLLLoss2d。目前,我只是忽略了这一点,我直接使用MSELoss()。我应该使用带有Sigmoid激活层的NLLLoss2d吗?
由于
答案 0 :(得分:1)
在我看来,你的Sigmoids正在使激活地图饱和。图像未正确标准化或缺少某些批量标准化层。如果您有一个与其他图像一起使用的实现,请检查图像加载器并确保它不会使像素值饱和。这通常发生在16位通道上。你能分享一些输入图像吗?
PS很抱歉在答案中发表评论。这是一个新帐户,我暂时不能发表评论。
答案 1 :(得分:1)
您可能想要使用torch.nn.BCEWithLogitsLoss()
,替换Sigmoid和BCELoss函数。
docs的摘录告诉您为什么总是更好地使用此损失函数实现。
这种损失将Sigmoid层和BCELoss组合在一个单独的类中。这个版本在数值上比使用普通Sigmoid后跟BCELoss更稳定,因为通过将操作组合成一个层,我们利用log-sum-exp技巧来实现数值稳定性。