Tensorflow:实现新的损失函数返回“ValueError:没有为任何变量提供梯度”

Posted

技术标签:

【中文标题】Tensorflow:实现新的损失函数返回“ValueError:没有为任何变量提供梯度”【英文标题】:Tensorflow: Implementing new loss function returns a "ValueError: No gradients provided for any variable" 【发布时间】:2017-10-16 19:47:08 【问题描述】:

我需要为我的深度网络实现一个新的损失函数,如下所示:

import tensorflow as tf
from tensorflow.python import confusion_matrix
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import array_ops

def gms_loss(targets=None, logits=None, name=None):
    #Shape checking
    try:
        targets.get_shape().merge_with(logits.get_shape())
    except ValueError:
        raise ValueError("logits and targets must have the same shape (%s vs %s)"
                         % (logits.get_shape(), targets.get_shape()))
    #Compute the confusion matrix
    predictions=tf.nn.softmax(logits)
    cm=confusion_matrix(tf.argmax(targets,1),tf.argmax(predictions,1),3)

    def compute_sensitivities(name):
        """Compute the sensitivity per class via the confusion matrix."""
        per_row_sum = math_ops.to_float(math_ops.reduce_sum(cm, 1))
        cm_diag = math_ops.to_float(array_ops.diag_part(cm))
        denominator = per_row_sum

        # If the value of the denominator is 0, set it to 1 to avoid
        # zero division.
        denominator = array_ops.where(
            math_ops.greater(denominator, 0), denominator,
            array_ops.ones_like(denominator))

        accuracies = math_ops.div(cm_diag, denominator)
        return accuracies

    gms = math_ops.reduce_prod(compute_sensitivities('sensitivities'))
    return gms

这是从图形代码调用:

test=gms_loss(targets=y,logits=pred)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(test)

最后是已知错误:

"ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables..."

我找不到问题,如果我使用 softmax_cross_entropy,它可以工作(但无法正确优化,这就是我需要新损失函数的原因)

提前谢谢你

【问题讨论】:

【参考方案1】:

我认为问题在于tf.argmax() 函数不可微分。因此,优化器将无法计算损失函数相对于您的预测和目标的梯度。我不知道用 argmax 函数处理这个问题的方法,所以我建议避免使用不可微分的函数。

【讨论】:

你是对的,算了,GMS 是不可推导的......谢谢你的时间。 @DarkHawk 我在尝试创建自定义成本/损失函数时遇到了类似的问题。我使用 argmax 来计算混淆矩阵,而不是像 False Positives 那样惩罚 False Negatives。你有没有想过解决你的问题?你介意分享吗?谢谢! @mschmidt42 假设正(信号)索引为 0,所有其他索引为负(背景),您可以在其中使用 w = s(y)[:,0] * (1 - y'[:,0]) + K * (1 - s(y)[:,0]) * y'[:, 0], where y is the network output, s(y) is the softmax of the network output, and y' are the true labels. This produces large errors for false positives (first part of the sum) and false negatives (second part). There is no argmax` 之类的东西,因此它也会产生错误正确的预测,但它是可微的。您可以通过增加或减少 K 来调整零件的相对权重。 @mschmidt42 只需将这个损失w添加到现有的交叉熵损失函数中,或者用w替换即可。

以上是关于Tensorflow:实现新的损失函数返回“ValueError:没有为任何变量提供梯度”的主要内容,如果未能解决你的问题,请参考以下文章

损失函数tensorflow2实现——Python实战

TensorFlow 用TensorFlow实现L2正则损失函数线性回归算法

在 TensorFlow 中使用 SSIM 损失返回 NaN 值

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

TensorFlow 损失函数在第一个 epoch 后归零

实现二元交叉熵损失给出了与 Tensorflow 不同的答案