pythontensorflowkerasneural-networkconv-neural-network

How do I get probability/confidence as output for a CNN using keras in python?


So, I'm new to deep learning and I've started with cats and dogs dataset for a CNN Model using Keras.

In my code, I'm unable to get probabilities as output for both classifier.predict or classifier.predict_proba. I'm just getting the output as [[0,1]] or [[1,0]]. I've tried with several images.

But I'm looking for something like, [[0.4,0.6]], [[0.89,0.11]]

I've tried changing loss function from binary_crossentropy to categorical_crossentropy.

I've tried changing the activation function of the output layer from sigmoid to softmax.

I've also tried changing the class_mode in flow_from_directory from binary to categorical.

I think I might be going wrong with the data type, as the type of array of output is float32. But even if that is the error, I don't know how to change it though.

I'm unable to find where I'm going wrong. Please clarify/help. Thanks.

Why do I need probabilities?

In my another project, I'll be splitting an image into 'n' number of smaller pieces. I'll then use the classifier on 'n' number of pieces separately and find the one piece with the largest probability. For this, I won't use the dataset of cats and dogs though. It's for bin-picking and that dataset will also be binary output as 'YES' or 'NO'. Any suggestions for this is also welcome. Thanks.

Link for the code in Github.

    #Building the CNN
    
    from keras.models import Sequential
    from keras.layers import Convolution2D
    from keras.layers import MaxPooling2D
    from keras.layers import Flatten
    from keras.layers import Dense
    
    #Initialising the CNN
    
    classifier = Sequential()
    
    #Step 1 - Convolution
    classifier.add(Convolution2D(filters=32,kernel_size=[3,3],input_shape=(64,64,3),activation='relu'))
    
    #Step 2 - Pooling
    classifier.add(MaxPooling2D(pool_size=(2,2),strides=2))
    
    #Adding another Convolutional Layer for better accuracy
    #classifier.add(Convolution2D(filters=32,kernel_size=[3,3],activation='relu'))
    #classifier.add(MaxPooling2D(pool_size=(2,2),strides=2))
    
    #Step 3 - Flattening
    classifier.add(Flatten()) 
    
    #Step 4 - Fully Connected Layers
    classifier.add(Dense(units= 64, activation='relu'))
    classifier.add(Dense(units= 2, activation='softmax'))
    
    
    #Compiling the CNN
    classifier.compile(optimizer='adam',loss = 'categorical_crossentropy', metrics=['accuracy'])
    
    #Part 2 - Fitting the CNN to the images
    from keras.preprocessing.image import ImageDataGenerator
    
    train_datagen=ImageDataGenerator(
            rescale=1./255,
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True)
    
    test_datagen=ImageDataGenerator(rescale=1./255)
    
    training_set = train_datagen.flow_from_directory('dataset/training_set',
                                                     target_size=(64,64),
                                                     batch_size=32,
                                                     class_mode='categorical')
    
    test_set = test_datagen.flow_from_directory('dataset/test_set',
                                                target_size=(64,64),
                                                batch_size=32,
                                                class_mode='categorical')
    
    classifier.fit_generator(training_set,
                        steps_per_epoch=250,
                        epochs=3,                       #Just for time being I've kept very few epochs.
                        validation_data=test_set,
                        validation_steps=62)
    
    
    #Making new Predictions
    import numpy as np
    from keras.preprocessing import image
    
    test_image_luna=image.load_img('dataset/single/SkilletLuna.JPG',target_size=(64,64))
    test_image2=image.img_to_array(test_image_luna)
    test_image2=np.expand_dims(test_image2,axis=0)
    luna=classifier.predict_proba(test_image2)

In [11]: luna
    ...: 
Out[11]: array([[0., 1.]], dtype=float32)

Solution

  • I think I found the mistake. You are rescaling your train and test data with the ImageDataGenerator. But you are not doing that when testing a single image. Try this:

    # Making new Predictions
    import numpy as np
    from keras.preprocessing import image
    
    test_image_luna = image.load_img('D:\\NR\\data\\live2013\\caps.bmp', target_size=(64,64))
    test_image2 = image.img_to_array(test_image_luna)/255.
    test_image2 = np.expand_dims(test_image2, axis=0)
    luna = classifier.predict_proba(test_image2)
    

    The high input values lead to very high output values. Since you are using softmax activation these values are leading to predictions very close to 0 and 1.