Search code examples
pythontensorflowkeras

keras always return same values in a Human horses CNN model example


I'm working on a CNN model with Keras for Human vs Horses dataset to predict some images.

with following codes I build the model and save in a file:

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import RMSprop

training_dir = 'horse-or-human/training'

train_datagen = ImageDataGenerator(
    rescale=1/255,
    rotation_range=40,
    width_shift_range= 0.2,
    height_shift_range= 0.2,
    shear_range=0.2,
    zoom_range= 0.2,
    horizontal_flip= True,
    fill_mode='nearest'
)

train_generator = train_datagen.flow_from_directory(training_dir , target_size=(300,300) , class_mode='binary')

model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(16 , (3,3), activation=tf.nn.relu , input_shape = (300,300,3)),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(32 , (3,3), activation=tf.nn.relu),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(64 , (3,3), activation=tf.nn.relu),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(64 , (3,3), activation=tf.nn.relu),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(64 , (3,3), activation=tf.nn.relu),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(512 ,activation=tf.nn.relu ),
    tf.keras.layers.Dense(1, activation = tf.nn.sigmoid)   
])

model.compile(optimizer = RMSprop(learning_rate = 0.001) , metrics=['accuracy'] , loss='binary_crossentropy' )

validation_dir = 'horse-or-human/validation'

validation_datagen = ImageDataGenerator(rescale=1/255)

validation_generator = validation_datagen.flow_from_directory(
    validation_dir ,
    target_size=(300,300) ,
    class_mode='binary'
)

model.fit(train_generator , epochs= 15 ,validation_data=validation_generator)

model.save('human-horses-model.h5')

And this part of my code that using that model to predict s specific image :

import tensorflow as tf
from ipyfilechooser import FileChooser
import keras.utils as image
import numpy as np

model = tf.keras.models.load_model('human-horses-model.h5')

fc = FileChooser()
display(fc)

img = image.load_img(fc.selected , target_size=(300,300))


img = image.img_to_array(img)
img /= 255.

img = np.expand_dims(img , axis=0)

output = model.predict(img)

if output[0]> 0.5 :
    print('selected Image is a Human')
else :
    print('selected Image is a Horses')

And following is output of each epochs:

Found 256 images belonging to 2 classes.
Epoch 1/15
33/33 [==============================] - 83s 2s/step - loss: 0.7800 - accuracy: 0.5686 - val_loss: 0.6024 - val_accuracy: 0.5859
Epoch 2/15
33/33 [==============================] - 73s 2s/step - loss: 0.6430 - accuracy: 0.6777 - val_loss: 0.8060 - val_accuracy: 0.5586
Epoch 3/15
33/33 [==============================] - 77s 2s/step - loss: 0.5252 - accuracy: 0.7595 - val_loss: 0.7498 - val_accuracy: 0.6875
Epoch 4/15
33/33 [==============================] - 79s 2s/step - loss: 0.4754 - accuracy: 0.7731 - val_loss: 1.7478 - val_accuracy: 0.5938
Epoch 5/15
33/33 [==============================] - 77s 2s/step - loss: 0.3966 - accuracy: 0.8130 - val_loss: 2.0004 - val_accuracy: 0.5234
Epoch 6/15
33/33 [==============================] - 73s 2s/step - loss: 0.4196 - accuracy: 0.8442 - val_loss: 0.3918 - val_accuracy: 0.8281
Epoch 7/15
33/33 [==============================] - 73s 2s/step - loss: 0.2859 - accuracy: 0.8802 - val_loss: 1.6727 - val_accuracy: 0.6680
Epoch 8/15
33/33 [==============================] - 74s 2s/step - loss: 0.2489 - accuracy: 0.8929 - val_loss: 3.1737 - val_accuracy: 0.6484
Epoch 9/15
33/33 [==============================] - 76s 2s/step - loss: 0.2829 - accuracy: 0.8948 - val_loss: 1.8389 - val_accuracy: 0.7109
Epoch 10/15
33/33 [==============================] - 76s 2s/step - loss: 0.2140 - accuracy: 0.9250 - val_loss: 1.8419 - val_accuracy: 0.7930
Epoch 11/15
33/33 [==============================] - 73s 2s/step - loss: 0.2341 - accuracy: 0.9299 - val_loss: 1.5261 - val_accuracy: 0.6914
Epoch 12/15
33/33 [==============================] - 74s 2s/step - loss: 0.1576 - accuracy: 0.9464 - val_loss: 0.9359 - val_accuracy: 0.8398
Epoch 13/15
33/33 [==============================] - 75s 2s/step - loss: 0.2002 - accuracy: 0.9250 - val_loss: 1.9854 - val_accuracy: 0.7344
Epoch 14/15
33/33 [==============================] - 79s 2s/step - loss: 0.1854 - accuracy: 0.9406 - val_loss: 0.7637 - val_accuracy: 0.8164
Epoch 15/15
33/33 [==============================] - 80s 2s/step - loss: 0.1160 - accuracy: 0.9611 - val_loss: 1.6901 - val_accuracy: 0.7656

My model always return 1 or a number very near to 1 that show all images are Human while in real that are Horse.

I searched a lot but did not find the answer!

Can anyone help me to find and solve the problem.


Solution

  • Please use class_mode='sparse' as you are using the image dataset and Adam optimzer for better results or change the kernel size to (7,7) or (5,5) to convolve the large image dataset efficiently.

    (I have replicated the same code and attached the gist for your reference which predicts the expected result as you can see in the image below)

    You can also try using Pretrained model or Strategies to prevent overfitting for fine tune the model performance.

    enter image description here