我正在使用Keras 2.2.4,并且正在尝试实现here中所述的按像素分类的损失函数,但是这里遇到了一些困难。我正在执行3D分割,因此我的目标向量是(b_size, width_x, width_y, width_z, nb_classes)
。我实现了以下损失函数,其中权重图与目标和预测矢量的形状相同:
def dice_xent_loss(y_true, y_pred, weight_map):
"""Adaptation of https://arxiv.org/pdf/1809.10486.pdf for multilabel
classification with overlapping pixels between classes. Dec 2018.
"""
loss_dice = weighted_dice(y_true, y_pred, weight_map)
loss_xent = weighted_binary_crossentropy(y_true, y_pred, weight_map)
return loss_dice + loss_xent
def weighted_binary_crossentropy(y_true, y_pred, weight_map):
return tf.reduce_mean((K.binary_crossentropy(y_true,
y_pred)*weight_map)) / (tf.reduce_sum(weight_map) + K.epsilon())
def weighted_dice(y_true, y_pred, weight_map):
if weight_map is None:
raise ValueError("Weight map cannot be None")
if y_true.shape != weight_map.shape:
raise ValueError("Weight map must be the same size as target vector")
dice_numerator = 2.0 * K.sum(y_pred * y_true * weight_map, axis=[1,2,3])
dice_denominator = K.sum(weight_map * y_true, axis=[1,2,3]) + \
K.sum(y_pred * weight_map, axis=[1,2,3])
loss_dice = (dice_numerator) / (dice_denominator + K.epsilon())
h1=tf.square(tf.minimum(0.1,loss_dice)*10-1)
h2=tf.square(tf.minimum(0.01,loss_dice)*100-1)
return 1.0 - tf.reduce_mean(loss_dice) + \
tf.reduce_mean(h1)*10 + \
tf.reduce_mean(h2)*10
我按照建议使用sample_weights=temporal
编译模型,并将权重作为model.fit
传递给sample_weight=weights
。仍然出现以下错误:
File "overfit_one_case.py", line 153, in <module>
main()
File "overfit_one_case.py", line 81, in main
sample_weight_mode="temporal")
File "/home/igt/anaconda2/envs/niftynet/lib/python2.7/site-packages/keras/engine/training.py", line 342, in compile
sample_weight, mask)
File "/home/igt/anaconda2/envs/niftynet/lib/python2.7/site-packages/keras/engine/training_utils.py", line 404, in weighted
score_array = fn(y_true, y_pred)
TypeError: dice_xent_loss() takes exactly 3 arguments (2 given)
在training_utils.py
中,Keras称我的自定义损失没有任何权重。关于如何解决这个问题的任何想法?我的另一个限制是我正在尝试在此特定模型上进行迁移学习。因此,我无法按照建议的here将weight_map
添加到Input
层。
答案 0 :(得分:1)
样本权重是样本的权重,而不是像素的权重。
除y_true
和y_pred
之外,克拉斯损失从未接受任何其他论点。所有keras加权都是自动的。
对于自定义权重,您需要自己实现。您可以创建包裹在需要权重的函数中的这些损失函数,如下所示:
def weighted_dice_xent_loss(weight_map):
def dice_xent_loss(y_true, y_pred):
#code...
return loss_dice + loss_xent
return dice_xent_loss
def weighted_binary_crossentropy(weight_map):
def inner_binary_crossentropy(y_true, y_pred):
return tf.reduce_mean(
(K.binary_crossentropy(y_true, y_pred)*weight_map)) / (
tf.reduce_sum(weight_map) + K.epsilon())
return inner_binnary_crossentropy
def weighted_dice(weight_map):
def dice(y_true, y_pred):
#code....
return 1.0 - tf.reduce_mean(loss_dice) + \
tf.reduce_mean(h1)*10 + \
tf.reduce_mean(h2)*10
return dice
例如,将它们用作loss=weighted_dice_xent_loss(weight_map)
。
使用样本权重的丑陋解决方法。
如果每个样本的权重都是唯一的,则必须将每个像素变成一个样本(这很不正常)。
使用您的数据:
(b_size * width_x * width_y * width_z, nb_channels)
。 使用您的模型:
Lambda
在K.reshape
图层中重塑形状以恢复原始尺寸:K.reshape(x, (-1, width_x, width_y, width_z, nb_classes))
Lambda
在K.reshape(x, (-1, nb_classes))
层中重塑输出您的损失: