Keras 中的自定义损失函数(IoU 损失函数)和梯度误差?

Posted

技术标签:

【中文标题】Keras 中的自定义损失函数(IoU 损失函数)和梯度误差?【英文标题】:Customized Loss function in Keras (IoU loss function) and gradient error? 【发布时间】:2021-02-24 12:53:28 【问题描述】:

我是 ML 新手,我正在尝试实现我自己的损失函数(IoU 损失函数),但得到关于梯度的错误(“没有为任何变量提供梯度”)。 请注意,我正在尝试预测将代表矩阵中行号的数字(例如 y_pred = [1 5 3 9])。在损失函数中,我应该计算正确预测的行数,然后将其除以 y_true 的元素总数。由于应该尽量减少损失,所以我在函数末尾放了 1-IoU。

这是我的功能,因为我不知道如何准确解释我的问题,所以更清楚:

**def** loss_IoU(y_true, y_pred):

  intersection = []
  #roundig the predicted values y_pred, since the values could be floats ex. [1.5 2 8.98 ...]
  Roundy_pred = tf.round(y_pred)   # (none, 6) with shape of none, and the size of the outputs 6.
  intersection = tf.math.count_nonzero( Roundy_pred == y_true, axis=1, keepdims=True)   # (none, 1) count the number of equal values for each row (i.e. for each predicted y and a true y)
  union = y_true.shape[1] # which is 6 here
  iou = intersection/union
  returned_iou = 1 - iou
  return returned_iou

这是我得到的错误:

    ValueError                                Traceback (most recent call last)
<ipython-input-176-631f68b50b34> in <module>()
      9 history = model.fit(AS_Training_Set, Label_Training_Set, 
     10                     steps_per_epoch=8, epochs=600, validation_data=
---> 11           (AS_Validation_Set, Label_Validation_Set))

10 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    971           except Exception as e:  # pylint:disable=broad-except
    972             if hasattr(e, "ag_error_metadata"):
--> 973               raise e.ag_error_metadata.to_exception(e)
    974             else:
    975               raise

ValueError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:796 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:1211 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2585 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2945 _call_for_each_replica
        return fn(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:789 run_step  **
        outputs = model.train_step(data)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:757 train_step
        self.trainable_variables)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:2737 _minimize
        trainable_variables))
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:562 _aggregate_gradients
        filtered_grads_and_vars = _filter_grads(grads_and_vars)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:1271 _filter_grads
        ([v.name for _, v in grads_and_vars],))

    ValueError: No gradients provided for any variable: ['conv2d_16/kernel:0', 'conv2d_16/bias:0', 'conv2d_17/kernel:0', 'conv2d_17/bias:0', 'batch_normalization_8/gamma:0', 'batch_normalization_8/beta:0', 'conv2d_18/kernel:0', 'conv2d_18/bias:0', 'conv2d_19/kernel:0', 'conv2d_19/bias:0', 'batch_normalization_9/gamma:0', 'batch_normalization_9/beta:0', 'conv2d_20/kernel:0', 'conv2d_20/bias:0', 'conv2d_21/kernel:0', 'conv2d_21/bias:0', 'batch_normalization_10/gamma:0', 'batch_normalization_10/beta:0', 'conv2d_22/kernel:0', 'conv2d_22/bias:0', 'conv2d_23/kernel:0', 'conv2d_23/bias:0', 'batch_normalization_11/gamma:0', 'batch_normalization_11/beta:0', 'dense_4/kernel:0', 'dense_4/bias:0', 'dense_5/kernel:0', 'dense_5/bias:0'].

谁能帮我解决这个错误,我尝试修复它但没有任何结果,我不知道问题是否与舍入函数有关。

从现在开始谢谢。

【问题讨论】:

【参考方案1】:

对于 IoU 损失函数,我将这个用于 Pascal VOC 数据集。

def IoU_loss(y_true, y_pred):
    nb_classes = K.int_shape(y_pred)[-1]
    iou = []
    pred_pixels = K.argmax(y_pred, axis=-1)
    for i in range(0, nb_classes):  # exclude first label (background) and last label (void)
        true_labels = K.equal(y_true[:, :, 0], i)
        pred_labels = K.equal(pred_pixels, i)
        inter = tf.cast(true_labels & pred_labels, dtype=tf.int32)
        union = tf.cast(true_labels | pred_labels, dtype=tf.int32)
        legal_batches = K.sum(tf.cast(true_labels, dtype=tf.int32), axis=1) > 0
        ious = K.sum(inter, axis=1) / K.sum(union, axis=1)
        iou.append(K.mean(ious[legal_batches]))

    iou = tf.stack(iou)
    legal_labels = ~tf.math.is_nan(iou)
    iou = iou[legal_labels]
    return K.mean(iou)

它需要进行一些更改,但它也适用于您。

【讨论】:

非常感谢,会试一试,希望对我有用。

以上是关于Keras 中的自定义损失函数(IoU 损失函数)和梯度误差?的主要内容,如果未能解决你的问题,请参考以下文章

Keras 中的自定义损失函数 - 遍历 TensorFlow

Keras 中的自定义损失函数应该返回批次的单个损失值还是训练批次中每个样本的一系列损失?

Keras 中基于输入数据的自定义损失函数

R Keras 中的自定义损失函数

Keras 中的自定义损失函数以惩罚假阴性

Keras 上的自定义损失函数