0
$\begingroup$

I'm trying to do image classification using CNN. The exact model isn't important but I decided to try use AlexNet and I'm getting abysmal accuracy.

I believe the issue might be with my data preprocessing. My dataset directory contains a Training and Test folder but no validation folder (I have to split the dataset myself) and they are layed out like this:

Training
├── class0
│   ├── image1
│   ├── ....
│   └── image20
│
├── ....
│   ├── image1
│   ├── ....
│   └── image20
│
└── class9
    ├── image1
    ├── ....
    └── image20

Here is my AlexNet model, the code is below:

model = tf.keras.models.Sequential([
    #Conv_1          #original model was built for input shape of 224X224
    tf.keras.layers.Conv2D(96, (11,11),strides=4, padding='valid', activation='relu', input_shape=(224, 224, 3)),
    # Pooling_1
    tf.keras.layers.MaxPooling2D((2, 2), strides=(2,2),padding='valid'),
    # Batch Normalisation_1
    tf.keras.layers.BatchNormalization(),
    # Conv_2
    tf.keras.layers.Conv2D(256, (11,11),strides=1, padding='valid', activation='relu'),
    # Pooling_2
    tf.keras.layers.MaxPooling2D((2, 2), strides=(2,2),padding='valid'),
    #Batch Normalisation_2
    tf.keras.layers.BatchNormalization(),
    # Conv_3
    tf.keras.layers.Conv2D(384, (3,3),strides=1, padding='valid', activation='relu'),
    # Batch Normalisation_3
    tf.keras.layers.BatchNormalization(),
    # Conv_4
    tf.keras.layers.Conv2D(384, (3,3),strides=1, padding='valid', activation='relu'),
    # Batch Normalisation_3
    tf.keras.layers.BatchNormalization(),
    #conv_5
    tf.keras.layers.Conv2D(256, (3,3),strides=1, padding='valid', activation='relu'),
    #pooling_3
    tf.keras.layers.MaxPooling2D((2, 2), strides=(2,2),padding='valid'),
    #Batch Normalization_4
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Flatten(),
    #Dense layer_1
    tf.keras.layers.Dense(4096, activation='relu'),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.BatchNormalization(),
    #Dense layer_2
    tf.keras.layers.Dense(4096, activation='relu'),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.BatchNormalization(),
    #Dense layer_3
    tf.keras.layers.Dense(1000, activation='relu'),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(1, activation='sigmoid')
    ])

As for what I did to preprocess my data:

train_dir = '/content/gdrive/My Drive/x/Training'
test_dir = '/content/gdrive/My Drive/x/Test'

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',
      )

test_datagen = ImageDataGenerator(rescale=1./255, validation_split=0.4)


train_generator = train_datagen.flow_from_directory(
        train_dir,  
        target_size=(224, 224),  
        batch_size=20,
        class_mode='binary')


validation_generator = test_datagen.flow_from_directory(
        test_dir,
        target_size=(224, 224),
        batch_size=20,
        class_mode='binary',
        subset='validation')

model.compile(loss='binary_crossentropy',
              optimizer=RMSprop(lr=1e-4),
              metrics=['acc'])

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,  
      epochs=10,
      validation_data=validation_generator,
      validation_steps=10,  
      #callbacks = [checkpoint],
      verbose=2)

Any and all help will be immensely appreciated! Thank you to anyone who may reply.

$\endgroup$
  • $\begingroup$ Why your class_mode is "binary", though it seems 10 Classes of image. Please show your y_test and y_pred $\endgroup$ – 10xAI May 31 at 3:10
  • $\begingroup$ I don't know how to check y_test and y_pred but umm I have several classes. I just realised this as well but it seems I shouldn't do binary but categorical? $\endgroup$ – aguythatneedshelp May 31 at 3:46
  • $\begingroup$ No...You can simply follow this example from Keras official keras.io/examples/cifar10_cnn Your last layer and Loss fn will also change (Just an FYI) $\endgroup$ – 10xAI May 31 at 4:30
  • $\begingroup$ The cifar10 cnn link did not help very much but the advice on the binary class fixed my issue, thanks! $\endgroup$ – aguythatneedshelp Jun 2 at 13:53
0
$\begingroup$

Find a working Keras setup for a pretrained model with custom data generator here.

Note that validation data should not be augmented!

from keras.preprocessing.image import ImageDataGenerator

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')

# Validation data should not be augmented!
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=20,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=lr_first), # 2e-5
              metrics=['acc'])
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you for answering! Your response did not help me but I've solved my preprocessing data issue already. I am still thankful you bothered to reply though! $\endgroup$ – aguythatneedshelp Jun 2 at 13:54
  • $\begingroup$ @aguythatneedshelp: Maybe you answer your own question if you think it can help other people. $\endgroup$ – Peter Jun 2 at 15:17
0
$\begingroup$

Since someone said that if I solved my answer I should answer my own question: What I did was:

train_generator = train_datagen.flow_from_directory(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=20,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='categorical')

model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.RMSprop(lr=lr_first), # 2e-5
              metrics=['acc'])

Basically replaced the binary labels with categorical.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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