此问题已在此处有答案:
How do I find the non differentiable operation in my layer?(1个答案)
5天前关闭。
我目前正在尝试用keras训练一个图像分割模型。我希望我的模型返回一个掩码(只有0和1的图像),应用于输入图像,只得到感兴趣的部分。当我使用mse loss训练我的模型时,它返回的掩码值明显低于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层实现tresholding,也出现了完全相同的错误。我已经经历了很多类似的主题,但到目前为止解决方案都不令人满意。
2条答案
按热度按时间mrfwxfqh1#
您的问题是
tf.where
没有提供渐变(好吧,在这种情况下,因为1.0
和0.0
没有渐变)。然而,你误解了神经网络的一些事情:
1.您的输出为(并且应该)连续正是因为这个原因。在训练模型时,你想知道输出距离你想要的位置有多远,而不仅仅是它是错误的。如果你知道它有多远,你可以慢慢地向它迈进,直到所有你想要为1的值都非常接近1,所有你想为0的值都非常接近于零。它们(几乎)永远不会正好为零。你可以阅读更多关于here的内容。
1.虽然在训练模型时不应该简单地将值四舍五入到0或1,但应该使用类似于sigmoid激活函数的方法将它们引导到这些值。该函数将大多数负数Map到0,将大多数正值Map到1,并且在它们之间具有连续的过渡。
1.虽然在训练时不应该将损失函数中的值四舍五入为0或1,但可以在预测期间对模型的输出进行四舍五入。这将为您提供纯分割图,然后您可以根据需要使用。
uoifb46i2#
我假设这是因为我的函数是不可微的,我怎样才能达到我想要的而没有这样的错误呢?
你不能。神经网络(大多数时候)是用基于梯度的方法(例如反向传播)训练的。你定义的函数有0个梯度,因此不能使用。就是这样。
话虽如此,我相信你是从错误的假设开始的。事实上,你正在有效地寻找对事物进行二进制分类并不意味着你的损失必须这样做(你的掩码只不过是一个多标签分类问题,这个掩码的每个“像素”都是它自己的二进制分类)。特别是典型的二进制分类不会在学习过程中对预测进行二进制分类,你只会在推理过程中这样做。
你要找的是标准的SigmoidCrossEntropy,然后在预测过程中,你只需要把阈值定在0.5。