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

#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

In [3]:
num_classes = 10

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)

tower_1 = Conv2D(16, (3, 3), strides=(1, 1), padding='same', name = "inc1_conv1", activation='relu')(inputs)
tower_2 = Conv2D(16, (5, 5), strides=(1, 1), padding='same', name = "inc1_conv2", activation='relu')(inputs)
tower_3 = Conv2D(16, (7, 7), strides=(1, 1), padding='same', name = "inc1_conv3", activation='relu')(inputs)
tower_4 = Conv2D(16, (9, 9), strides=(1, 1), padding='same', name = "inc1_conv4", activation='relu')(inputs)
concat_1 = keras.layers.concatenate([tower_1, tower_2, tower_3, tower_4], axis=3, name = "inc1_concat")

reduce = Conv2D(16, (1, 1), strides=(1, 1), padding='same', name = "inc2_1by1_1")(concat_1)
tower_1 = Conv2D(32, (3, 3), strides=(1, 1), padding='same', name = "inc2_conv1", activation='relu')(reduce)

tower_2 = Conv2D(32, (5, 5), strides=(1, 1), padding='same', name = "inc2_conv2", activation='relu')(reduce)

tower_3 = Conv2D(32, (7, 7), strides=(1, 1), padding='same', name = "inc2_conv3", activation='relu')(reduce)

tower_4 = Conv2D(32, (9, 9), strides=(1, 1), padding='same', name = "inc2_conv4", activation='relu')(reduce)

concat_2 = keras.layers.concatenate([tower_1, tower_2, tower_3, tower_4], axis=3, name = "inc2_concat")
concat_2 = Conv2D(16, (1, 1), strides=(1, 1), padding='same', activation='relu', name = "conc_1x1_1")(concat_2)

