您如何训练语义分割模型以优化 IoU 而不是准确性?

数据挖掘 计算机视觉 阶级失衡 语义分割
2022-03-06 21:43:16

我目前正在 Tensorflow Keras 上构建一个 U-NET 语义分割模型,以将像素分类为属于或不属于某个类。

对于这个问题,我只为一个类隔离了掩码(即使存在多个掩码类),因为我的目标是让模型在识别看不见的图像中存在一个类时表现出色。

在当前的训练方案中,模型的准确率似乎在大约 20 轮训练后达到稳定水平。然而,从第一个纪元到最后一个纪元,Union 的平均交叉点似乎是平坦的。

当模型完成训练时,验证准确率最终达到 70% 左右,但我怀疑这是因为类不平衡,而不是我的模型擅长对图像像素进行分类。

我对机器学习和深度学习还比较陌生,所以我真的希望得到一些关于你通常如何解决这个问题的高级建议。

  • 我的问题是我在 UNET 架构中指定了一些错误吗?我在输出层选择了一个 sigmoid 激活函数,并在编译调用中使用了 Adam 优化器和二元交叉熵。compile 调用中的指标当前是“准确度”和 num_classes = 2 的 keras.metrics.meanIoU。
  • Intersection Over Union 甚至是我应该在这类问题中优化的指标吗?
  • 是否有一些常识性的图像增强步骤我应该尝试提高模型的分类效率?
1个回答

您可以通过实现以下损失直接优化平均 IoU 损失:

def mean_iou(y_pred, y_true):
    if y_pred.shape.ndims > 1:
        y_pred = array_ops.reshape(y_pred, [-1])

    if y_true.shape.ndims > 1:
        y_true = array_ops.reshape(y_true, [-1])
    intersection = K.sum(K.sum(K.abs(y_true * y_pred), axis=-1))
    union = K.sum(K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1))

    return intersection / union

另一个有用的损失是 Jaccard 损失,如果分割类不平衡,它会派上用场:

def jaccard_distance_loss(y_true, y_pred, smooth=10):
  """
  Jaccard = (|X & Y|)/ (|X|+ |Y| - |X & Y|)
        = sum(|A*B|)/(sum(|A|)+sum(|B|)-sum(|A*B|))

  """
  intersection = K.sum(K.sum(K.abs(y_true * y_pred), axis=-1))
  union = K.sum(K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1))
  jac = (intersection + smooth) / (union - intersection + smooth)
  return (1 - jac) * smooth