【问题标题】:Zero Jaccard accuracy in u-net implementation with keras使用 keras 实现 u-net 的 Jaccard 精度为零
【发布时间】:2018-03-15 09:47:39
【问题描述】:

我正在尝试将 u-net 与 keras 实现一起使用,我正在使用以下 repo 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:骰子也会发生同样的事情。
P.S:输出层是conv 1 * 1,带有sigmoid激活函数

更新:

附上keras中二进制精度的原始实现:

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

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

【问题讨论】:

    标签: python machine-learning deep-learning keras image-segmentation


    【解决方案1】:

    你正在四舍五入你的函数 (K.round)。

    这会导致两个问题:

    • (真正的问题)该函数不可微,不能作为损失函数(将显示“None values not supported”错误)
    • 当您的网络不确定并且有任何低于 0.5 的值时,这些值将被视为零。

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

    • 您的网络将倾向于首先将所有内容预测为零,这确实会导致更好的二元交叉熵损失!
      • 如果不是圆角,也是更好的 Jaccard
      • 但如果四舍五入则为零 Jaccard
    • 只有稍后,当学习率调整得更精细时,它才会开始将白色像素带出它们应该在的位置。

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

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

    【讨论】:

    • 谢谢!,我知道微分问题,但我用它作为准确度指标,而不是损失函数,关于舍入,我想我需要舍入才能知道输出预测网络作为两个类,如果我让它不圆整(连续),那么我怎么知道这两个类,因此我如何测量与基本事实相比的输出精度??
    • 你只需要对“输出”进行四舍五入,并且只有“当你想要”的时候才能知道类。如果你想要一个指标,不要四舍五入,因为你会想看到网络的演变。当值在 0 和 0.5 之间时,您看不到从黑色图像到正确图像的演变。
    • hmmm,我不明白,Jaccard 本身(还有 Dice)旨在查看两个图像重叠的程度!所以我们将它们相乘并计算个数,所以两个输入图像(基本事实和预测)必须是二进制另一件事:请检查我附加的更新
    • 使用神经网络时没有“二进制”。他们总是“连续”地工作。如果您放置度量二进制文件,您将“看不到它不断发展”(但您的网络正在不断发展)。您可以使用两个指标,一个二进制表示“您想要的实际价值”,另一个连续,这样您就可以看到正在发生的事情。
    • 如果你只使用二进制度量,你将不得不等待所有的训练,直到你的网络最终开始输出大于 0.5 的值,直到那时你只会看到零,如答案中所述。
    【解决方案2】:

    试试下面这些功能,复制自github。在 keras 指标中使用 jacard_coef,如果你想要 jacard_coef_loss keras loss

    def jacard_coef(y_true, y_pred):
        y_true_f = K.flatten(y_true)
        y_pred_f = K.flatten(y_pred)
        intersection = K.sum(y_true_f * y_pred_f)
        return (intersection + 1.0) / (K.sum(y_true_f) + K.sum(y_pred_f) - intersection + 1.0)
    
    
    def jacard_coef_loss(y_true, y_pred):
        return -jacard_coef(y_true, y_pred)
    
    model.compile(optimizer = Adam(lr = 1e-4), loss = [jacard_coef_loss], metrics = [jacard_coef])
    

    【讨论】:

    • 我以前见过这些函数,除了他加了(1.0用于平滑和避免除零)之外,它和我的一样,它也归零
    • 我有,但问题仍然存在,损失函数应该对改变出现的准确度没有影响,我只是改变了指标但所有的训练过程都是一样的
    • 是的,您是否正确理解了问题?例如,它从精度 0.1 开始,然后逐渐减小到零,这是不合逻辑的!同时它在传统的二进制精度下工作得很好
    猜你喜欢
    • 2023-03-29
    • 2020-01-27
    • 1970-01-01
    • 2020-09-07
    • 1970-01-01
    • 2019-10-18
    • 2020-05-04
    • 1970-01-01
    • 2019-04-18
    相关资源
    最近更新 更多