My code is given below, I am only getting the accuracy of the class 0 instead of all the classes. The output is Epoch 1/2 58/58 [==============================] - 424s 7s/step - loss: 4.7356 - accuracy: 0.5317 - acc_1_0: 0.9655 - acc_1_1: 0.0000e+00 - acc_1_2: 0.0000e+00 - acc_1_3: 0.0000e+00 - acc_1_4: 0.0000e+00 - recall_1_0: 0.2252 - recall_1_1: 0.0000e+00 - prec_1_0: 0.9655 - prec_1_1: 0.0000e+00 - val_loss: 0.9262 - val_accuracy: 0.6447 - val_acc_1_0: 1.0000 - val_acc_1_1: 0.0000e+00 - val_acc_1_2: 0.0000e+00 - val_acc_1_3: 0.0000e+00 - val_acc_1_4: 0.0000e+00 - val_recall_1_0: 0.2062 - val_recall_1_1: 0.0000e+00 - val_prec_1_0: 1.0000 - val_prec_1_1: 0.0000e+00
The code on https://tykimos.github.io/2017/09/24/Custom_Metric/ is working perfectly find. I think the issue is with the preprocessing function used to process the data because in the given example in the URL, they are using mnist dataset. and extracting data as x_train, y_train while with tf.keras.preprocessing.image_dataset_from_directory the dataset as a whole is fed to fit. Please help to resolve this issue. Thanks
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir, labels ='inferred', label_mode='int',
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir, labels ='inferred', label_mode='int',
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
resnet_model = Sequential()
pretrained_model= tf.keras.applications.VGG16(include_top=False,
input_shape=(180,180,3),
pooling='avg',classes=5,
weights='imagenet',
#classifier_activation= 'sigmoid')
classifier_activation= 'softmax')
for layer in pretrained_model.layers: layer.trainable=False
resnet_model.add(pretrained_model)
resnet_model.add(Flatten())
resnet_model.add(Dense(512, activation='relu'))
resnet_model.add(Dense(5, activation='softmax'))
interesting_class_id = 0 # Choose the class of interest
from keras import backend as K
def single_class_accuracy(interesting_class_id):
def acc1(y_true, y_pred):
class_id_true = K.argmax(y_true, axis=-1)
class_id_preds = K.argmax(y_pred, axis=-1)
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
acc1.__name__ = 'acc_1_{}'.format(interesting_class_id)
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 recall.name = 'recall_1_{}'.format(interesting_class_id) 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
prec.__name__ = 'prec_1_{}'.format(interesting_class_id)
return prec
resnet_model.compile(optimizer=Adam(lr=0.01),loss='sparse_categorical_crossentropy',
metrics=[
'accuracy',
single_class_accuracy(0),
single_class_accuracy(1),
single_class_accuracy(2),
single_class_accuracy(3),
single_class_accuracy(4),
single_class_recall(0),
single_class_recall(1),
single_class_precision(0),
single_class_precision(1)
])
history = resnet_model.fit(train_ds, validation_data=val_ds, epochs=2)