0

I am building a multi-class multi-label object recognition CNN using Keras, where it will give a percent confidence in which class(es) an image falls. Unfortunately, I cannot seem to get it to give percentages, but just a 0 or 1 value for each class when I run the model.predict() method. Is there something wrong with my code, or has it just not been trained on enough images yet? (Yes, I am using new photos the model has never seen for predictions.)

#building the CNN
classifier = Sequential()

classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 
'relu'))

classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Dropout(0.25))

classifier.add(Flatten())

classifier.add(Dense(units = 128, activation = 'relu'))

classifier.add(Dense(units = 64, activation = 'relu'))

classifier.add(Dense(units = 4, activation = 'sigmoid'))

classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', 
metrics = ['accuracy'])

datagen = ImageDataGenerator(rescale = 1./255,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True,
validation_split = 0.1)

training_set = datagen.flow_from_directory('images',
target_size = (64, 64),
batch_size = 32,
class_mode = 'categorical',
subset = 'training')

test_set = datagen.flow_from_directory('images',
target_size = (64, 64),
batch_size = 32,
class_mode = 'categorical',
subset = 'validation')

classifier.fit_generator(training_set,
steps_per_epoch = training_set.samples,
epochs = 10,
validation_data = test_set,
validation_steps = test_set.samples)

#predicting new image class
test_image = image.load_img(r'XXXX', target_size = (64, 64))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = classifier.predict_proba(test_image)
print (result)

Training output:

# Epoch 10/10
# 237/237 [==============================] - 14s 58ms/step - loss: 1.3194e-04 - acc: 1.0000 - val_loss: 0.0312 - val_acc: 0.9860

These are my loss/accuracies.

[[1. 1. 0. 0.]]

This is an example result of predicting a new image. I have even given my model highly unrelated images which still come back with similar results.

I realize that 237 photos is a very small training pool; I will be increasing the image database over the next few months.

Engineero
  • 12,340
  • 5
  • 53
  • 75
scalywag
  • 3
  • 2

1 Answers1

2

To get a percentage output, use a softmax activation function in your output layer to get the probabilities. You should not use sigmoid activation function anyways due to the vanishing gradient problem with them.

classifier = Sequential()

classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 
'relu'))

classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Dropout(0.25))

classifier.add(Flatten())

classifier.add(Dense(units = 128, activation = 'relu'))

classifier.add(Dense(units = 64, activation = 'relu'))

classifier.add(Dense(units = 4, activation = 'softmax'))

Another possible reason could be data scaling. Please refer to Returning probabilities in a classification prediction in Keras? for the solution.

Engineero
  • 12,340
  • 5
  • 53
  • 75
secretive
  • 2,032
  • 7
  • 16
  • I tried retraining the CNN with the output layer as softmax and am still getting 0 or 1 results. https://github.com/keras-team/keras/issues/741 is why I initially did not use softmax. – scalywag May 13 '19 at 21:16
  • what is your dataset. Please describe the classification task. also check this link https://stackoverflow.com/questions/47599436/returning-probabilities-in-a-classification-prediction-in-keras – secretive May 13 '19 at 21:21
  • My task is to classify leaf tissue into 4 disease categories. I just checked that link and realized I had not rescaled my prediction images. Problem appears to be solved. Thank you! – scalywag May 13 '19 at 21:25
  • accept the answer to show that you found the solution. – secretive May 13 '19 at 21:31