为什么我的损失可以正确地计算为指标,但不能正确计算为TensorFlow中的损失?

时间:2020-11-11 00:32:16

标签: python tensorflow keras loss-function

我正在训练3D U-Net,并尝试使用Tensorflow实现Dice损失。我创建了以下函数,该函数可以返回骰子得分或相应的损失(1-score)

def dice_coefficient(_type="score", empty_score = 1.0):
    """ Computes Dice
    Args: 
        _type: "score" or "loss"
        empty_score: score if union is empty
    Returns:
        either Dice score or Dice loss (-score)
    """
    def dice_score(y_true, y_pred):
        # Flatten
        y_true_f = K.cast(K.flatten(y_true), y_pred.dtype)
        y_pred_f = K.flatten(y_pred)

        im_sum = K.sum(y_true_f) + K.sum(y_pred_f)
        if im_sum == 0:
            return empty_score
        im_sum = K.cast(im_sum, tf.float32)

        # Compute Dice coefficient
        intersection = K.sum(y_true_f * y_pred_f)
        intersection = K.cast(intersection, tf.float32)
        return 2. * intersection / im_sum
    
    def dice_loss(y_true, y_pred):
        return 1-dice_score(y_true, y_pred)

    if _type == "score":
        return dice_score
    elif _type == "loss":
        return dice_loss

训练模型时,我会同时设置损失和得分。

model.compile(optimizer=optimizer,
              loss=dice_coefficient(_type="loss"),
              metrics=dice_coefficient(_type="score"))

但是我得到nan的损失和分数的数值:如上所述,损失不应该是1-score吗?

144/Unknown - 68s 473ms/step - loss: nan - dice_score: 0.0209

1 个答案:

答案 0 :(得分:0)

我已经实现了骰子损失函数来优化图像分割。您可以查看此路径 https://github.com/charuu/msc-tooth-segmentation/blob/main/modelIO.py 上的代码 代码片段如下

class Dice(Loss):
      def call(self, y_true, y_pred):
        y_pred = ops.convert_to_tensor_v2(y_pred)
        y_true = gen_math_ops.cast(y_true, y_pred.dtype)
        y_true = tf.keras.backend.clip(y_true, tf.keras.backend.epsilon(), 1-tf.keras.backend.epsilon())
        y_pred = tf.keras.backend.clip(y_pred, tf.keras.backend.epsilon(), 1-tf.keras.backend.epsilon())
        
        intersection = tf.keras.backend.sum(tf.keras.backend.abs(y_true * y_pred), axis=-1)
        numerator = (2. * intersection + 1) 
        denominator = (tf.keras.backend.sum(tf.keras.backend.square(y_true),-1) + tf.keras.backend.sum(tf.keras.backend.square(y_pred),-1) + 1)
        return 1 - (numerator/denominator)