In [1]:
%matplotlib inline  
import struct
from struct import unpack
from numpy import zeros, uint8, float32
from pylab import imshow, show, cm
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import subprocess


#Initialize for keras
import keras
from keras.datasets import mnist
from keras.models import Sequential, Input,Model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D
from keras import backend as K


Using TensorFlow backend.

In [2]:
# Define functions for reading data.
# Based on https://gist.github.com/tylerneylon/
def read_idx(filename):
    """
        Read from file and create numpy array
    """
    with open(filename, 'rb') as f:
        zero, data_type, dims = struct.unpack('>HBB', f.read(4))
        shape = tuple(struct.unpack('>I', f.read(4))[0] for d in range(dims))
        return np.fromstring(f.read(), dtype=np.uint8).reshape(shape)

def get_data(image_file, label_file, num_classes = 10):
    """
        Read the image and label data
    """
    # Read the files
    pre_images = read_idx(image_file)
    pre_labels = read_idx(label_file)
    
    images = np.zeros((len(pre_images), 28,28, 1), dtype=np.float32)
    labels = np.zeros((len(pre_labels),num_classes), dtype=np.int8)
    for i in range(len(pre_images)):
        pre_img=pre_images[i]
        pre_label=pre_labels[i]
        img = (pre_img.transpose() / 255.0)
        images[i] = img.reshape(28,28,1) 
        labels[i] = keras.utils.to_categorical(pre_label, num_classes)
    
    return images, labels

def file_len(fname):
    p = subprocess.Popen(['wc', '-l', fname], stdout=subprocess.PIPE, 
                                              stderr=subprocess.PIPE)
    result, err = p.communicate()
    if p.returncode != 0:
        raise IOError(err)
    return int(result.strip().split()[0])

In [3]:
train_mapping_file = '/home/carnd/data/emnist/emnist-mnist-mapping.txt'
num_classes = file_len(train_mapping_file)
train_image_file = '/home/carnd/data/emnist/emnist-mnist-train-images-idx3-ubyte'
train_label_file = '/home/carnd/data/emnist/emnist-mnist-train-labels-idx1-ubyte'
train_images, train_labels = get_data(train_image_file, train_label_file,num_classes)
print ('Training Data')
print ('Images Shape: {}'.format(train_images.shape))
print ('Labels Shape: {}'.format(train_labels.shape))

test_image_file = '/home/carnd/data/emnist/emnist-mnist-test-images-idx3-ubyte'
test_label_file = '/home/carnd/data/emnist/emnist-mnist-test-labels-idx1-ubyte'
test_images, test_labels = get_data(test_image_file, test_label_file,num_classes)
print ('Training Data')
print ('Images Shape: {}'.format(test_images.shape))
print ('Labels Shape: {}'.format(test_labels.shape))


Training Data
Images Shape: (60000, 28, 28, 1)
Labels Shape: (60000, 10)
Training Data
Images Shape: (10000, 28, 28, 1)
Labels Shape: (10000, 10)

In [4]:
def view_image(image, label=""):
    """View a single image."""
    print("Label - {} : {} ".format(np.argmax(label), label))
    plt.imshow((image.reshape(28,28)), cmap="gray")
    plt.show()

for i in range(2):
    view_image(train_images[i], train_labels[i])


Label - 4 : [0 0 0 0 1 0 0 0 0 0] 
Label - 1 : [0 1 0 0 0 0 0 0 0 0] 

In [5]:
# Train, Test split
from sklearn.model_selection import train_test_split
X_val, X_test, y_val, y_test = train_test_split(test_images, test_labels, test_size=0.5, random_state=42)

In [6]:
# Initialize the hyperparameters
input_shape = (28,28, 1)

In [7]:
# Build model
inputs = Input(shape=input_shape)
conv = Conv2D(32, (7, 7), strides=(1, 1), padding='same', name = "conv1", activation='relu')(inputs)
conv = AveragePooling2D((3, 3))(conv)
conv = Conv2D(64, (3, 3), strides=(1, 1), padding='same', name = "conv2", activation='relu')(conv)
conv = AveragePooling2D((2, 2))(conv)
conv = Conv2D(128, (3, 3), strides=(1, 1), padding='same', name = "conv3", activation='relu')(conv)
flat = Flatten()(conv)
dense = Dense(128, activation='relu', name = "dense2")(flat)
dropout = Dropout(0.4)(dense)
outputs = Dense(num_classes, activation='softmax', name = "output")(dropout)

