# How do I handle with my Keras CNN overfitting

In my CNN, I have 700 images of class 0, 700 images of class 1, and 72 validation images.

My code:

visible = Input(shape=(256,256,3))
conv1 = Conv2D(16, kernel_size=(3,3), activation='relu', strides=(1, 1))(visible)
conv2 = Conv2D(32, kernel_size=(3,3), activation='relu', strides=(1, 1))(conv1)
bat1 = BatchNormalization()(conv2)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv3)
drop1 = Dropout(0.30)(pool1)

conv4 = Conv2D(32, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(drop1)
conv5 = Conv2D(64, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(conv4)
bat2 = BatchNormalization()(conv5)
pool2 = MaxPooling2D(pool_size=(1, 1))(bat2)
drop1 = Dropout(0.30)(pool2)

conv6 = Conv2D(128, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(pool2)
conv7 = Conv2D(128, kernel_size=(2,2), activation='relu', strides=(1, 1), padding='valid')(conv6)
bat3 = BatchNormalization()(conv7)
pool3 = MaxPooling2D(pool_size=(1, 1))(bat3)
drop1 = Dropout(0.30)(pool3)

flat = Flatten()(pool3)
drop4 = Dropout(0.50)(flat)

output = Dense(1, activation='sigmoid')(drop4)
model = Model(inputs=visible, outputs=output)

model.compile(optimizer= opt, loss='binary_crossentropy', metrics=['accuracy'])

data = np.array(data)
labels = np.array(labels)

perm = np.random.permutation(len(data))
data = data[perm]
labels = labels[perm]
#model.fit(data, labels, epochs=8, validation_data = (np.array(test), np.array(lt)))

aug = ImageDataGenerator(rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15,
horizontal_flip=True)

# train the network
model.fit_generator(aug.flow(data, labels, batch_size=32),
validation_data=(np.array(test), np.array(lt)), steps_per_epoch=len(data) // 32,
epochs=7)

model.save('model.h5')


It returns these numbers:

Epoch 1/7
43/43 [==============================] - 1004s 23s/step - loss: 1.8090 - acc: 0.9724 - val_loss: 1.7871 - val_acc: 0.9861
Epoch 2/7
43/43 [==============================] - 1003s 23s/step - loss: 1.8449 - acc: 0.9801 - val_loss: 1.4828 - val_acc: 1.0000
Epoch 3/7
43/43 [==============================] - 1092s 25s/step - loss: 1.5704 - acc: 0.9920 - val_loss: 1.3985 - val_acc: 1.0000
Epoch 4/7
43/43 [==============================] - 1062s 25s/step - loss: 1.5219 - acc: 0.9898 - val_loss: 1.3167 - val_acc: 1.0000
Epoch 5/7
43/43 [==============================] - 990s 23s/step - loss: 2.5744 - acc: 0.9222 - val_loss: 2.9347 - val_acc: 0.9028
Epoch 6/7
43/43 [==============================] - 983s 23s/step - loss: 1.6053 - acc: 0.9840 - val_loss: 1.3299 - val_acc: 1.0000
Epoch 7/7
43/43 [==============================] - 974s 23s/step - loss: 1.6180 - acc: 0.9801 - val_loss: 1.5181 - val_acc: 0.9861


When I predict some test images, the result is always 0.

I already tried various things like adding more dropouts (or making the dropout rate bigger), data augmentation, batch normalization etc. and none of these have made it work properly.

What should I do?

• Let it run longer Sep 24 '19 at 17:45
• This is a big network when you only have ~1500 images Sep 24 '19 at 17:46
• Use dropout in your dense layers. The other comment is also true and has to be considered. Sep 24 '19 at 18:39
• I have only one dense layer and there's a dropout in there. How much I have to reduce my layers? 3 convolutionals? 4? Sep 24 '19 at 19:23

If you have less number of images, my advice to you is to use transfer learning. Use the model according to your dataset like VGG16, VGG19 and do transfer learning instead of creating a new model. the advantages of using transfer learning are like: 1. pre-trained model often speeds up the process of training the model on a new task. The model has already optimized weight so it might help to overcome overfitting.

as your data is very less, you should go for transfer learning as @muneeb already suggested, because that will already come with most learned parameters and then you can train that model using your custom dataset.

you can try out pre-trained models from here

If you want to go for your existing custom configured model only, try adding another Dense layer before the output.

like a Dense(128, activation='relu').

Share your results here, so that we can explore more.

• Ok, I'll try to use VGG16, thanks for your contribution, i'm gonna make new questions about it.. Sep 26 '19 at 12:00
• looking forward to see that, if you think my answer was helpful please mark it as an answer. Sep 26 '19 at 12:06

As other answers mentioned, using VGG like pre-trained models will help. But when you are saying its always coming as 0, following things you can check in your code:

1. Are class labels proper? It can be the case that all are 0 class.
2. See softmax value of predictions, are they different. If not then we have a problem.
3. Try without Drop out and batch normalization.
4. Check if predictions are fine on train data. It might be possible that there is an error in your invocation code. (Like you are processing image differently while training as compared to invoking)
5. After CNN layers, as @desmond mentioned, use the Dense layer or even Global Max pooling. Also, check to remove BatchNorm and dropout, sometimes they behave differently.
6. Last and most likely this is the case: How different are your images in the train as compared to validation. If they are from different camera or something it will be different and these things cause issues