Keras - 自定义损失功能 - 倒角距离

时间:2018-02-04 22:17:58

标签: tensorflow machine-learning neural-network deep-learning keras

我正在尝试使用如下定义的自定义丢失函数进行对象分割:

def chamfer_loss_value(y_true, y_pred):           

    # flatten the batch 
    y_true_f = K.batch_flatten(y_true)
    y_pred_f = K.batch_flatten(y_pred)

    # ==========
    # get chamfer distance sum

    // error here
    y_pred_mask_f = K.cast(K.greater_equal(y_pred_f,0.5), dtype='float32')

    finalChamferDistanceSum = K.sum(y_pred_mask_f * y_true_f, axis=1, keepdims=True)  

    return K.mean(finalChamferDistanceSum)

def chamfer_loss(y_true, y_pred):   
    return chamfer_loss_value(y_true, y_pred)

y_pred_f是我的U-net的结果。 y_true_f是地面实况标签掩码x上的欧氏距离变换的结果,如下所示:

distTrans = ndimage.distance_transform_edt(1 - x)

要计算倒角距离,可以将预测图像(理想情况下,1和0的遮罩)与地面真实距离变换相乘,并简单地对所有像素求和。为此,我需要通过阈值y_pred_mask_f获取掩码y_pred_f,然后乘以y_true_f,并对所有像素求和。

y_pred_f在[0,1]中提供了连续的值范围,我在None type not supported的评估中得到错误y_true_mask_f。我知道损失函数必须是可微分的,greater_equalcast不是。但是,在克拉斯有没有办法规避这个?也许在Tensorflow中使用一些解决方法?

1 个答案:

答案 0 :(得分:6)

嗯,这很棘手。您的错误背后的原因是您的损失与您的网络之间存在无连续依赖。为了计算你的损失的梯度w.r.t.对于网络,如果您的输出大于0.5,则您的损失必须计算指标的梯度(因为这是您的最终损失值与网络输出y_pred之间的唯一连接)。这是不可能的,因为该指标部分恒定且不连续。

可能的解决方案 - 平滑指标:

def chamfer_loss_value(y_true, y_pred):           

    # flatten the batch 
    y_true_f = K.batch_flatten(y_true)
    y_pred_f = K.batch_flatten(y_pred)

    y_pred_mask_f = K.sigmoid(y_pred_f - 0.5)

    finalChamferDistanceSum = K.sum(y_pred_mask_f * y_true_f, axis=1, keepdims=True)  

    return K.mean(finalChamferDistanceSum)

由于sigmoid是步进函数的连续版本。如果您的输出来自sigmoid - 您只需使用y_pred_f代替y_pred_mask_f