【问题标题】:How to get iou of single class in keras semantic segmentation?keras语义分割中如何获取单类的iou?
【发布时间】:2021-06-22 14:07:06
【问题描述】:

我正在使用fchollet 的图像分割指南来执行语义分割。我尝试通过将 8 位 img 掩码值标记为 1 和 2 来修改指南以适应我的数据集,就像在 Oxford Pets 数据集中一样。 (将在class OxfordPets(keras.utils.Sequence): 中减去 0 和 1)

问题是如何获得单个类的 IoU 指标(例如 1)?

我尝试了 Stack Overflow 建议的不同指标,但大多数人建议使用我尝试过的 MeanIoU,但结果我得到了 nan loss。这是使用自动对比度后的蒙版示例。 PIL.ImageOps.autocontrast(load_img(val_target_img_paths[i]))

该模型似乎训练得很好,但准确度随着时间的推移而下降。

另外,有人可以帮助解释如何从y_truey_pred 计算指标分数吗? 我不太清楚何时在 IoU 指标计算中使用标签值.

【问题讨论】:

    标签: python keras metrics image-segmentation


    【解决方案1】:

    我当时也有类似的问题。我使用了jaccard_distance_lossdice_metric。它们基于 IoU。我的任务是二进制分割,所以我猜你可能需要修改代码,以防你想将它用于多标签分类问题。

    from keras import backend as K
    
    def jaccard_distance_loss(y_true, y_pred, smooth=100):
        """
        Jaccard = (|X & Y|)/ (|X|+ |Y| - |X & Y|)
                = sum(|A*B|)/(sum(|A|)+sum(|B|)-sum(|A*B|))
        
        The jaccard distance loss is usefull for unbalanced datasets. This has been
        shifted so it converges on 0 and is smoothed to avoid exploding or disapearing
        gradient.
        
        Ref: https://en.wikipedia.org/wiki/Jaccard_index
        
        @url: https://gist.github.com/wassname/f1452b748efcbeb4cb9b1d059dce6f96
        @author: wassname
        """
        intersection = K.sum(K.sum(K.abs(y_true * y_pred), axis=-1))
        sum_ = K.sum(K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1))
        jac = (intersection + smooth) / (sum_ - intersection + smooth)
        return (1 - jac) * smooth
    
    def dice_metric(y_pred, y_true):
        intersection = K.sum(K.sum(K.abs(y_true * y_pred), axis=-1))
        union = K.sum(K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1))
        # if y_pred.sum() == 0 and y_pred.sum() == 0:
        #     return 1.0
    
        return 2*intersection / union
    
    # Example
    size = 10
    
    y_true = np.zeros(shape=(size,size))
    y_true[3:6,3:6] = 1
    
    y_pred = np.zeros(shape=(size,size))
    y_pred[3:5,3:5] = 1
    
    loss = jaccard_distance_loss(y_true,y_pred)
    
    metric = dice_metric(y_pred,y_true)
    
    print(f"loss: {loss}")
    print(f"dice_metric: {metric}")
    
    
    loss: 4.587155963302747
    dice_metric: 0.6153846153846154
    

    【讨论】:

    • 对于您的掩码,您是否使用 0 和 1 进行二进制分割?
    • 是的,1s 是我的前景,0s 是背景。
    • 对了有帮助吗?如果确实如此,那么接受这个答案来帮助其他人会很棒。
    • 是的!我认为我的数据集有问题,因为改组数据集导致 jaccard_distance_loss 返回的分数大相径庭。此外,即使在以 1e-5 的低学习率进行训练后,骰子指标也没有提高。
    • 我明白了。确保在将数据集提供给模型之前对其进行规范化。另外仅供参考,我的损失约为 5,指标约为 0.4,但对测试数据集的预测还不错。一般来说,语义图像分割很难获得高精度,因为模型预测的是图像(例如 256×256 像素),而不是实例(例如猫、狗)。祝你工作顺利!
    猜你喜欢
    • 2019-10-31
    • 2018-06-23
    • 2019-01-06
    • 1970-01-01
    • 2017-10-17
    • 2021-05-04
    • 2019-12-20
    • 2018-12-09
    • 2021-11-19
    相关资源
    最近更新 更多