如何在TensorFlow中创建多个自定义AUC度量,每个输出一个?

如何在TensorFlow中创建多个自定义AUC度量,每个输出一个?,tensorflow,keras,tensorflow2.0,auc,Tensorflow,Keras,Tensorflow2.0,Auc,在TensorFlow 2.0中,有一个类。它可以很容易地添加到compile方法的度量列表中,如下所示 # Example taken from the documentation model.compile('sgd', loss='mse', metrics=[tf.keras.metrics.AUC()]) class CustomAUC(tf.metrics.Metric): def __init__(self, num_outputs, name="custom_auc"

在TensorFlow 2.0中,有一个类。它可以很容易地添加到
compile
方法的度量列表中,如下所示

# Example taken from the documentation
model.compile('sgd', loss='mse', metrics=[tf.keras.metrics.AUC()])
class CustomAUC(tf.metrics.Metric):

    def __init__(self, num_outputs, name="custom_auc", **kwargs):
        super(CustomAUC, self).__init__(name=name, **kwargs)
        assert num_outputs >= 1
        self.num_outputs = num_outputs
        self.aucs = [tf.metrics.AUC() for _ in range(self.num_outputs)]

    def update_state(self, y_true, y_pred, sample_weight=None):
        for output in range(self.num_outputs):
            y_true1 = y_true[:, output]
            y_pred1 = y_pred[:, output]
            self.aucs[output].update_state(y_true1, y_pred1)

    def result(self):
        return [auc.result() for auc in self.aucs]
然而,在我的例子中,我的神经网络的输出是一个
NxM
张量,其中
N
是批量大小,
M
是单独输出的数量。我想分别计算每个
M
输出的AUC度量(在批处理的所有
N
实例中)。因此,应该有
M
AUC度量,每个度量都是用
N
观察值计算的。我试图创建一个自定义指标,但我面临一些问题。以下是我的第一次尝试

def get_custom_auc(output):
    auc = tf.metrics.AUC()

    @tf.function
    def custom_auc(y_true, y_pred):
        y_true = y_true[:, output]
        y_pred = y_pred[:, output]
        auc.update_state(y_true, y_pred)
        return auc.result()

    custom_auc.__name__ = "custom_auc_" + str(output)
    return custom_auc
需要重命名
custom\u auc.\uuuuuu name\uuuuuu
的内容如下所述:。但是,此实现会引发一个错误

tensorflow.python.framework.errors\u impl.InvalidArgumentError:断言失败:[预测必须>=0][条件x>=y未保持元素状态:[x(跨步切片1:0)=][3.14020467 3.06779885 2.86414027…][y(强制转换1/x:0)=][0] [{{node metrics/custom\u auc\u 2/StatefulPartitionedCall/assert\u morer\u equal/assert/AssertGuard/else/\u 161/assert}}][Op:uuuu推理\u keras\u scratch\u图形\u 5149]

我还尝试在
自定义_AUC
中创建
AUC
对象,但这是不可能的,因为我使用的是
@tf.function
,因此我将得到错误
ValueError:tf.function-de装饰函数尝试在非首次调用时创建变量。
。即使我删除了
@tf.function
(我可能需要它,因为我可能会在实现中使用一些if-else语句),我也会遇到另一个错误

tensorflow.python.framework.errors\u impl.failedPremissionError:从容器localhost读取资源变量_AnonymousVar33时出错。这可能意味着变量未初始化。未找到:资源localhost/\u AnonymousVar33/N10tensorflow3VarE不存在。 [[node metrics/custom\u auc\u 0/add/ReadVariableOp(在/train.py:173处定义)][Op:\uuuuuuuuuuuu推断\uKeras\uScratch\uGraph\u5174]

请注意,目前我正在添加这些AUC度量,每个
M
输出一个,如中所述。此外,我不能简单地返回对象
auc
,因为显然Keras期望自定义度量的输出是张量而不是auc对象。因此,如果您这样做,您将得到以下错误

TypeError:为了与tf.contrib.eager.defun兼容,Python函数必须返回零个或多个张量;在0x1862e6680>处编译.custom_auc时,找到类型为的返回值,该值不是张量

我还尝试实现一个自定义度量类,如下所示

# Example taken from the documentation
model.compile('sgd', loss='mse', metrics=[tf.keras.metrics.AUC()])
class CustomAUC(tf.metrics.Metric):

    def __init__(self, num_outputs, name="custom_auc", **kwargs):
        super(CustomAUC, self).__init__(name=name, **kwargs)
        assert num_outputs >= 1
        self.num_outputs = num_outputs
        self.aucs = [tf.metrics.AUC() for _ in range(self.num_outputs)]

    def update_state(self, y_true, y_pred, sample_weight=None):
        for output in range(self.num_outputs):
            y_true1 = y_true[:, output]
            y_pred1 = y_pred[:, output]
            self.aucs[output].update_state(y_true1, y_pred1)

    def result(self):
        return [auc.result() for auc in self.aucs]
然而,我目前得到的错误

ValueError:形状(200、)和()不兼容

此错误似乎与重置状态有关,因此我可能也应该重写此方法。事实上,如果我用以下实现覆盖
reset_states

def reset_states(self):
    for auc in self.aucs:
        auc.reset_states()
我不再犯这个错误了,但我又犯了一个错误

tensorflow.python.framework.errors\u impl.InvalidArgumentError:断言失败:[预测必须>=0][条件x>=y未保持元素状态:[x(跨步切片1:0)=][-1.38822043 1.24234951-0.25447281…][y(强制转换1/x:0)=][0] [{{node metrics/custom_auc/PartitionedFunctionCall/assert_morerar_equal/assert/AssertGuard/else/_98/assert}}][Op:uu推理_keras_scratch_graph_5248]

那么,我如何实现这个定制的AUC度量,一个用于网络的
M
输出?基本上,我想做一些类似于中描述的解决方案的事情,但是使用AUC度量


我还打开了TensorFlow的Github问题跟踪器上的。我有一个与您类似的问题。我有一个有3个输出的模型,我想为3个输出(每个输出有不同数量的类)计算一个自定义度量(ConfusionMatricMetric)。我在这里使用了一个解决方案——去低层。我现在的问题是我不能训练模型,因为

ValueError: tf.function-decorated function tried to create variables on non-first call.
然后我用

tf.config.run_functions_eagerly(True)
现在模型训练速度很慢,但可以省去


另外,我还使用了
tf.keras.metrics.kldisference()
,而不是我的自定义指标,并以与上述相同的结果复制了相同的实验-训练和保存(
tf.saved\u model.save

您面临着最困难的tensorflow keras问题之一。由于收到错误消息,您可能无法将新定义的度量用作函数。我建议您定义一个自定义度量标准
,因为您可以将其解读为类似的问题。@Geeocode我将尝试查看该答案,但是,如果您可以为我的特定问题提供答案并解决我的问题,我将投票并接受;)明白。:)我想这个解决方案会有点费时,但是如果明天你仍然会被这个问题困扰,我会回来看看。@Geeocode我只是想实现它,但我不确定应该如何定义实际的类,例如,我应该从
AUC
还是从
Metric
继承(并定义类内
AUC
对象的列表)。如果您能为我的问题提供一个具体的解决方案,我将不胜感激,因为我目前还不确定应该如何实现它,因为我从来没有为metric.P.S.实现过自定义类。我非常感谢您提供一个完整而简单的示例。@Geeocode好的,我已经完成了(尽管我只是快速阅读了该线程)。我将编辑我的问题,以包括我第一次尝试开发自定义类度量。请看。