model = Model(inputs=inputs, outputs=outputs)

model.summary()
model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Nadam(),
              metrics=['accuracy'])


_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 28, 28, 1)         0         
_________________________________________________________________
conv1 (Conv2D)               (None, 28, 28, 32)        1600      
_________________________________________________________________
average_pooling2d_1 (Average (None, 9, 9, 32)          0         
_________________________________________________________________
conv2 (Conv2D)               (None, 9, 9, 64)          18496     
_________________________________________________________________
average_pooling2d_2 (Average (None, 4, 4, 64)          0         
_________________________________________________________________
conv3 (Conv2D)               (None, 4, 4, 128)         73856     
_________________________________________________________________
flatten_1 (Flatten)          (None, 2048)              0         
_________________________________________________________________
dense2 (Dense)               (None, 128)               262272    
_________________________________________________________________
dropout_1 (Dropout)          (None, 128)               0         
_________________________________________________________________
output (Dense)               (None, 10)                1290      
=================================================================
Total params: 357,514
Trainable params: 357,514
Non-trainable params: 0
_________________________________________________________________

In [8]:
batch_size = 1000
epochs = 50
history = model.fit(train_images, train_labels,
          batch_size=batch_size,
          epochs=epochs,
          verbose=2,
          validation_data=(X_val, y_val))


Train on 60000 samples, validate on 5000 samples
Epoch 1/50
7s - loss: 0.7582 - acc: 0.7600 - val_loss: 0.1943 - val_acc: 0.9414
Epoch 2/50
6s - loss: 0.1585 - acc: 0.9530 - val_loss: 0.0719 - val_acc: 0.9766
Epoch 3/50
6s - loss: 0.0875 - acc: 0.9744 - val_loss: 0.0515 - val_acc: 0.9822
Epoch 4/50
6s - loss: 0.0757 - acc: 0.9775 - val_loss: 0.0425 - val_acc: 0.9862
Epoch 5/50
6s - loss: 0.0563 - acc: 0.9836 - val_loss: 0.0392 - val_acc: 0.9878
Epoch 6/50
6s - loss: 0.0457 - acc: 0.9863 - val_loss: 0.0336 - val_acc: 0.9886
Epoch 7/50
6s - loss: 0.0402 - acc: 0.9876 - val_loss: 0.0359 - val_acc: 0.9874
Epoch 8/50
6s - loss: 0.0360 - acc: 0.9889 - val_loss: 0.0330 - val_acc: 0.9896
Epoch 9/50
6s - loss: 0.0316 - acc: 0.9902 - val_loss: 0.0275 - val_acc: 0.9912
Epoch 10/50
6s - loss: 0.0280 - acc: 0.9917 - val_loss: 0.0307 - val_acc: 0.9894
Epoch 11/50
6s - loss: 0.0249 - acc: 0.9923 - val_loss: 0.0232 - val_acc: 0.9922
Epoch 12/50
6s - loss: 0.0226 - acc: 0.9931 - val_loss: 0.0222 - val_acc: 0.9924
Epoch 13/50
6s - loss: 0.0213 - acc: 0.9934 - val_loss: 0.0211 - val_acc: 0.9932
Epoch 14/50
6s - loss: 0.0183 - acc: 0.9945 - val_loss: 0.0298 - val_acc: 0.9914
Epoch 15/50
6s - loss: 0.0176 - acc: 0.9944 - val_loss: 0.0240 - val_acc: 0.9930
Epoch 16/50
6s - loss: 0.0150 - acc: 0.9953 - val_loss: 0.0232 - val_acc: 0.9940
Epoch 17/50
6s - loss: 0.0140 - acc: 0.9955 - val_loss: 0.0251 - val_acc: 0.9918
Epoch 18/50
6s - loss: 0.0143 - acc: 0.9955 - val_loss: 0.0226 - val_acc: 0.9930
Epoch 19/50
6s - loss: 0.0125 - acc: 0.9961 - val_loss: 0.0282 - val_acc: 0.9914
Epoch 20/50
6s - loss: 0.0110 - acc: 0.9968 - val_loss: 0.0237 - val_acc: 0.9928
Epoch 21/50
6s - loss: 0.0107 - acc: 0.9964 - val_loss: 0.0256 - val_acc: 0.9928
Epoch 22/50
6s - loss: 0.0086 - acc: 0.9973 - val_loss: 0.0258 - val_acc: 0.9934
Epoch 23/50
6s - loss: 0.0090 - acc: 0.9972 - val_loss: 0.0228 - val_acc: 0.9936
Epoch 24/50
6s - loss: 0.0094 - acc: 0.9969 - val_loss: 0.0241 - val_acc: 0.9940
Epoch 25/50
6s - loss: 0.0086 - acc: 0.9973 - val_loss: 0.0238 - val_acc: 0.9938
Epoch 26/50
6s - loss: 0.0084 - acc: 0.9973 - val_loss: 0.0252 - val_acc: 0.9930
Epoch 27/50
6s - loss: 0.0082 - acc: 0.9974 - val_loss: 0.0218 - val_acc: 0.9940
Epoch 28/50
6s - loss: 0.0077 - acc: 0.9975 - val_loss: 0.0208 - val_acc: 0.9946
Epoch 29/50
6s - loss: 0.0076 - acc: 0.9976 - val_loss: 0.0224 - val_acc: 0.9944
Epoch 30/50
6s - loss: 0.0070 - acc: 0.9978 - val_loss: 0.0226 - val_acc: 0.9942
Epoch 31/50
6s - loss: 0.0065 - acc: 0.9980 - val_loss: 0.0287 - val_acc: 0.9932
Epoch 32/50
6s - loss: 0.0068 - acc: 0.9978 - val_loss: 0.0258 - val_acc: 0.9936
Epoch 33/50
6s - loss: 0.0056 - acc: 0.9982 - val_loss: 0.0225 - val_acc: 0.9940
Epoch 34/50
6s - loss: 0.0060 - acc: 0.9978 - val_loss: 0.0216 - val_acc: 0.9950
Epoch 35/50
6s - loss: 0.0058 - acc: 0.9983 - val_loss: 0.0269 - val_acc: 0.9946
Epoch 36/50
6s - loss: 0.0050 - acc: 0.9984 - val_loss: 0.0260 - val_acc: 0.9942
Epoch 37/50
6s - loss: 0.0054 - acc: 0.9983 - val_loss: 0.0212 - val_acc: 0.9954
Epoch 38/50
6s - loss: 0.0057 - acc: 0.9982 - val_loss: 0.0221 - val_acc: 0.9944
Epoch 39/50
6s - loss: 0.0049 - acc: 0.9984 - val_loss: 0.0271 - val_acc: 0.9934
Epoch 40/50
6s - loss: 0.0059 - acc: 0.9979 - val_loss: 0.0273 - val_acc: 0.9930
Epoch 41/50
6s - loss: 0.0063 - acc: 0.9980 - val_loss: 0.0216 - val_acc: 0.9946
Epoch 42/50
6s - loss: 0.0044 - acc: 0.9986 - val_loss: 0.0243 - val_acc: 0.9936
Epoch 43/50
6s - loss: 0.0041 - acc: 0.9987 - val_loss: 0.0264 - val_acc: 0.9950
Epoch 44/50
6s - loss: 0.0040 - acc: 0.9989 - val_loss: 0.0252 - val_acc: 0.9952
Epoch 45/50
6s - loss: 0.0040 - acc: 0.9989 - val_loss: 0.0291 - val_acc: 0.9940
Epoch 46/50
6s - loss: 0.0052 - acc: 0.9985 - val_loss: 0.0273 - val_acc: 0.9932
Epoch 47/50
6s - loss: 0.0038 - acc: 0.9989 - val_loss: 0.0222 - val_acc: 0.9954
Epoch 48/50
6s - loss: 0.0047 - acc: 0.9987 - val_loss: 0.0324 - val_acc: 0.9936
Epoch 49/50
6s - loss: 0.0046 - acc: 0.9986 - val_loss: 0.0284 - val_acc: 0.9940
Epoch 50/50
6s - loss: 0.0048 - acc: 0.9986 - val_loss: 0.0292 - val_acc: 0.9932

In [9]:
# summarize history for accuracy
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# summarize history for loss
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()



In [10]:
score = model.evaluate(X_test, y_test, verbose=1, batch_size=batch_size)
print('Test loss:', score[0])
print('Test accuracy:', score[1])


5000/5000 [==============================] - 0s     
Test loss: 0.0279825121164
Test accuracy: 0.99279999733

In [ ]: