Dice coef greater than 1
Asked Answered
C

1

8

As I was training UNET, the dice coef and iou sometimes become greater than 1 and iou > dice, then after several batches they would become normal again. As shown in the picture.

I have defined them as following:

def dice_coef(y_true, y_pred, smooth=1):
    y_true_f = K.flatten(y_true)
    y_pred_f = K.flatten(y_pred)
    intersection = K.sum(y_true_f * y_pred_f)
    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)

def iou(y_true, y_pred, smooth=1):
    y_true_f = K.flatten(y_true)
    y_pred_f = K.flatten(y_pred)
    intersection = K.sum(y_true_f * y_pred_f)
    union = K.sum(y_true_f) + K.sum(y_pred_f) - intersection
    return (intersection + smooth) / (union + smooth)

def dice_loss(y_true, y_pred):
    return 1. - dice_coef(y_true, y_pred)

I have tried adding K.abs() to y_pred but that results in a worse performance. I feel that since the output is sigmoid activated whether adding K.abs() or not should give the same result? Also, as you can see my accuracy is weird, I have been relying on dice to judge my model performance, would be greater if someone can point out the issue.

Calamitous answered 6/2, 2020 at 8:14 Comment(5)
Are your y_true images really between 0 and 1? Check this.Ferrocene
Maybe you could share your model.summary(), the definition of your layers (at least the final layers), the "measured" shapes and ranges of y_true. (I know you said it's ok, but sometimes we get mistaken, every one of us :p)Ferrocene
You are right!!! my y_ture is not in (0,1) :( i've fixed it thanksCalamitous
Cool :) -- So if you think it solved everything, please mark the answer as valid :)Ferrocene
Yes, I encountered same issue and when I saw my y_true values they were not normalized, so just make sure you normalize labels.Dictate
A
10

I believe your y_true images might not be in the range between 0 and 1.... are you sure they're not between 0 and 255? Or that they have a single channel (instead of 3 channels?)

This should not be the cause, but you're using a batch dice, you should use an image dice:

def dice_coef(y_true, y_pred, smooth=1):
    y_true_f = K.batch_flatten(y_true)
    y_pred_f = K.batch_flatten(y_pred)

    intersection = K.sum(y_true_f * y_pred_f, axis=-1)
    sums = K.sum(y_true_f, axis=-1) + K.sum(y_pred_f, axis=-1)

    return (2. * intersection + smooth) / (sums + smooth)

Usually, I use K.epsilon() for "smooth" (something very small).

The same goes for iou:

def iou(y_true, y_pred, smooth=1):
    y_true_f = K.batch_flatten(y_true)
    y_pred_f = K.batch_flatten(y_pred)

    intersection = K.sum(y_true_f * y_pred_f, axis=-1)
    union = K.sum(y_true_f, axis=-1) + K.sum(y_pred_f, axis=-1) - intersection
    return (intersection + smooth) / (union + smooth)

Example of a channel dice:

#considering shape (batch, classes, image_size, image_size)
def dice_coef(y_true, y_pred, smooth=1):

    intersection = K.sum(y_true * y_pred, axis=[2,3])
    sums = K.sum(y_true, axis=[2,3]) + K.sum(y_pred, axis=[2,3])

    dice = (2. * intersection + smooth) / (sums + smooth)
    return K.mean(dice, axis=-1)
Activity answered 6/2, 2020 at 12:49 Comment(3)
My y_true is 1 or 0 and of shape (None, 3, 512, 512), but it's not RBG but 3 greyscale masks concatenated on axis = 1. I used "channel first" data format. May I know why should I use image dice? and why would batch dice > 1?Calamitous
The problem is not batch dice. This is not the cause of > 1, and I still believe there is something wrong with either y_true or y_pred. --- Using image dice is better because a batch dice will work well for big masks, but very very poorly for small masks.Ferrocene
You could even try a channel dice, since you have 3 channels there.Ferrocene

© 2022 - 2024 — McMap. All rights reserved.