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 = 47

train_image_file = '/home/carnd/data/emnist/emnist-bymerge-train-images-idx3-ubyte'
train_label_file = '/home/carnd/data/emnist/emnist-bymerge-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-bymerge-test-images-idx3-ubyte'
test_label_file = '/home/carnd/data/emnist/emnist-bymerge-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: (697932, 28, 28, 1)
Labels Shape: (697932, 47)
Training Data
Images Shape: (116323, 28, 28, 1)
Labels Shape: (116323, 47)

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 - 24 : [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0] 
Label - 36 : [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
 0 0 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 [ ]:
# Build model
inputs = Input(shape=input_shape)

tower_1 = Conv2D(32, (3, 3), strides=(1, 1), padding='same', name = "inc1_conv1", activation='relu')(inputs)
tower_2 = Conv2D(32, (5, 5), strides=(1, 1), padding='same', name = "inc1_conv2", activation='relu')(inputs)
tower_3 = Conv2D(32, (7, 7), strides=(1, 1), padding='same', name = "inc1_conv3", activation='relu')(inputs)
tower_4 = Conv2D(32, (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(16, (3, 3), strides=(1, 1), padding='same', name = "inc2_conv1", activation='relu')(reduce)

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

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

tower_4 = Conv2D(16, (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, 32)    320         input_1[0][0]                    
____________________________________________________________________________________________________
inc1_conv2 (Conv2D)              (None, 28, 28, 32)    832         input_1[0][0]                    
____________________________________________________________________________________________________
inc1_conv3 (Conv2D)              (None, 28, 28, 32)    1600        input_1[0][0]                    
____________________________________________________________________________________________________
inc1_conv4 (Conv2D)              (None, 28, 28, 32)    2624        input_1[0][0]                    
____________________________________________________________________________________________________
inc1_concat (Concatenate)        (None, 28, 28, 128)   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)    2064        inc1_concat[0][0]                
____________________________________________________________________________________________________
inc2_conv1 (Conv2D)              (None, 28, 28, 16)    2320        inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_conv2 (Conv2D)              (None, 28, 28, 16)    6416        inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_conv3 (Conv2D)              (None, 28, 28, 16)    12560       inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_conv4 (Conv2D)              (None, 28, 28, 16)    20752       inc2_1by1_1[0][0]                
____________________________________________________________________________________________________
inc2_concat (Concatenate)        (None, 28, 28, 64)    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)    1040        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, 47)            6063        dropout_1[0][0]                  
====================================================================================================
Total params: 1,662,351
Trainable params: 1,662,351
Non-trainable params: 0
____________________________________________________________________________________________________

In [ ]:
batch_size = 500
epochs = 10
history = model.fit(train_images, train_labels,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(X_val, y_val))


Train on 697932 samples, validate on 58161 samples
Epoch 1/10
697932/697932 [==============================] - 634s - loss: 0.5072 - acc: 0.8370 - val_loss: 0.3128 - val_acc: 0.8878
Epoch 2/10
697932/697932 [==============================] - 630s - loss: 0.3487 - acc: 0.8788 - val_loss: 0.2891 - val_acc: 0.8956
Epoch 3/10
291500/697932 [===========>..................] - ETA: 359s - loss: 0.3248 - acc: 0.8854

In [ ]:
# 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 [ ]:
score = model.evaluate(X_test, y_test, verbose=1, batch_size=batch_size)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

In [ ]: