1
$\begingroup$

I am new to CNNs and need some direction as I can't get any improvement in my validation results.

I am trying to do binary image classification on pictures of groups of small plastic pieces to detect defects. Unfortunately, I am unable to share pictures, but each picture is a group of round white pieces on a black background. One class includes pictures with all normal pieces, the other class includes pictures where two pieces in the picture are stuck together - and therefore defective.

I have a small data set: 250 pictures per class for training, 50 per class for validation, 30 per class for testing. The pictures are 256 x 256 pixels, although I can have a different resolution if needed.

Here is my CNN architecture:

classifier = Sequential()
classifier.add(Conv2D(32, (7, 7), padding="same", input_shape=(256, 256, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.5))

classifier.add(Conv2D(64, (5, 5), padding="same", input_shape=(256, 256, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.5))

classifier.add(Flatten())

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

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

# Treatment done to images:
train_datagen = ImageDataGenerator(rescale=1./255,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True)
validation_datagen = ImageDataGenerator(rescale=1./255)

train_batch_size = 10
val_batch_size = 10
num_epochs = 100
train_images = 250
val_images = 50

classifier.fit_generator(training_set,
                             steps_per_epoch=train_images // train_batch_size
                             epochs=num_epochs,
                             validation_data=validation_set,
                             validation_steps=val_images // val_batch_size) 

Here are the results:

Plot

It's overfitting and the validation loss increases over time. The validation accuracy is not better than a coin toss, so clearly my model is not learning anything.

I have tried different values of dropout and L1/L2 for both the convolutional and FC layers, but validation accuracy is never better than a coin toss.

I understand that my data set is very small, but even getting a small increase in validation would be acceptable as long as my model seems correct, which it doesn't at this point.

Update: Switching from binary to multiclass classification helped raise the validation accuracy and reduced the validation loss, but it still grows consistenly:

Plot 2

Any advice would be very appreciated. Thanks in advance!

$\endgroup$
  • $\begingroup$ Instead of binary classification, make a multiclass classification with two classes. You are using relu with sigmoid which might cause the instability. I insist to use softmax at the output layer. $\endgroup$ – Shubham Panchal Jul 19 '19 at 0:30
  • $\begingroup$ Thank you, @ShubhamPanchal. I switched to multiclass classification and am using softmax with relu instead of sigmoid, which helped improved the results slightly. However, the validation loss continues increasing instead of decreasing. Do you recommend making any other changes to the architecture to solve it? $\endgroup$ – Irina Jul 19 '19 at 14:15
1
$\begingroup$

Your data set is very small, so you definitely should try your luck at transfer learning, if it is an option.

Other than that, you probably should have a dropout layer after the dense-128 layer. Also, it is probably a good idea to remove dropouts after pooling layers. Instead, you can try using SpatialDropout after convolutional layers.

$\endgroup$
0
$\begingroup$

I suggest you:

  • Lower the size of the kernel filters. The best filter is (3, 3). I think that a (7, 7) is leaving too much information out.
  • If the size of the images is too big, consider the possiblity of rescaling them before training the CNN.
  • If possible, remove one Max-Pool layer.
  • Lower dropout, that looks too high IMHO (but other people might disagree with me on this). I usually set it between 0.1-0.25.
  • The number of output nodes should equal the number of classes.
$\endgroup$
  • $\begingroup$ Thank you, Leevo. I changed the number of output nodes, which was a mistake on my part. Unfortunately, I wasn't able to remove any Max-Pool layers and have it still work. I have tried a few combinations of the other suggestions without much success, but I will keep trying. Thanks again. $\endgroup$ – Irina Jul 22 '19 at 14:57

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.