I am training a CNN model with about 20.000 images with two classes each 10.000 images. The size of the images vary between 50*50 pixel and 1000x500 pixels. I am resizing all images to the average size of all images, which is 350x150 pixels. Then training a CNN with this architecture:
import cv2
import os
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.constraints import maxnorm
from keras.optimizers import SGD
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from sklearn.model_selection import train_test_split
import random
import matplotlib.pyplot as plt
data = []
labels = []
imagePaths = sorted(list(my_images))
random.seed(42)
random.shuffle(imagePaths)
# loop over the images
for imagePath in imagePaths:
image = cv2.imread(imagePath)
image = cv2.resize(image, (350, 150))
data.append(image)
# extract the class label from the image path and update the
# labels list
label = imagePath.split(os.path.sep)[-2].split('/')[-1]
if label == 'pos':
label = 1
elif label == 'neg':
label = 0
labels.append(label)
# scale the raw pixel intensities to the range [0, 1]
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)
# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.25, random_state=42)
unique, counts = np.unique(trainY, return_counts=True)
print(dict(zip(unique, counts)))
y_train = np_utils.to_categorical(trainY)
y_test = np_utils.to_categorical(testY)
num_classes = 2
# # # Create the model
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(150, 350, 3), activation='relu', border_mode='same'))
model.add(Dropout(0.2))
model.add(Convolution2D(32, 3, 3, activation='relu', border_mode='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
model.add(Dropout(0.2))
model.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(1024, activation='relu', W_constraint=maxnorm(3)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu', W_constraint=maxnorm(3)))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))
# Compile model
epochs = 25
lrate = 0.01
decay = lrate / epochs
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
I am getting an accuracy of 95 % which is really good and I am using it as production model. However I am wondering whether I can improve the accuracy since the number of images seems to be very high and the classification problem separable: example images
Is there any chance to improve the model and to squeeze out a bit more from the prediction?