We implement a Convolutional Neural Network to classify MNIST digits based on LeNet.
In [1]:
from __future__ import division, print_function
from keras.callbacks import Callback
from keras.models import Sequential
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.layers.core import Activation, Flatten, Dense
from keras.optimizers import SGD
from keras.utils import np_utils
from sklearn import datasets
from sklearn.cross_validation import train_test_split
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
In [2]:
dataset = datasets.fetch_mldata("MNIST Original")
X = dataset.data
X = X.reshape((X.shape[0], 28, 28))
X = X[:, np.newaxis, :, :] # add channel
X = X / 255.0
Y = np_utils.to_categorical(dataset.target.astype("int"), 10)
In [3]:
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X, Y, test_size=0.3, random_state=0)
print(Xtrain.shape, Xtest.shape, Ytrain.shape, Ytest.shape)
In [4]:
model = Sequential()
# first convolutional layer
model.add(Convolution2D(20, 5, 5, border_mode="same", input_shape=(1, 28, 28)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# second convolution layer
model.add(Convolution2D(50, 5, 5, border_mode="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# first fully connected layer
model.add(Flatten())
model.add(Dense(512))
model.add(Activation("relu"))
# second fully connected layer + softmax
model.add(Dense(10))
model.add(Activation("softmax"))
optimizer = SGD(lr=0.01)
model.compile(loss="categorical_crossentropy", optimizer=optimizer,
metrics=["accuracy"])
In [5]:
# customized callback
class LossHistory(Callback):
def on_train_begin(self, logs={}):
self.losses = []
def on_batch_end(self, batch, logs={}):
self.losses.append(logs.get("loss"))
In [6]:
history = LossHistory()
model.fit(Xtrain, Ytrain, batch_size=128, nb_epoch=10,
validation_data=(Xtest, Ytest), callbacks=[history])
Out[6]:
In [7]:
loss = model.evaluate(Xtest, Ytest, batch_size=128)
print("loss on test set: %.3f, accuracy: %.3f" % (loss[0], loss[1]))
In [8]:
plt.plot(range(len(history.losses)), history.losses)
plt.xlabel("time")
plt.ylabel("loss")
plt.grid()
plt.show()
In [9]:
Xtests = np.zeros((10, 1, 28, 28))
for idx, i in enumerate(np.random.randint(0, Xtest.shape[0], 10)):
Xtests[idx] = Xtest[i, 0]
Y_ = model.predict(Xtests)
y_ = np_utils.categorical_probas_to_classes(Y_)
print(y_)
for i in range(10):
img = Xtests[i, 0]
plt.imshow(img)
plt.show()
print("Predicted class: %d" % (y_[i]))
In [ ]: