1
$\begingroup$

I'm trying to build a deep learning model to predict image classes from the Kaggle competition. I'm using the Xception model as the top layers and then putting the last layer into a dense layer with the softmax output of 4. No matter what I try with the model, it only predicts one class, the first-class 'healthy', even on the training set which gets a high accuracy. The data set is imbalanced in the multiple_diseases class, but even when I use RandomOverSampler, I get the same problem. There has to be an error in the way I am uploading my images or feeding them into the model. predict function. Anyway, here is the code:

healthy: 516 multiple_diseases: 91 rust: 622 scab: 592

train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')
targets = train_df[['healthy', 'multiple_diseases', 'rust', 'scab']]

print(train_df.describe())
print(test_df.describe())

           healthy  multiple_diseases         rust         scab
count  1821.000000        1821.000000  1821.000000  1821.000000
mean      0.283361           0.049973     0.341571     0.325096
std       0.450754           0.217948     0.474367     0.468539
min       0.000000           0.000000     0.000000     0.000000
25%       0.000000           0.000000     0.000000     0.000000
50%       0.000000           0.000000     0.000000     0.000000
75%       1.000000           0.000000     1.000000     1.000000
max       1.000000           1.000000     1.000000     1.000000

from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from tqdm.notebook import tqdm

path = '/content/images/'
num_img = train_df.shape[0]
size = 224
train_images = np.ndarray(shape=(train_len, size, size, 3))
    for i in tqdm(range(num_img)):
      img = load_img(path + f'Train_{i}.jpg', target_size=(size, size))
      train_images[i] = np.float32(img_to_array(img))

test_images = np.ndarray(shape=(test_len, size, size, 3))
    for i in tqdm(range(num_img)):
      img = load_img(path + f'Test_{i}.jpg', target_size=(size, size))
      test_images[i] = np.float32(img_to_array(img))

from keras_preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale = 1./255,
      rotation_range=40,
      horizontal_flip=True,
      vertical_flip=True,
      fill_mode='nearest')

validation_datagen = ImageDataGenerator(rescale = 1./255)

train_generator = train_datagen.flow(
    x = x_train, 
    y = y_train,
    batch_size = 32
    )

validation_generator = validation_datagen.flow(
    x = x_test,
    y = y_test,
    batch_size = 32
    )

def create_model():
  pretrained_model = tf.keras.applications.Xception(input_shape=[*[224, 224], 3], include_top=False)
  pretrained_model.trainable = True
  model = tf.keras.Sequential([
      pretrained_model,
      tf.keras.layers.GlobalAveragePooling2D(),
      tf.keras.layers.Dense(4, activation='softmax')
      ])

  model.compile(
        loss = 'categorical_crossentropy', 
        optimizer = 'adam', 
    metrics = ['accuracy'])
  return model

model = create_model()

model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param    
=================================================================
xception (Model)             (None, 7, 7, 2048)        20861480  
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048)              0         
_________________________________________________________________
dense (Dense)                (None, 4)                 8196      
=================================================================
Total params: 20,869,676
Trainable params: 20,815,148
Non-trainable params: 54,528
_________________________________________________________________

epochs = 12
batch_size = 32
steps_per_epoch = 55

start_lr = 0.00001
min_lr = 0.00001
max_lr = 0.00005
rampup_epochs = 5
sustain_epochs = 0
exp_decay = .8

def lrfn(epoch):
  if epoch < rampup_epochs:
    return (max_lr - start_lr)/rampup_epochs * epoch + start_lr
  elif epoch < rampup_epochs + sustain_epochs:
    return max_lr
  else:
    return (max_lr - min_lr) * exp_decay**(epoch-rampup_epochs-sustain_epochs) + min_lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lambda epoch: lrfn(epoch), verbose=True)

history = model.fit(
    train_generator,  
    validation_data = validation_generator,
    epochs = epochs,
    steps_per_epoch = steps_per_epoch,
    validation_steps = steps_per_epoch,
    callbacks = [lr_callback],
    verbose=1)

Epoch 00001: LearningRateScheduler reducing learning rate to 1e-05.
Epoch 1/12
55/55 [==============================] - 25s 454ms/step - loss: 1.3612 - accuracy: 0.3166 - val_loss: 1.2711 - val_accuracy: 0.4729 - lr: 1.0000e-05

Epoch 00002: LearningRateScheduler reducing learning rate to 1.8000000000000004e-05.
Epoch 2/12
55/55 [==============================] - 24s 435ms/step - loss: 1.1027 - accuracy: 0.6805 - val_loss: 0.8197 - val_accuracy: 0.7671 - lr: 1.8000e-05

