我正在尝试将u-net与keras实现一起使用,我正在使用以下回购协议
https://github.com/zhixuhao/unet
它运作良好,但我的问题是两类分割问题,因此我想将准确度指标设置为jaccard,同时还要设置损失函数

我试图定义函数:

def Jac(y_true, y_pred):
    y_pred_f = K.flatten(K.round(y_pred))
    y_true_f = K.flatten(y_true)
    num = K.sum(y_true_f * y_pred_f)
    den = K.sum(y_true_f) + K.sum(y_pred_f) - num
    return num / den


并在编译中调用它:

model.compile(optimizer = Adam(lr = 1e-4), loss = ['binary_crossentropy'], metrics = [Jac])


当我这样做时,每次迭代中的jaccard精度都会降低,直到达到零!
为什么会发生这种情况的任何解释?
附注:骰子也会发生同样的事情。
P.S:输出层是conv 1 * 1,具有S型激活功能

更新:

在keras中附加了二进制精度的原始实现:

def binary_accuracy(y_true, y_pred):
    return K.mean(K.equal(y_true, K.round(y_pred)), axis=-1)


而且我可以看到它也使用舍入来获得输出预测。

最佳答案

您正在舍入函数(K.round)。

这导致两个问题:


(实际问题)该函数不可微且将不能成为损失函数(将显示“不支持任何值”错误)
只要您的网络不确定并具有小于0.5的任何值,这些值将被视为零。


如果y_true中的黑色(零)像素数量大于白色(1)像素,则会发生这种情况:


您的网络将倾向于先将所有内容预测为零,这确实会导致更好的二进制交叉熵损失!


如果不是四舍五入的话,还有更好的Jaccard
但如果舍入为零,则Jaccard为零

并且只有稍后,当对学习速率进行更精细的调整时,它将开始将白色像素显示在应有的位置。


由于上述两个原因,您实际上应该使用非四舍五入函数。
有时绘制输出以查看发生了什么:)

请注意,如果您将此函数用作损失函数,请将其乘以-1(因为您希望它减少而不是增加)

关于python - 使用keras在u-net中实现零Jaccard准确性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49296099/

10-11 16:39