准确度良好,但在图像分割中没有骰子损失

Posted

技术标签:

【中文标题】准确度良好,但在图像分割中没有骰子损失【英文标题】:Good performance with Accuracy but not with Dice loss in Image Segmentation 【发布时间】:2020-06-21 21:01:31 【问题描述】:

我正在使用带有 Keras 的 Tensorflow 上类似 U-Net 的架构进行图像分割,但我是深度学习的新手。 我有这个数据集具有以下设置的形状:

火车:X : (175250, 30, 30, 6) Y: (175250, 30, 30) 验证:X: (29200, 30, 30, 6) Y: (29200, 30, 30) 测试:X: (29200, 30, 30, 6) Y: (29200, 30, 30)

得到了这些图像和每个频道的一些示例,进一步向下。

--> 20% 正例和 80% 负例在每组中均等

我运行了一些系列,但为了获得最佳过滤器组合 BCE 的图具有良好的准确性:

自定义函数的绘图,Dice_Coeff 的 Dice_Loss:

还有一些使用测试图像训练的最佳模型生成的图像:

问题是当我更改为骰子损失和系数时,没有像我们在图像图中看到的那样好的预测,现在它不在我们可能看到的图像预测中。

为什么它在骰子损失中表现如此糟糕?你还有什么推荐的功能?

我的骰子损失和系数函数:

def dice_coeff(y_true, y_pred, smooth=1):
    intersection = K.sum(K.abs(y_true * y_pred), axis=-1)
    return (2. * intersection + smooth) / (K.sum(K.square(y_true),-1) + K.sum(K.square(y_pred),-1) + smooth)


def dice_loss(y_true, y_pred):
    return 1-dice_coeff(y_true, y_pred)

【问题讨论】:

根据我的个人经验,骰子损失与 BCE 非常适合用于多类分割。对于二元分割,BCE 表现更好。 @SusmitAgrawal 什么是 BCE?二进制交叉熵? 没错。 【参考方案1】:

您是否尝试过使用软骰子? 最近在计算机视觉方面的工作提出了软代理来缓解差异并直接优化所需的度量,或者通过松弛(soft-Dice、soft-Jaccard)。

还有其他流行的图像分割损失函数:

图像分割任务中最常用的损失函数是逐像素交叉熵损失。 这种损失单独检查每个像素,将类预测(深度像素向量)与我们的 one-hot 编码目标向量进行比较。

另一个用于图像分割任务的流行损失函数是基于 Dice 系数(您已经尝试过),它本质上是两个样本之间重叠的度量。该度量的范围从 0 到 1,其中 Dice 系数为 1 表示完全重叠。 如果您想知道,在计算 Dice 系数时,分子中有 2,因为我们的分母“双重计算”了两组之间的共同元素。为了制定可以最小化的损失函数,我们将简单地使用 1−Dice。

这种损失函数被称为软骰子损失,因为我们直接使用预测概率而不是做阈值并将它们转换为二进制掩码。

soft Dice loss 分别为每个类别计算,然后取平均值得出最终分数。下面提供了一个示例实现。

def soft_dice_loss(y_true, y_pred, epsilon=1e-6): 
    """Soft dice loss calculation for arbitrary batch size, number of classes, and number of spatial dimensions.
    Assumes the `channels_last` format.
  
    # Arguments
        y_true: b x X x Y( x Z...) x c One hot encoding of ground truth
        y_pred: b x X x Y( x Z...) x c Network output, must sum to 1 over c channel (such as after softmax) 
        epsilon: Used for numerical stability to avoid divide by zero errors
    """
   
    # skip the batch and class axis for calculating Dice score
    axes = tuple(range(1, len(y_pred.shape)-1)) 
    numerator = 2. * np.sum(y_pred * y_true, axes)
    denominator = np.sum(np.square(y_pred) + np.square(y_true), axes)
    
    return 1 - np.mean(numerator / (denominator + epsilon)) # average over classes and batch

您可以尝试这些功能并找出最适合您的模型的功能。

【讨论】:

在这篇文章中解释您在答案中复制和粘贴的内容:jeremyjordan.me/semantic-segmentation 我一直在努力工作,以摆脱软骰子的损失。我收到以下错误消息:“NotImplementedError:无法将符号张量 (loss/conv2d_10_loss/mul:0) 转换为 numpy 数组。” 这个定义行不通,因为它没有写成张量。

以上是关于准确度良好,但在图像分割中没有骰子损失的主要内容,如果未能解决你的问题,请参考以下文章

深度学习从入门到精通——图像分割技术原理解析

骰子点数识别-图像分割

语义分割损失函数

图像分割 - Keras 中的自定义损失函数

图像分割损失函数OhemCELoss

图像分割损失函数OhemCELoss