Home > Blockchain >  Class wise classification in keras on tensorflow
Class wise classification in keras on tensorflow

Time:09-07

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

CodePudding user response:

You can't add multiple metrics in metrics argument, changing only the parameter with which you call the metric. During the fit of your model, it will detect that you have multiple metrics with same name. The name is automatically set as the name of the inner metric function: acc1, recall and prec in your case. 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.

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
  • Related