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, starts_at=0 ):
    """
        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]-starts_at
        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-letters-mapping.txt'
num_classes = file_len(train_mapping_file)
train_image_file = '/home/carnd/data/emnist/emnist-letters-train-images-idx3-ubyte'
train_label_file = '/home/carnd/data/emnist/emnist-letters-train-labels-idx1-ubyte'
train_images, train_labels = get_data(train_image_file, train_label_file,num_classes, 1)
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-letters-test-images-idx3-ubyte'
test_label_file = '/home/carnd/data/emnist/emnist-letters-test-labels-idx1-ubyte'
test_images, test_labels = get_data(test_image_file, test_label_file,num_classes,1)
print ('Training Data')
print ('Images Shape: {}'.format(test_images.shape))
print ('Labels Shape: {}'.format(test_labels.shape))


Training Data
Images Shape: (124800, 28, 28, 1)
Labels Shape: (124800, 26)
Training Data
Images Shape: (20800, 28, 28, 1)
Labels Shape: (20800, 26)

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 - 22 : [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] 
Label - 6 : [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] 

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 = Dropout(0.4)(conv)
conv = MaxPooling2D((2, 2))(conv)
conv = Conv2D(64, (5, 5), strides=(1, 1), padding='same', name = "conv2", activation='relu')(conv)
conv = Dropout(0.4)(conv)
conv = MaxPooling2D((2, 2))(conv)
conv = Conv2D(128, (3, 3), strides=(1, 1), padding='same', name = "conv3", activation='relu')(conv)
conv = Dropout(0.4)(conv)
conv = MaxPooling2D((2, 2))(conv)
conv = Conv2D(256, (3, 3), strides=(1, 1), padding='same', name = "conv4", 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      
_________________________________________________________________
dropout_1 (Dropout)          (None, 28, 28, 32)        0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
conv2 (Conv2D)               (None, 14, 14, 64)        51264     
_________________________________________________________________
dropout_2 (Dropout)          (None, 14, 14, 64)        0         
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 7, 7, 64)          0         
_________________________________________________________________
conv3 (Conv2D)               (None, 7, 7, 128)         73856     
_________________________________________________________________
dropout_3 (Dropout)          (None, 7, 7, 128)         0         
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 3, 3, 128)         0         
_________________________________________________________________
conv4 (Conv2D)               (None, 3, 3, 256)         295168    
_________________________________________________________________
flatten_1 (Flatten)          (None, 2304)              0         
_________________________________________________________________
dense2 (Dense)               (None, 128)               295040    
_________________________________________________________________
dropout_4 (Dropout)          (None, 128)               0         
_________________________________________________________________
output (Dense)               (None, 26)                3354      
=================================================================
Total params: 720,282
Trainable params: 720,282
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 124800 samples, validate on 10400 samples
Epoch 1/50
44s - loss: 1.2092 - acc: 0.6442 - val_loss: 0.6036 - val_acc: 0.9132
Epoch 2/50
37s - loss: 0.2971 - acc: 0.9053 - val_loss: 0.4143 - val_acc: 0.9298
Epoch 3/50
37s - loss: 0.2299 - acc: 0.9254 - val_loss: 0.3745 - val_acc: 0.9367
Epoch 4/50
37s - loss: 0.1978 - acc: 0.9352 - val_loss: 0.3250 - val_acc: 0.9411
Epoch 5/50
37s - loss: 0.1836 - acc: 0.9387 - val_loss: 0.3003 - val_acc: 0.9423
Epoch 6/50
37s - loss: 0.1718 - acc: 0.9420 - val_loss: 0.2841 - val_acc: 0.9419
Epoch 7/50
37s - loss: 0.1636 - acc: 0.9439 - val_loss: 0.2571 - val_acc: 0.9453
Epoch 8/50
37s - loss: 0.1557 - acc: 0.9461 - val_loss: 0.2640 - val_acc: 0.9448
Epoch 9/50
37s - loss: 0.1484 - acc: 0.9482 - val_loss: 0.2457 - val_acc: 0.9494
Epoch 10/50
37s - loss: 0.1466 - acc: 0.9490 - val_loss: 0.2487 - val_acc: 0.9444
Epoch 11/50
37s - loss: 0.1391 - acc: 0.9504 - val_loss: 0.2383 - val_acc: 0.9488
Epoch 12/50
37s - loss: 0.1380 - acc: 0.9503 - val_loss: 0.2434 - val_acc: 0.9470
Epoch 13/50
37s - loss: 0.1338 - acc: 0.9515 - val_loss: 0.2211 - val_acc: 0.9465
Epoch 14/50
37s - loss: 0.1304 - acc: 0.9528 - val_loss: 0.1906 - val_acc: 0.9458
Epoch 15/50
37s - loss: 0.1284 - acc: 0.9528 - val_loss: 0.2160 - val_acc: 0.9489
Epoch 16/50
37s - loss: 0.1258 - acc: 0.9539 - val_loss: 0.1768 - val_acc: 0.9495
Epoch 17/50
37s - loss: 0.1251 - acc: 0.9545 - val_loss: 0.1937 - val_acc: 0.9450
Epoch 18/50
37s - loss: 0.1215 - acc: 0.9551 - val_loss: 0.2209 - val_acc: 0.9463
Epoch 19/50
37s - loss: 0.1205 - acc: 0.9554 - val_loss: 0.1893 - val_acc: 0.9483
Epoch 20/50
37s - loss: 0.1188 - acc: 0.9558 - val_loss: 0.1924 - val_acc: 0.9438
Epoch 21/50
37s - loss: 0.1182 - acc: 0.9565 - val_loss: 0.1789 - val_acc: 0.9476
Epoch 22/50
37s - loss: 0.1174 - acc: 0.9563 - val_loss: 0.1967 - val_acc: 0.9465
Epoch 23/50
37s - loss: 0.1160 - acc: 0.9565 - val_loss: 0.1753 - val_acc: 0.9496
Epoch 24/50
37s - loss: 0.1118 - acc: 0.9578 - val_loss: 0.1754 - val_acc: 0.9488
Epoch 25/50
37s - loss: 0.1118 - acc: 0.9579 - val_loss: 0.1790 - val_acc: 0.9484
Epoch 26/50
37s - loss: 0.1120 - acc: 0.9576 - val_loss: 0.1664 - val_acc: 0.9478
Epoch 27/50
37s - loss: 0.1098 - acc: 0.9581 - val_loss: 0.1705 - val_acc: 0.9484
Epoch 28/50
37s - loss: 0.1087 - acc: 0.9592 - val_loss: 0.1682 - val_acc: 0.9485
Epoch 29/50
37s - loss: 0.1094 - acc: 0.9577 - val_loss: 0.1646 - val_acc: 0.9469
Epoch 30/50
37s - loss: 0.1096 - acc: 0.9581 - val_loss: 0.1676 - val_acc: 0.9478
Epoch 31/50
37s - loss: 0.1067 - acc: 0.9595 - val_loss: 0.1620 - val_acc: 0.9465
Epoch 32/50
37s - loss: 0.1056 - acc: 0.9589 - val_loss: 0.1596 - val_acc: 0.9489
Epoch 33/50
37s - loss: 0.1055 - acc: 0.9593 - val_loss: 0.1625 - val_acc: 0.9500
Epoch 34/50
37s - loss: 0.1057 - acc: 0.9592 - val_loss: 0.1559 - val_acc: 0.9465
Epoch 35/50
37s - loss: 0.1029 - acc: 0.9593 - val_loss: 0.1532 - val_acc: 0.9492
Epoch 36/50
37s - loss: 0.1057 - acc: 0.9593 - val_loss: 0.1565 - val_acc: 0.9484
Epoch 37/50
37s - loss: 0.1052 - acc: 0.9594 - val_loss: 0.1548 - val_acc: 0.9495
Epoch 38/50
37s - loss: 0.1026 - acc: 0.9603 - val_loss: 0.1611 - val_acc: 0.9482
Epoch 39/50
37s - loss: 0.1024 - acc: 0.9606 - val_loss: 0.1584 - val_acc: 0.9496
Epoch 40/50
37s - loss: 0.1018 - acc: 0.9608 - val_loss: 0.1564 - val_acc: 0.9499
Epoch 41/50
37s - loss: 0.1033 - acc: 0.9603 - val_loss: 0.1532 - val_acc: 0.9509
Epoch 42/50
37s - loss: 0.1002 - acc: 0.9613 - val_loss: 0.1549 - val_acc: 0.9508
Epoch 43/50
37s - loss: 0.1009 - acc: 0.9608 - val_loss: 0.1552 - val_acc: 0.9514
Epoch 44/50
37s - loss: 0.1021 - acc: 0.9608 - val_loss: 0.1547 - val_acc: 0.9481
Epoch 45/50
37s - loss: 0.0993 - acc: 0.9608 - val_loss: 0.1502 - val_acc: 0.9511
Epoch 46/50
37s - loss: 0.0974 - acc: 0.9620 - val_loss: 0.1539 - val_acc: 0.9496
Epoch 47/50
37s - loss: 0.0976 - acc: 0.9615 - val_loss: 0.1571 - val_acc: 0.9469
Epoch 48/50
37s - loss: 0.0983 - acc: 0.9619 - val_loss: 0.1559 - val_acc: 0.9489
Epoch 49/50
37s - loss: 0.0980 - acc: 0.9614 - val_loss: 0.1531 - val_acc: 0.9501
Epoch 50/50
37s - loss: 0.0973 - acc: 0.9614 - val_loss: 0.1541 - val_acc: 0.9485

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])


10000/10400 [===========================>..] - ETA: 0sTest loss: 0.159593482144
Test accuracy: 0.94798081884

In [ ]: