实现多类骰子损失函数

Ham*_*aya 4 python tensorflow semantic-segmentation tensorflow2.0

我正在使用 UNet 进行多类分割。我对模型的输入是HxWxC,我的输出是,

outputs = layers.Conv2D(n_classes, (1, 1), activation='sigmoid')(decoder0)
Run Code Online (Sandbox Code Playgroud)

使用SparseCategoricalCrossentropy我可以很好地训练网络。现在我还想尝试骰子系数作为损失函数。实施如下,

def dice_loss(y_true, y_pred, smooth=1e-6):
    y_true = tf.cast(y_true, tf.float32)
    y_pred = tf.math.sigmoid(y_pred)

    numerator = 2 * tf.reduce_sum(y_true * y_pred) + smooth
    denominator = tf.reduce_sum(y_true + y_pred) + smooth

    return 1 - numerator / denominator
Run Code Online (Sandbox Code Playgroud)

然而,我实际上得到的是越来越多的损失,而不是减少的损失。我检查了多个来源,但我找到的所有材料都使用骰子损失进行二元分类而不是多类分类。所以我的问题是实施有问题。

Dav*_*d S 6

问题是你的骰子损失并没有解决你拥有的类的数量,而是假设二进制情况,所以它可能解释你的损失的增加。

您应该实现涵盖所有类别的广义骰子损失,并返回所有类别的值。

像下面这样:

def dice_coef_9cat(y_true, y_pred, smooth=1e-7):
    '''
    Dice coefficient for 10 categories. Ignores background pixel label 0
    Pass to model as metric during compile statement
    '''
    y_true_f = K.flatten(K.one_hot(K.cast(y_true, 'int32'), num_classes=10)[...,1:])
    y_pred_f = K.flatten(y_pred[...,1:])
    intersect = K.sum(y_true_f * y_pred_f, axis=-1)
    denom = K.sum(y_true_f + y_pred_f, axis=-1)
    return K.mean((2. * intersect / (denom + smooth)))

def dice_coef_9cat_loss(y_true, y_pred):
    '''
    Dice loss to minimize. Pass to model as loss during compile statement
    '''
    return 1 - dice_coef_9cat(y_true, y_pred)
Run Code Online (Sandbox Code Playgroud)

此片段取自https://github.com/keras-team/keras/issues/9395#issuecomment-370971561

这是针对 9 个类别的,您应该根据您拥有的类别数量进行调整。