Reputation: 123
I am trying to build a dice loss for my model (needs segmentation with masks, so I am using IoU metric).
When it comes to the last part, the division between the intersection and union, I can't overcome the 'float division by zero' part. I have tried using a smooth constant (1e-6), the if else
and the try except
clause for the ZeroDivisionError
.
Here's the code:
import numpy as np
def arith_or(array1, array2):
res = []
for a, b in zip(array1, array2):
if a == 1.0 or b == 1.0:
res.append(1.0)
else:
res.append(0.0)
return res
def arith_and(array1, array2):
res = []
for a, b in zip(array1, array2):
if a == 1.0 and b == 1.0:
res.append(1.0)
else:
res.append(0.0)
return res
def dice_loss(y_true, y_pred):
y_true_f = np.ravel(y_true)
y_pred_f = np.ravel(y_pred)
intersection = arith_and(y_true_f, y_pred_f).sum((1, 2))
union = arith_or(y_true_f, y_pred_f).sum((1, 2))
score = ((2.0 * intersection + 1e-6) / (union + 1e-6))
return 1 - score
The error:
ZeroDivisionError Traceback (most recent call last)
<ipython-input-40-886068d106e5> in <module>()
65 output_layer = build_model(input_layer, 16)
66 model = Model(input_layer, output_layer)
---> 67 model.compile(loss=dice_loss, optimizer="adam", metrics=["accuracy"])
2 frames
/content/losers.py in dice_loss(y_true, y_pred)
30 intersection = arith_and(y_true_f, y_pred_f).sum((1, 2))
31 union = arith_or(y_true_f, y_pred_f).sum((1, 2))
---> 32 score = ((2.0 * intersection + 1e-6) / (union + 1e-6))
33
34 return 1 - score
ZeroDivisionError: float division by zero
Upvotes: 0
Views: 1491
Reputation: 173
I am no expert, but the dice loss function which I use comes from 'Image Segmentation with tf.keras' by Raymond Yuan (https://ej.uz/hk9s) and it has not failed me once.
The function:
def dice_coeff(y_true, y_pred):
smooth = 1.
y_true_f = tf.reshape(y_true, [-1])
y_pred_f = tf.reshape(y_pred, [-1])
intersection = tf.reduce_sum(y_true_f * y_pred_f)
score = (2. * intersection + smooth) / (tf.reduce_sum(y_true_f) + tf.reduce_sum(y_pred_f) + smooth)
return score
def dice_loss(y_true, y_pred):
loss = 1 - dice_coeff(y_true, y_pred)
return loss
It seems, that a float of 1 has just been added both to numerator and denominator.
With numpy it would be:
def dice_loss(y_true, y_pred):
smooth = 1.
y_true_f = np.ravel(y_true)
y_pred_f = np.ravel(y_pred)
intersection = np.sum(y_true_f * y_pred_f)
score = (2. * intersection + smooth) / (np.sum(y_true_f) + np.sum(y_pred_f) + smooth)
return 1 - score
Upvotes: 2