3

我正在尝试在用 Keras(TF 后端)编写的不同 convnet 中 实现NiftyNet中实现的 Generalized Dice Loss 。

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:一个操作没有梯度。请确保您的所有操作都定义了渐变(即可微分)。没有梯度的常见操作:K.argmax、K.round、K.eval。

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

4

1 回答 1

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))
于 2019-07-03T02:27:49.433 回答