|
| 1 | +'''Example of how to use sklearn wrapper |
| 2 | +
|
| 3 | +Builds simple CNN models on MNIST and uses sklearn's GridSearchCV to find best model |
| 4 | +''' |
| 5 | + |
| 6 | +from __future__ import print_function |
| 7 | +import numpy as np |
| 8 | +np.random.seed(1337) # for reproducibility |
| 9 | + |
| 10 | +from keras.datasets import mnist |
| 11 | +from keras.models import Sequential |
| 12 | +from keras.layers.core import Dense, Dropout, Activation, Flatten |
| 13 | +from keras.layers.convolutional import Convolution2D, MaxPooling2D |
| 14 | +from keras.utils import np_utils |
| 15 | +from keras.wrappers.scikit_learn import KerasClassifier |
| 16 | +from sklearn.grid_search import GridSearchCV |
| 17 | + |
| 18 | + |
| 19 | +nb_classes = 10 |
| 20 | + |
| 21 | +# input image dimensions |
| 22 | +img_rows, img_cols = 28, 28 |
| 23 | + |
| 24 | +# load training data and do basic data normalization |
| 25 | +(X_train, y_train), (X_test, y_test) = mnist.load_data() |
| 26 | +X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols) |
| 27 | +X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols) |
| 28 | +X_train = X_train.astype('float32') |
| 29 | +X_test = X_test.astype('float32') |
| 30 | +X_train /= 255 |
| 31 | +X_test /= 255 |
| 32 | + |
| 33 | +# convert class vectors to binary class matrices |
| 34 | +y_train = np_utils.to_categorical(y_train, nb_classes) |
| 35 | +y_test = np_utils.to_categorical(y_test, nb_classes) |
| 36 | + |
| 37 | +def make_model(dense_layer_sizes, nb_filters, nb_conv, nb_pool): |
| 38 | + '''Creates model comprised of 2 convolutional layers followed by dense layers |
| 39 | +
|
| 40 | + dense_layer_sizes: List of layer sizes. This list has one number for each layer |
| 41 | + nb_filters: Number of convolutional filters in each convolutional layer |
| 42 | + nb_conv: Convolutional kernel size |
| 43 | + nb_pool: Size of pooling area for max pooling |
| 44 | + ''' |
| 45 | + |
| 46 | + model = Sequential() |
| 47 | + |
| 48 | + model.add(Convolution2D(nb_filters, nb_conv, nb_conv, |
| 49 | + border_mode='valid', |
| 50 | + input_shape=(1, img_rows, img_cols))) |
| 51 | + model.add(Activation('relu')) |
| 52 | + model.add(Convolution2D(nb_filters, nb_conv, nb_conv)) |
| 53 | + model.add(Activation('relu')) |
| 54 | + model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool))) |
| 55 | + model.add(Dropout(0.25)) |
| 56 | + |
| 57 | + model.add(Flatten()) |
| 58 | + for layer_size in dense_layer_sizes: |
| 59 | + model.add(Dense(layer_size)) |
| 60 | + model.add(Activation('relu')) |
| 61 | + model.add(Dropout(0.5)) |
| 62 | + model.add(Dense(nb_classes)) |
| 63 | + model.add(Activation('softmax')) |
| 64 | + |
| 65 | + model.compile(loss='categorical_crossentropy', |
| 66 | + optimizer='adadelta', |
| 67 | + metrics=['accuracy']) |
| 68 | + |
| 69 | + return model |
| 70 | + |
| 71 | +dense_size_candidates = [[32], [64], [32, 32], [64, 64]] |
| 72 | +my_classifier = KerasClassifier(make_model, batch_size=32) |
| 73 | +validator = GridSearchCV(my_classifier, |
| 74 | + param_grid={'dense_layer_sizes': dense_size_candidates, |
| 75 | + # nb_epoch is avail for tuning even when not |
| 76 | + # an argument to model building function |
| 77 | + 'nb_epoch': [3, 6], |
| 78 | + 'nb_filters': [8], |
| 79 | + 'nb_conv': [3], |
| 80 | + 'nb_pool': [2]}, |
| 81 | + scoring='log_loss', |
| 82 | + n_jobs=1) |
| 83 | +validator.fit(X_train, y_train) |
| 84 | + |
| 85 | +print('The parameters of the best model are: ') |
| 86 | +print(validator.best_params_) |
| 87 | + |
| 88 | +# validator.best_estimator_ returns sklearn-wrapped version of best model. |
| 89 | +# validator.best_estimator_.model returns the (unwrapped) keras model |
| 90 | +best_model = validator.best_estimator_.model |
| 91 | +metric_names = best_model.metrics_names |
| 92 | +metric_values = best_model.evaluate(X_test, y_test) |
| 93 | +for metric, value in zip(metric_names, metric_values): |
| 94 | + print(metric, ': ', value) |
0 commit comments