14

I am using model.fit_generator to train and get results for my binary (two class) model because I am giving input images directly from my folder. How to get confusion matrix in this case (TP, TN, FP, FN) as well because generally I use confusion_matrix command of sklearn.metrics to get it, which requires predicted, and actual labels. But here I don't have both. May be I can calculate predicted labels from predict=model.predict_generator(validation_generator) command. But I don't know how my model is taking input labels from my images. General structure of my input folder is:

train/
 class1/
     img1.jpg
     img2.jpg
     ........
 class2/
     IMG1.jpg
     IMG2.jpg
test/
 class1/
     img1.jpg
     img2.jpg
     ........
 class2/
     IMG1.jpg
     IMG2.jpg
     ........

and some blocks of my code is:

train_generator = train_datagen.flow_from_directory('train',  
        target_size=(50, 50),  batch_size=batch_size,
        class_mode='binary',color_mode='grayscale')  


validation_generator = test_datagen.flow_from_directory('test',
        target_size=(50, 50),batch_size=batch_size,
        class_mode='binary',color_mode='grayscale')

model.fit_generator(
        train_generator,steps_per_epoch=250 ,epochs=40,
        validation_data=validation_generator,
        validation_steps=21 )

So the above code automatically takes two class inputs, but I don't know for which it consider class 0 and for which class 1.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Hitesh
  • 1,285
  • 6
  • 20
  • 36

3 Answers3

5

I've managed it in the following way, using keras.utils.Sequence.

from sklearn.metrics import confusion_matrix
from keras.utils import Sequence


class MySequence(Sequence):
    def __init__(self, *args, **kwargs):
        # initialize
        # see manual on implementing methods

    def __len__(self):
        return self.length

    def __getitem__(self, index):
        # return index-th complete batch


# create data generator
data_gen = MySequence(evaluation_set, batch_size=10) 

n_batches = len(data_gen)

confusion_matrix(
    np.concatenate([np.argmax(data_gen[i][1], axis=1) for i in range(n_batches)]),    
    np.argmax(m.predict_generator(data_gen, steps=n_batches), axis=1) 
)

The implemented class returns batches of data in tuples, that allows not to hold all of them in RAM. Please, note that it must be implemented in __getitem__, and this method must return same batch for the same argument.

Unfortunately this code iterates data twice: first time, it creates array of true answers from returned batches, the second time it calls predict method of the model.

wl2776
  • 4,099
  • 4
  • 35
  • 77
4
probabilities = model.predict_generator(generator=test_generator)

will give us set of probabilities.

y_true = test_generator.classes

will give us true labels.

Because this is a binary classification problem, you have to find predicted labels. To do that you can use

y_pred = probabilities > 0.5

Then we have true labels and predicted labels on the test dataset. So, the confusion matrix is given by

font = {
'family': 'Times New Roman',
'size': 12
}
matplotlib.rc('font', **font)
mat = confusion_matrix(y_true, y_pred)
plot_confusion_matrix(conf_mat=mat, figsize=(8, 8), show_normed=False)
Davide Fiocco
  • 5,350
  • 5
  • 35
  • 72
Shirantha Madusanka
  • 1,461
  • 1
  • 11
  • 16
3

You can view the mapping from class names to class indices by calling the attribute class_indices on your train_generator or validation_generator objects, as in

train_generator.class_indices

blackHoleDetector
  • 2,975
  • 2
  • 13
  • 13
  • your help is valuable. when i type `train_generator.class_indices` and `validation_generator.class_indices` it gives me output `{'class1': 0, 'class2': 1}` . Suppose for test data i have 10 samples for both classes (total 20) so my input class will be like [0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1]? and output classes i will get from `predict=model.predict_generator(validation_generator)` and after that i can get confusion matrix. – Hitesh Dec 21 '17 at 06:06
  • 1
    @Hitesh I'm a bit confused about your question. If you're asking about how does the output of class_indices actually map to your underlying labels, check out my video explaining this here. The output is shown around 4:20. https://youtu.be/pZoy_j3YsQg Also, the output you get from predict_generator will be what you use for your confusion matrix. – blackHoleDetector Dec 22 '17 at 22:23
  • can you expand a but on how to go from predict_generator to confusion matrix. – bw4sz Dec 23 '17 at 23:25
  • @bw4sz once you have the predictions from predict_generator, as well as the labels for those predictions, you can plot the results using sklearn's confusion matrix. I demonstrate the process here: https://youtu.be/km7pxKy4UHU Note, in that video, we're using predict() rather than predict_generator() for the predictions, but the concept is the same. After watching that one, if you want to see the process with predict_generator(), check out https://youtu.be/bfQBPNDy5EM around the 5:30 mark. The second video doesn't go through the full detailed process of creating the matrix like the first one. – blackHoleDetector Dec 24 '17 at 17:53