广义骰子丢失:在keras

时间:2018-05-31 16:34:11

标签: niftynet

我正在尝试实现NiftyNet中实现的广义骰子丢失,在用Keras(TF后端)编写的不同的网络中。

def generalised_dice_loss(prediction,
                      ground_truth,
                      weight_map=None,
                      type_weight='Square'):
"""
Function to calculate the Generalised Dice Loss defined in
    Sudre, C. et. al. (2017) Generalised Dice overlap as a deep learning
    loss function for highly unbalanced segmentations. DLMIA 2017

:param prediction: the logits
:param ground_truth: the segmentation ground truth
:param weight_map:
:param type_weight: type of weighting allowed between labels (choice
    between Square (square of inverse of volume),
    Simple (inverse of volume) and Uniform (no weighting))
:return: the loss
"""
prediction = tf.cast(prediction, tf.float32)
if len(ground_truth.shape) == len(prediction.shape):
    ground_truth = ground_truth[..., -1]
one_hot = labels_to_one_hot(ground_truth, tf.shape(prediction)[-1])

if weight_map is not None:
    n_classes = prediction.shape[1].value
    weight_map_nclasses = tf.reshape(
        tf.tile(weight_map, [n_classes]), prediction.get_shape())
    ref_vol = tf.sparse_reduce_sum(
        weight_map_nclasses * one_hot, reduction_axes=[0])

    intersect = tf.sparse_reduce_sum(
        weight_map_nclasses * one_hot * prediction, reduction_axes=[0])
    seg_vol = tf.reduce_sum(
        tf.multiply(weight_map_nclasses, prediction), 0)
else:
    ref_vol = tf.sparse_reduce_sum(one_hot, reduction_axes=[0])
    intersect = tf.sparse_reduce_sum(one_hot * prediction,
                                     reduction_axes=[0])
    seg_vol = tf.reduce_sum(prediction, 0)
if type_weight == 'Square':
    weights = tf.reciprocal(tf.square(ref_vol))
elif type_weight == 'Simple':
    weights = tf.reciprocal(ref_vol)
elif type_weight == 'Uniform':
    weights = tf.ones_like(ref_vol)
else:
    raise ValueError("The variable type_weight \"{}\""
                     "is not defined.".format(type_weight))
new_weights = tf.where(tf.is_inf(weights), tf.zeros_like(weights), weights)
weights = tf.where(tf.is_inf(weights), tf.ones_like(weights) *
                   tf.reduce_max(new_weights), weights)
generalised_dice_numerator = \
    2 * tf.reduce_sum(tf.multiply(weights, intersect))
generalised_dice_denominator = \
    tf.reduce_sum(tf.multiply(weights, seg_vol + ref_vol)) + 1e-6
generalised_dice_score = \
    generalised_dice_numerator / generalised_dice_denominator
return 1 - generalised_dice_score

但是,当我尝试使用此损失函数训练模型时,会出现以下错误:

  

ValueError:渐变操作为None。请确保您的所有操作都定义了渐变(即可区分)。没有渐变的常见操作:K.argmax,K.round,K.eval。

我试图实现的任何其他损失函数都不会发生这种情况。有人知道如何解决这个问题吗?据我所知,代码中没有非差异运算符。

1 个答案:

答案 0 :(得分:0)

与keras相似的问题(自定义图层和/或模型),解决方案是先在def init()中构建图层,然后再在call()中使用它们

self.lstm_custom_1 = keras.layers.LSTM(128,batch_input_shape=batch_input_shape, return_sequences=False,stateful=True)
self.lstm_custom_1.build(batch_input_shape)

self.dense_custom_1 = keras.layers.Dense(32,  activation = 'relu')
self.dense_custom_1.build(input_shape=(batch_size, 128))