我正在尝试使用自定义损失函数进行对象分割,如下定义:
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_equal
和cast
不是。但是,Keras 中有没有办法规避这个问题呢?也许在 Tensorflow 中使用一些解决方法?
最佳答案
嗯,这很棘手。你的错误背后的原因是你的损失和你的网络之间没有持续的依赖。为了计算损失的梯度对于网络,如果您的输出大于 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
。
关于tensorflow - Keras - 自定义损失函数 - 倒角距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48613573/