简体   繁体   English

Class 在 tensorflow 上的 keras 中的明智分类

[英]Class wise classification in keras on tensorflow

I am getting the following error, I am trying to get class-wise accuracy on training data.我收到以下错误,我正在尝试获得训练数据的分类准确性。 I have installed the latest TensorFlow and Keras, could anyone please help with the error?我已经安装了最新的 TensorFlow 和 Keras,有人可以帮忙解决错误吗? Thanks谢谢

Error:错误:

**raise ValueError('Found two metrics with the same name: {}'.format(
    ValueError: Found two metrics with the same name: acc1**

Code:代码:

resnet_model.summary()
from keras import backend as K

#interesting_class_id = 0  # Choose the class of interest

def single_class_accuracy(interesting_class_id):

    def acc1(y_true, y_pred):

        class_id_true = K.argmax(y_true)
        class_id_preds = K.argmax(y_pred)
        accuracy_mask = K.cast(K.equal(class_id_preds, interesting_class_id), 'int32')

        class_acc_tensor = K.cast(K.equal(class_id_true, class_id_preds), 'int32') * 
        accuracy_mask
        class_acc = K.cast(K.sum(class_acc_tensor), 'float32') / 
        K.cast(K.maximum(K.sum(accuracy_mask), 1), 'float32')
        return class_acc
    return acc1


def single_class_recall(interesting_class_id):

    def recall(y_true, y_pred):

        class_id_true = K.argmax(y_true, axis=-1)
        class_id_pred = K.argmax(y_pred, axis=-1)
        recall_mask = K.cast(K.equal(class_id_true, interesting_class_id), 'int32')

        class_recall_tensor = K.cast(K.equal(class_id_true, class_id_pred), 'int32') * 
        recall_mask
        class_recall = K.cast(K.sum(class_recall_tensor), 'float32') / 
        K.cast(K.maximum(K.sum(recall_mask), 1), 'float32')
        return class_recall
    return recall


def single_class_precision(interesting_class_id):
    def prec(y_true, y_pred):
        class_id_true = K.argmax(y_true, axis=-1)
        class_id_pred = K.argmax(y_pred, axis=-1)
        precision_mask = K.cast(K.equal(class_id_pred, interesting_class_id), 'int32') 
        class_prec_tensor = K.cast(K.equal(class_id_true, class_id_pred), 'int32') * 
        precision_mask 
        class_prec = K.cast(K.sum(class_prec_tensor), 'float32') / 
         K.cast(K.maximum(K.sum(precision_mask), 1), 'float32')
        return class_prec
    return prec

resnet_model.compile(optimizer=Adam(lr=0.01),loss='binary_crossentropy',metrics=[                                         
                         'accuracy',
                         single_class_accuracy(0),  
                         single_class_accuracy(1),
                         single_class_recall(0),
                         single_class_recall(1),
                         single_class_precision(0),  
                        single_class_precision(1)
                       ])


resnet_model.save('my_model')

history = resnet_model.fit(train_ds, validation_data=val_ds, epochs=20)

You can't add multiple metrics in metrics argument, changing only the parameter with which you call the metric.您不能在metrics参数中添加多个指标,只更改您调用指标的参数。 During the fit of your model, it will detect that you have multiple metrics with same name.在拟合 model 期间,它会检测到您有多个具有相同名称的指标。 The name is automatically set as the name of the inner metric function: acc1 , recall and prec in your case.该名称会自动设置为内部度量的名称 function: acc1 ,在您的情况下recallprec So when it goes through your metrics , it will find single_class_accuracy(0) and will call it acc1 , then will find single_class_accuracy(1) and will try to call it acc1 too, which leads to the error.因此,当它通过您的metrics时,它会找到single_class_accuracy(0)并将其称为acc1 ,然后会找到single_class_accuracy(1)并尝试将其称为acc1 ,这会导致错误。

What you can do is set different names to your metric functions, like so:您可以为度量函数设置不同的名称,如下所示:

def single_class_accuracy(interesting_class_id):

    def acc1(y_true, y_pred):

        class_id_true = K.argmax(y_true)
        class_id_preds = K.argmax(y_pred)
        accuracy_mask = K.cast(K.equal(class_id_preds, interesting_class_id), 'int32')

        class_acc_tensor = K.cast(K.equal(class_id_true, class_id_preds), 'int32') * accuracy_mask
        class_acc = K.cast(K.sum(class_acc_tensor), 'float32') / K.cast(K.maximum(K.sum(accuracy_mask), 1), 'float32')
        return class_acc
    
    # setting a name according to your additional parameter
    acc1.__name__ = 'acc_1_{}'.format(interesting_class_id)
    return acc1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM