我正在尝试使用如下定义的自定义丢失函数进行对象分割:
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
不是。但是,在克拉斯有没有办法规避这个?也许在Tensorflow中使用一些解决方法?
答案 0 :(得分:6)
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
。