不可微损失函数keras



我目前正在尝试用keras训练图像分割模型。我希望我的模型返回一个掩码(只有0和1的图像),以应用于输入图像,只获得有趣的部分。当我使用mse损失训练我的模型时,它返回的掩码值明显低于1,即使它看起来是收敛的。所以我实现了一个自定义损失函数

def loss(y_true, y_pred):   
tresholded_pred = tf.where(y_pred >= 0.5, 1.0, 0.0)
sq_diff = tf.square(y_true - tresholded_pred)
return tf.reduce_mean(sq_diff, axis=-1)

但是我得到了以下错误:

ValueError: No gradients provided for any variable

我认为这是因为函数的不可微性。我怎样才能达到我想要的而不出现这样的错误呢?

我也试过用lambda层实现阈值,它引发了完全相同的错误。我已经经历了很多类似的话题,但到目前为止,解决方案都不令人满意。

你的问题是tf.where不提供渐变(好吧,在这种情况下,因为1.00.0没有渐变)。

然而,你误解了一些关于神经网络的事情:

  1. 正是由于这个原因,您的输出是(并且应该是)连续的。在训练你的模型时,你想知道输出离你想要的地方有多远,而不仅仅是它是错误的。如果你知道它有多远,你可以慢慢地向它靠近,直到所有你想要的值都非常接近1,所有你想要的值都非常接近0。它们(几乎)永远不会完全为零。你可以在这里阅读更多。
  2. 虽然在训练模型时不应该简单地将值四舍五入到0或1,但应该使用类似于应用于输出的s形激活函数的东西来诱导它们达到这些值。该函数将大多数负数映射为0,将大多数正值映射为1,并在它们之间进行连续转换。
  3. 虽然你不应该在训练时将损失函数的值四舍五入到0或1,但你可以在预测期间将模型的输出四舍五入。这将为您提供纯分割图,然后您可以根据需要使用。

我认为这是因为我的函数不可微。我怎样才能达到我想要的而不出现这样的错误呢?

你不能。神经网络(大多数时候)是用基于梯度的方法来训练的。(如反向传播)。您定义的函数有0个梯度,因此不能使用。就是这样。

话虽如此,我相信你从错误的假设开始。你正在有效地寻找对事物进行二元分类的事实并不意味着你的损失必须这样做(你的掩码只不过是一个多标签分类问题,每个像素;这个掩码本身就是一个二元分类)。特别是典型的二元分类不会在学习过程中对预测进行二值化,只会在推理过程中进行二值化。

你要找的是标准的SigmoidCrossEntropy。在预测过程中,你的阈值是0.5。