flat = Flatten()(concat_2)
dense = Dense(128, activation='relu', name = "dense1")(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 #     Connected to                     
====================================================================================================
input_1 (InputLayer)             (None, 28, 28, 1)     0                                            
____________________________________________________________________________________________________
inc1_conv1 (Conv2D)              (None, 28, 28, 16)    160         input_1[0][0]                    
____________________________________________________________________________________________________
inc1_conv2 (Conv2D)              (None, 28, 28, 16)    416         input_1[0][0]                    
____________________________________________________________________________________________________
inc1_conv3 (Conv2D)              (None, 28, 28, 16)    800         input_1[0][0]                    
____________________________________________________________________________________________________
inc1_conv4 (Conv2D)              (None, 28, 28, 16)    1312        input_1[0][0]                    
____________________________________________________________________________________________________
inc1_concat (Concatenate)        (None, 28, 28, 64)    0           inc1_conv1[0][0]                 
                                                                   inc1_conv2[0][0]                 
                                                                   inc1_conv3[0][0]                 
                                                                   inc1_conv4[0][0]                 
____________________________________________________________________________________________________
inc2_1by1_1 (Conv2D)             (None, 28, 28, 16)    1040        inc1_concat[0][0]                
____________________________________________________________________________________________________
inc2_conv1 (Conv2D)              (None, 28, 28, 32)    4640        inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_conv2 (Conv2D)              (None, 28, 28, 32)    12832       inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_conv3 (Conv2D)              (None, 28, 28, 32)    25120       inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_conv4 (Conv2D)              (None, 28, 28, 32)    41504       inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_concat (Concatenate)        (None, 28, 28, 128)   0           inc2_conv1[0][0]                 
                                                                   inc2_conv2[0][0]                 
                                                                   inc2_conv3[0][0]                 
                                                                   inc2_conv4[0][0]                 
____________________________________________________________________________________________________
conc_1x1_1 (Conv2D)              (None, 28, 28, 16)    2064        inc2_concat[0][0]                
____________________________________________________________________________________________________
flatten_1 (Flatten)              (None, 12544)         0           conc_1x1_1[0][0]                 
____________________________________________________________________________________________________
dense1 (Dense)                   (None, 128)           1605760     flatten_1[0][0]                  
____________________________________________________________________________________________________
dropout_1 (Dropout)              (None, 128)           0           dense1[0][0]                     
____________________________________________________________________________________________________
output (Dense)                   (None, 10)            1290        dropout_1[0][0]                  
====================================================================================================
Total params: 1,696,938
Trainable params: 1,696,938
Non-trainable params: 0
____________________________________________________________________________________________________

In [8]:
batch_size = 250
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
68s - loss: 0.2059 - acc: 0.9357 - val_loss: 0.0440 - val_acc: 0.9854
Epoch 2/50
66s - loss: 0.0517 - acc: 0.9849 - val_loss: 0.0343 - val_acc: 0.9890
Epoch 3/50
66s - loss: 0.0382 - acc: 0.9886 - val_loss: 0.0275 - val_acc: 0.9916
Epoch 4/50
66s - loss: 0.0296 - acc: 0.9913 - val_loss: 0.0293 - val_acc: 0.9922
Epoch 5/50
66s - loss: 0.0262 - acc: 0.9920 - val_loss: 0.0268 - val_acc: 0.9920
Epoch 6/50
66s - loss: 0.0226 - acc: 0.9931 - val_loss: 0.0275 - val_acc: 0.9928
Epoch 7/50
66s - loss: 0.0191 - acc: 0.9945 - val_loss: 0.0365 - val_acc: 0.9892
Epoch 8/50
66s - loss: 0.0174 - acc: 0.9945 - val_loss: 0.0310 - val_acc: 0.9932
Epoch 9/50
66s - loss: 0.0153 - acc: 0.9951 - val_loss: 0.0273 - val_acc: 0.9936
Epoch 10/50
66s - loss: 0.0157 - acc: 0.9950 - val_loss: 0.0360 - val_acc: 0.9922
Epoch 11/50
66s - loss: 0.0166 - acc: 0.9950 - val_loss: 0.0319 - val_acc: 0.9920
Epoch 12/50
66s - loss: 0.0149 - acc: 0.9954 - val_loss: 0.0257 - val_acc: 0.9944
Epoch 13/50
66s - loss: 0.0138 - acc: 0.9958 - val_loss: 0.0203 - val_acc: 0.9948
Epoch 14/50
66s - loss: 0.0107 - acc: 0.9967 - val_loss: 0.0395 - val_acc: 0.9922
Epoch 15/50
66s - loss: 0.0127 - acc: 0.9958 - val_loss: 0.0360 - val_acc: 0.9920
Epoch 16/50
66s - loss: 0.0112 - acc: 0.9968 - val_loss: 0.0391 - val_acc: 0.9918
Epoch 17/50
66s - loss: 0.0116 - acc: 0.9967 - val_loss: 0.0391 - val_acc: 0.9928
Epoch 18/50
66s - loss: 0.0100 - acc: 0.9972 - val_loss: 0.0429 - val_acc: 0.9928
Epoch 19/50
66s - loss: 0.0110 - acc: 0.9968 - val_loss: 0.0428 - val_acc: 0.9922
Epoch 20/50
66s - loss: 0.0116 - acc: 0.9964 - val_loss: 0.0357 - val_acc: 0.9938
Epoch 21/50
66s - loss: 0.0097 - acc: 0.9971 - val_loss: 0.0317 - val_acc: 0.9934
Epoch 22/50
66s - loss: 0.0089 - acc: 0.9973 - val_loss: 0.0487 - val_acc: 0.9906
Epoch 23/50
66s - loss: 0.0096 - acc: 0.9971 - val_loss: 0.0424 - val_acc: 0.9916
Epoch 24/50
66s - loss: 0.0087 - acc: 0.9973 - val_loss: 0.0386 - val_acc: 0.9922
Epoch 25/50
66s - loss: 0.0087 - acc: 0.9971 - val_loss: 0.0417 - val_acc: 0.9926
Epoch 26/50
66s - loss: 0.0114 - acc: 0.9969 - val_loss: 0.0439 - val_acc: 0.9926
Epoch 27/50
66s - loss: 0.0092 - acc: 0.9973 - val_loss: 0.0378 - val_acc: 0.9930
Epoch 28/50
66s - loss: 0.0071 - acc: 0.9979 - val_loss: 0.0541 - val_acc: 0.9924
Epoch 29/50
66s - loss: 0.0081 - acc: 0.9974 - val_loss: 0.0433 - val_acc: 0.9930
Epoch 30/50
66s - loss: 0.0089 - acc: 0.9973 - val_loss: 0.0413 - val_acc: 0.9934
Epoch 31/50
66s - loss: 0.0090 - acc: 0.9973 - val_loss: 0.0294 - val_acc: 0.9936
Epoch 32/50
66s - loss: 0.0079 - acc: 0.9981 - val_loss: 0.0444 - val_acc: 0.9914
Epoch 33/50
66s - loss: 0.0083 - acc: 0.9978 - val_loss: 0.0481 - val_acc: 0.9920
Epoch 34/50
66s - loss: 0.0076 - acc: 0.9977 - val_loss: 0.0468 - val_acc: 0.9930
Epoch 35/50
66s - loss: 0.0081 - acc: 0.9979 - val_loss: 0.0581 - val_acc: 0.9904
Epoch 36/50
66s - loss: 0.0091 - acc: 0.9975 - val_loss: 0.0405 - val_acc: 0.9922
Epoch 37/50
66s - loss: 0.0076 - acc: 0.9977 - val_loss: 0.0517 - val_acc: 0.9926
Epoch 38/50
66s - loss: 0.0065 - acc: 0.9982 - val_loss: 0.0457 - val_acc: 0.9926
Epoch 39/50
66s - loss: 0.0075 - acc: 0.9977 - val_loss: 0.0584 - val_acc: 0.9918
Epoch 40/50
66s - loss: 0.0084 - acc: 0.9979 - val_loss: 0.0533 - val_acc: 0.9916
Epoch 41/50
66s - loss: 0.0088 - acc: 0.9976 - val_loss: 0.0479 - val_acc: 0.9918
Epoch 42/50
66s - loss: 0.0061 - acc: 0.9982 - val_loss: 0.0592 - val_acc: 0.9922
Epoch 43/50
66s - loss: 0.0092 - acc: 0.9977 - val_loss: 0.0468 - val_acc: 0.9922
Epoch 44/50
66s - loss: 0.0059 - acc: 0.9984 - val_loss: 0.0460 - val_acc: 0.9934
Epoch 45/50
66s - loss: 0.0076 - acc: 0.9978 - val_loss: 0.0473 - val_acc: 0.9922
Epoch 46/50
66s - loss: 0.0059 - acc: 0.9984 - val_loss: 0.0520 - val_acc: 0.9924
Epoch 47/50
66s - loss: 0.0079 - acc: 0.9981 - val_loss: 0.0644 - val_acc: 0.9922
Epoch 48/50
66s - loss: 0.0074 - acc: 0.9982 - val_loss: 0.0643 - val_acc: 0.9916
Epoch 49/50
66s - loss: 0.0067 - acc: 0.9982 - val_loss: 0.0543 - val_acc: 0.9922
Epoch 50/50
66s - loss: 0.0064 - acc: 0.9982 - val_loss: 0.0612 - val_acc: 0.9920

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 [==============================] - 1s     
Test loss: 0.0391118680062
Test accuracy: 0.993000084162

In [ ]: