简体   繁体   English

keras语义分割中如何获取单个class的iou?

[英]How to get iou of single class in keras semantic segmentation?

I am using the Image segmentation guide by fchollet to perform semantic segmentation.我正在使用fchollet的图像分割指南来执行语义分割。 I have attempted modifying the guide to suit my dataset by labelling the 8-bit img mask values into 1 and 2 like in the Oxford Pets dataset.我尝试通过将 8 位 img 掩码值标记为 1 和 2 来修改指南以适应我的数据集,就像在 Oxford Pets 数据集中一样。 (which will be subtracted to 0 and 1 in class OxfordPets(keras.utils.Sequence): ) (将在class OxfordPets(keras.utils.Sequence):中减去 0 和 1:)

Question is how do I get the IoU metric of a single class (eg 1)?问题是如何获得单个 class(例如 1)的 IoU 指标

I have tried different metrics suggested by Stack Overflow but most of suggest using MeanIoU which I tried but I have gotten nan loss as a result.我尝试了 Stack Overflow 建议的不同指标,但大多数人建议使用我尝试过的 MeanIoU,但结果我得到了nan 损失 Here is an example of a mask after using autocontrast.这是使用自动对比度后的蒙版示例。 PIL.ImageOps.autocontrast(load_img(val_target_img_paths[i])) 在此处输入图像描述

The model seems to train well but the accuracy was decreasing over time. model 似乎训练得很好,但精度随着时间的推移而下降。

Also, can someone help explain how the metric score can be calculated from y_true and y_pred ?另外,有人可以帮助解释如何从y_truey_pred计算指标分数吗? I don't quite fully understand when the label value is used in the IoU metric calculation.我不太明白何时在 IoU 度量计算中使用 label 值。

I had a similar problem back then.我当时也有类似的问题。 I used jaccard_distance_loss and dice_metric .我使用jaccard_distance_lossdice_metric They are based on IoU.它们基于 IoU。 My task was a binary segmentation, so I guess you might have to modify the code in case you want to use it for a multi-label classification problem.我的任务是二进制分割,所以我猜你可能需要修改代码,以防你想将它用于多标签分类问题。

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

You can use the tf.keras.metrics.IoU method, and you can find its documentation here:https://www.tensorflow.org/api_docs/python/tf/keras/metrics/IoU您可以使用tf.keras.metrics.IoU方法,您可以在此处找到其文档:https://www.tensorflow.org/metric/ts/docsoU///ker

And how you can use it is shown here:此处显示了如何使用它:

import tensorflow as tf

y_true = [0, 1]
y_pred = [0.5, 1.0]  # they must be the same shape

# target_class_ids indicates the class/classes you want to calculate IoU on
loss = tf.keras.metrics.IoU(num_classes=2, target_class_ids=[1])
loss.update_state(y_true, y_pred)
print(loss.result().numpy())

And as you can see in the documentation, IoU is calculated by:正如您在文档中看到的那样,IoU 的计算公式为:

true_positives / (true_positives + false_positives + false_negatives)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM