Search code examples
plotkerasmetrics

Reporting each class metric


i am using Tensorflow/Keras to train a CNN. I have defined a custom metric to my problem. During the process, i get reports like:

Epoch 3/2000
57/57 - 3s - loss: 244231.4060 - custom_metric: 0.6170 - val_loss: 364119.8415 - val_custom_metric: 0.5506

It is a regression problem with 3 outputs. Is there anyway i can get those metric reports from each class separately?

I've seen in a paper where the author was using binary_accuracy as metrics, he also used TF/Keras, and even plotted in a graphic those values over all epochs.

This is the custom metric i have defined, with Yclasses = 3 and batch_size = 16:

def custom_metric(y_true, y_pred):
  truepotventolow = K.cast(K.less_equal(y_true[0:batch_size,0], 4000), 'int8')
  predpotventolow = K.cast(K.less_equal(y_pred[0:batch_size,0], 4000), 'int8')
  potventolow = K.sum(truepotventolow*predpotventolow)
  truepotventomed = K.cast(K.greater(y_true[0:batch_size,0], 4000) & K.less_equal(y_true[0:batch_size,0], 8500), 'int8')
  predpotventomed = K.cast(K.greater(y_pred[0:batch_size,0], 4000) & K.less_equal(y_pred[0:batch_size,0], 8500), 'int8')
  potventomed = K.sum(truepotventomed*predpotventomed)
  truepotventohigh = K.cast(K.greater(y_true[0:batch_size,0], 8500), 'int8')
  predpotventohigh = K.cast(K.greater(y_pred[0:batch_size,0], 8500), 'int8')
  potventohigh = K.sum(truepotventohigh*predpotventohigh)
  truedesvpadlow = K.cast(K.less_equal(y_true[0:batch_size,1], 1150), 'int8')
  preddesvpadlow = K.cast(K.less_equal(y_pred[0:batch_size,1], 1150), 'int8')
  desvpadlow = K.sum(truedesvpadlow*preddesvpadlow)
  truedesvpadmed = K.cast(K.greater(y_true[0:batch_size,1], 1150) & K.less_equal(y_true[0:batch_size,1], 2300), 'int8')
  preddesvpadmed = K.cast(K.greater(y_pred[0:batch_size,1], 1150) & K.less_equal(y_pred[0:batch_size,1], 2300), 'int8')
  desvpadmed = K.sum(truedesvpadmed*preddesvpadmed)
  truedesvpadhigh = K.cast(K.greater(y_true[0:batch_size,1], 2300), 'int8')
  preddesvpadhigh = K.cast(K.greater(y_pred[0:batch_size,1], 2300), 'int8')
  desvpadhigh = K.sum(truedesvpadhigh*preddesvpadhigh)
  truewlslow = K.cast(K.less_equal(y_true[0:batch_size,2], 0.075), 'int8')
  predwlslow = K.cast(K.less_equal(y_pred[0:batch_size,2], 0.075), 'int8')
  wlslow = K.sum(truewlslow*predwlslow)   
  truewlshigh = K.cast(K.greater(y_true[0:batch_size,2], 0.075), 'int8')
  predwlshigh = K.cast(K.greater(y_pred[0:batch_size,2], 0.075), 'int8')
  wlshigh = K.sum(truewlshigh*predwlshigh)
  return (potventolow+potventomed+potventohigh+desvpadlow+desvpadmed+desvpadhigh+wlslow+wlshigh)/(batch_size*Yclasses)

Solution

  • You should define a custom metric:

    def custom_metric(y_true, y_pred):
        return (
               keras.metrics.binary_accuracy(y_true[:, 0], y_pred[:, 0], threshold=0.5),
               keras.metrics.binary_accuracy(y_true[:, 1], y_pred[:, 1], threshold=0.5),
               keras.metrics.binary_accuracy(y_true[:, 2], y_pred[:, 2], threshold=0.5)
               )
    

    Then you can pass it to the model at compile time:

    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy', custom_metric])