GridSearchCV MNIST

Jerin K Antony
2 min readJun 15, 2020

Grid search becomes useful when it comes to finding best hyper-parameters for small models (models aimed for micro controllers, tiny processors etc)

Here is an MNIST example for grid search with scitkit learn,

Install the requirements using pip

And here is the full code!

import matplotlib.pyplot as plt# seed random number generator to improve reproducibility
import numpy as np
np.random.seed(22)
# the MNIST data set
from keras.datasets import mnist
# feed-forward neural network
from keras.models import Sequential
# required for dense final layers
from keras.layers import Dense, Flatten
# required for convolutional layers and max pooling
from keras.layers.convolutional import Conv2D, MaxPooling2D
# required to vectorize digit labels into one-hot encoding
from keras.utils import to_categorical
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import GridSearchCV
def create_model(conv_layers=[(4,5,2,2),(8,3,2,2)],
dense_layers=[50]):

print('model- conv_layers:', conv_layers, 'dense_layers:',dense_layers)
model = Sequential()
# add convolution layers
conv_layers_count = 0
for (filters, kernel_size, pooling_size, pool_stride) in conv_layers:
conv_layers_count += 1
if 1 == conv_layers_count:
# First convolutional layer
model.add(Conv2D(filters,
(kernel_size, kernel_size),
strides=(1, 1),
activation='relu',
input_shape=(28, 28, 1)))
model.add(MaxPooling2D(pool_size=(pooling_size, pooling_size),
strides=(pool_stride, pool_stride)))
else:
# Subsequent convolutional layer
model.add(Conv2D(filters,
(kernel_size, kernel_size),
strides=(1, 1),
activation='relu'))
model.add(MaxPooling2D(pool_size=(pooling_size, pooling_size),
strides=(pool_stride, pool_stride)))
# add dense layers
model.add(Flatten())
for nodes in dense_layers:
model.add(Dense(nodes, activation='relu'))
# Output layer
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.summary()
return modeldef grid_search(train_images, train_labels):
# Keras model is wrapped so that we can use it with Scikit-learn GridSearchCV
mnist_cnn_model = KerasClassifier(build_fn=create_model, verbose=2)
# Specify the hyperparameters we want to test
# 2x2x3 = 12 combinations
hyperparameters = {
'conv_layers': [[(4,5,2,2),(8,3,2,2)],
[(8,5,2,2),(16,3,2,2)]],
'dense_layers': [[50],[50,20]],
'epochs':[3, 5],
'batch_size':[64, 128, 256]
}
grid = GridSearchCV(estimator=mnist_cnn_model, param_grid=hyperparameters, cv=3, n_jobs = None)grid_result = grid.fit(train_images, train_labels)#import pdb;pdb.set_trace()
print('Best accuracy: {0:.4f}, Best Params: {1}'.format(grid_result.best_score_,
grid_result.best_params_))
return grid_resultif __name__ == '__main__':(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1).astype('float32')
train_images = train_images / 255
test_images = test_images / 255
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
grid_result = grid_search(train_images, train_labels)

model = create_model(conv_layers=grid_result.best_params_['conv_layers'], dense_layers=grid_result.best_params_['dense_layers'])
history = model.fit(train_images, train_labels,
epochs=grid_result.best_params_['epochs'],
batch_size=grid_result.best_params_['batch_size'],
verbose = 1)
scores = model.evaluate(test_images, test_labels, verbose=0)

print('Best accuracy: {0:.4f}, Best Params: {1}'.format(grid_result.best_score_,
grid_result.best_params_))

print("Accuracy: {0} Error: {1:.4f}".format(scores[1], (1-scores[1])*100))

Enjoy, See you next time.

--

--