Epoch 00003: LearningRateScheduler reducing learning rate to 2.6000000000000002e-05.
Epoch 3/12
55/55 [==============================] - 24s 435ms/step - loss: 0.6554 - accuracy: 0.8310 - val_loss: 0.4950 - val_accuracy: 0.8487 - lr: 2.6000e-05

Epoch 00004: LearningRateScheduler reducing learning rate to 3.4000000000000007e-05.
Epoch 4/12
55/55 [==============================] - 24s 435ms/step - loss: 0.3981 - accuracy: 0.8714 - val_loss: 0.4149 - val_accuracy: 0.8696 - lr: 3.4000e-05

Epoch 00005: LearningRateScheduler reducing learning rate to 4.2000000000000004e-05.
Epoch 5/12
55/55 [==============================] - 24s 434ms/step - loss: 0.3024 - accuracy: 0.8991 - val_loss: 0.3442 - val_accuracy: 0.8785 - lr: 4.2000e-05

Epoch 00006: LearningRateScheduler reducing learning rate to 5e-05.
Epoch 6/12
55/55 [==============================] - 24s 436ms/step - loss: 0.2155 - accuracy: 0.9291 - val_loss: 0.3372 - val_accuracy: 0.8910 - lr: 5.0000e-05

Epoch 00007: LearningRateScheduler reducing learning rate to 4.2000000000000004e-05.
Epoch 7/12
55/55 [==============================] - 24s 436ms/step - loss: 0.1778 - accuracy: 0.9435 - val_loss: 0.2799 - val_accuracy: 0.8958 - lr: 4.2000e-05

Epoch 00008: LearningRateScheduler reducing learning rate to 3.5600000000000005e-05.
Epoch 8/12
55/55 [==============================] - 24s 436ms/step - loss: 0.1446 - accuracy: 0.9516 - val_loss: 0.2872 - val_accuracy: 0.9041 - lr: 3.5600e-05

Epoch 00009: LearningRateScheduler reducing learning rate to 3.0480000000000006e-05.
Epoch 9/12
55/55 [==============================] - 24s 436ms/step - loss: 0.1359 - accuracy: 0.9539 - val_loss: 0.2637 - val_accuracy: 0.9017 - lr: 3.0480e-05

Epoch 00010: LearningRateScheduler reducing learning rate to 2.6384000000000004e-05.
Epoch 10/12
55/55 [==============================] - 24s 435ms/step - loss: 0.1164 - accuracy: 0.9596 - val_loss: 0.2602 - val_accuracy: 0.9130 - lr: 2.6384e-05

Epoch 00011: LearningRateScheduler reducing learning rate to 2.3107200000000005e-05.
Epoch 11/12
55/55 [==============================] - 24s 435ms/step - loss: 0.1209 - accuracy: 0.9723 - val_loss: 0.2699 - val_accuracy: 0.9124 - lr: 2.3107e-05

Epoch 00012: LearningRateScheduler reducing learning rate to 2.0485760000000004e-05.
Epoch 12/12
55/55 [==============================] - 24s 435ms/step - loss: 0.0896 - accuracy: 0.9758 - val_loss: 0.2449 - val_accuracy: 0.9113 - lr: 2.0486e-05

probabilities = model.predict(test_images)
print(probabilities)

[[1.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00]
 [1.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00]
 [1.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00]
 ...
 [1.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00]
 [1.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00]
 [1.000000e+00 0.000000e+00 0.000000e+00 5.321019e-38]]

Same thing for training images:

idx = 500
tester = np.reshape(train_images[idx], (1, size, size, 3))
print(tester.shape)
print(train_df.iloc[idx,:])

probabilities = model.predict(tester)
print(probabilities)

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

And it does that for all the training images. What is going on here?

Edit: Including a description of the data set.

$\endgroup$

1 Answer 1

1
$\begingroup$

You have 1760 samples and you are using a pre-trained model with 12 epochs which has 20,815,148 trainable params. So, do not use the F-35 fighter to kill a mosquito. You better use a simpler model like simpler Neural Networks or even Logistic Regression.

$\endgroup$
4
  • $\begingroup$ Would it not be 55*32 images/samples? I'm doing batch size 32 and 55 steps per epoch, per this post datascience.stackexchange.com/questions/29719/…. $\endgroup$ Commented Mar 28, 2020 at 15:41
  • $\begingroup$ Ok, 1760 samples you have. What is the distribution of your samples in each class? $\endgroup$
    – amin
    Commented Mar 28, 2020 at 15:48
  • 1
    $\begingroup$ I edited the post to include a describe on train_df, which includes the distribution among the labels. Sorry about that. $\endgroup$ Commented Mar 28, 2020 at 15:49
  • $\begingroup$ Did you try to use two-layer Perceptron or CNN? I believe that your model is too complex for this data. Use your test data as validation data and see how much accuracy you get per epoch. $\endgroup$
    – amin
    Commented Mar 28, 2020 at 16:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.