我正在尝试为我的模型构建一个骰子损失函数(需要使用掩码进行分割,因此我使用的是IoU指标)。
在最后一步,即交集和并集的除法部分,我无法克服“浮点数除零”的问题。我已经尝试使用平滑常数(1e-6)、if else
语句以及try except
子句来处理ZeroDivisionError
错误。
这是代码:
import numpy as npdef 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 resdef 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 resdef 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
错误信息:
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 - scoreZeroDivisionError: float division by zero
回答:
我不是专家,但我使用的骰子损失函数来自Raymond Yuan的“使用tf.keras进行图像分割”(https://ej.uz/hk9s),它从未让我失望过。
函数如下:
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 scoredef dice_loss(y_true, y_pred): loss = 1 - dice_coeff(y_true, y_pred) return loss
似乎在分子和分母中都添加了一个浮点数1。
如果使用numpy,会是这样的:
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