niftynet - 广义骰子损失 : None-gradient when implemented in keras

标签 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: An operation has None for gradient. Please make sure that all of your ops have a gradient defined (i.e. are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.

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

最佳答案

与 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))

关于niftynet - 广义骰子损失 : None-gradient when implemented in keras,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50628958/

相关文章:

image-segmentation - 了解 Niftynet 的输入形状 (spatial_window_size)

python - 更改 CNN 以使用 3D 卷积

python - 在 niftynet 上实现迁移学习

matplotlib - 阈值大津: AttributeError: 'AxesSubplot' object has no attribute 'ravel'

python - NiftyNet:索引超出范围错误