Ludy
Ludy

Reputation: 23

Keras model predicts same class

I am new in the field of Deep Learning and I tried to train a model for image classification. I used a pre-trained model (ResNet50) and added own layers. The Dataset I use for training contains about 1000 images for each class and I separated it in train and test set. My problem is, that if I evaluate the Model with model.evaluate(test_set_generator) I get an accuracy of about 90%

If I load an Image and predict with model.predict(img) the result is always the same class

My generators:

img_height = 128
img_width = 128

train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)


train_generator = train_datagen.flow_from_directory(
    data_dir_path,
    target_size=(img_height, img_width),
    batch_size=16,
    shuffle=True,
    class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
    test_dir_path,
    target_size=(img_height, img_width),
    batch_size=16,
    class_mode='categorical')

my model:

    base_model = tf.keras.applications.ResNet50(input_shape=(img_height,img_width,3),
                                                   include_top=False,
                                                   weights='imagenet')
    prediction_layer = tf.keras.layers.Dense(5)

    model = models.Sequential()
    model.add(base_model)
    model.add(tf.keras.layers.GlobalAveragePooling2D())
    model.add(prediction_layer)

    base_learning_rate = 0.0005
    model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=base_learning_rate),
                  loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
                  metrics=['accuracy'])

How I am loading an Image:

test_image = image.load_img(path_to_image, target_size=(128, 128))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis=0)

I tried to load and predict every image from my test set and I got always the same result (that is a small output, but more or less every output looks the same):

 [[ -38774.88  -228962.86    20932.826 -169404.3   -265980.06 ]]
 [[ -54851.016 -320424.4     31585.99  -236997.28  -374307.2  ]]
 [[ -36518.344 -212326.48    18832.361 -156810.19  -244721.2  ]]
 [[ -31010.965 -196458.73    19816.562 -146228.39  -230922.06 ]]
 [[ -37712.95  -222710.1     19780.334 -164643.36  -256392.48 ]] 

I cant understand why the evaluation gets correct results and the prediction dont. I predicted the test_set_generator with model.predict(test_set_generator) and I got results that looked fine to me. The results were not always the same.

I tried to change the learning rate, more layers, a dropout layer, different amount of epochs and steps per epoch, a different pre-trained model and different batch sizes.

I am thankful for any suggestions

Upvotes: 2

Views: 1260

Answers (2)

akilat90
akilat90

Reputation: 5706

Your model expects the image values to be in range (0, 1).

Try with:

test_image = image.load_img(path_to_image, target_size=(128, 128))
test_image = image.img_to_array(test_image) / 255  # < - division by 255
test_image = np.expand_dims(test_image, axis=0)

Upvotes: 3

Thibault Bacqueyrisses
Thibault Bacqueyrisses

Reputation: 2331

There is two errors in your code :

  • First when you call a Dense layer without activation parameters, it will be a linear activation by default, in a multi-class prob we want a softmax activation
prediction_layer = tf.keras.layers.Dense(5, activation = "softmax")
  • Secondly, the loss, you are using binary_crossentropy, a loss used for binary classification, but here we, once again, have a multi-class problem, so you need to use the categorical_crossentropy loss
model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=base_learning_rate),
                  loss=tf.keras.losses.CategoricalCrossentropy(),
                  metrics=['accuracy'])

Upvotes: 0

Related Questions