In [1]:
import numpy as np
np.random.seed(1337)  # for reproducibility

from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD, Adam, RMSprop
from keras.utils import np_utils

In [2]:
batch_size = 128
nb_classes = 10
nb_epoch = 20

# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()

In [3]:
print(X_train.shape, y_train.shape)


(60000, 28, 28) (60000,)

In [4]:
X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)
X_train = X_train.astype("float32")
X_test = X_test.astype("float32")
X_train /= 255
X_test /= 255
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)

model = Sequential()
model.add(Dense(128, input_dim=784))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(10))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', class_mode='categorical')

model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=2, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])


60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/20
1s - loss: 0.4320 - acc: 0.8734 - val_loss: 0.1685 - val_acc: 0.9499
Epoch 2/20
1s - loss: 0.1827 - acc: 0.9457 - val_loss: 0.1177 - val_acc: 0.9646
Epoch 3/20
1s - loss: 0.1366 - acc: 0.9585 - val_loss: 0.0923 - val_acc: 0.9713
Epoch 4/20
1s - loss: 0.1107 - acc: 0.9666 - val_loss: 0.0825 - val_acc: 0.9748
Epoch 5/20
1s - loss: 0.0951 - acc: 0.9704 - val_loss: 0.0809 - val_acc: 0.9758
Epoch 6/20
1s - loss: 0.0812 - acc: 0.9745 - val_loss: 0.0714 - val_acc: 0.9774
Epoch 7/20
1s - loss: 0.0723 - acc: 0.9772 - val_loss: 0.0706 - val_acc: 0.9775
Epoch 8/20
1s - loss: 0.0683 - acc: 0.9785 - val_loss: 0.0679 - val_acc: 0.9790
Epoch 9/20
1s - loss: 0.0601 - acc: 0.9809 - val_loss: 0.0674 - val_acc: 0.9794
Epoch 10/20
1s - loss: 0.0548 - acc: 0.9827 - val_loss: 0.0692 - val_acc: 0.9794
Epoch 11/20
1s - loss: 0.0513 - acc: 0.9831 - val_loss: 0.0668 - val_acc: 0.9797
Epoch 12/20
1s - loss: 0.0476 - acc: 0.9849 - val_loss: 0.0689 - val_acc: 0.9810
Epoch 13/20
1s - loss: 0.0455 - acc: 0.9852 - val_loss: 0.0724 - val_acc: 0.9794
Epoch 14/20
1s - loss: 0.0433 - acc: 0.9854 - val_loss: 0.0670 - val_acc: 0.9806
Epoch 15/20
1s - loss: 0.0414 - acc: 0.9860 - val_loss: 0.0644 - val_acc: 0.9820
Epoch 16/20
1s - loss: 0.0399 - acc: 0.9869 - val_loss: 0.0752 - val_acc: 0.9779
Epoch 17/20
1s - loss: 0.0375 - acc: 0.9876 - val_loss: 0.0666 - val_acc: 0.9817
Epoch 18/20
1s - loss: 0.0356 - acc: 0.9883 - val_loss: 0.0666 - val_acc: 0.9813
Epoch 19/20
1s - loss: 0.0321 - acc: 0.9889 - val_loss: 0.0735 - val_acc: 0.9798
Epoch 20/20
1s - loss: 0.0327 - acc: 0.9885 - val_loss: 0.0712 - val_acc: 0.9809
Test score: 0.0711919080993
Test accuracy: 0.9809

In [5]:
import h5py
import json
import gzip

layer_name_dict = {
    'Dense': 'denseLayer',
    'Dropout': 'dropoutLayer',
    'Flatten': 'flattenLayer',
    'Embedding': 'embeddingLayer',
    'BatchNormalization': 'batchNormalizationLayer',
    'LeakyReLU': 'leakyReLULayer',
    'PReLU': 'parametricReLULayer',
    'ParametricSoftplus': 'parametricSoftplusLayer',
    'ThresholdedLinear': 'thresholdedLinearLayer',
    'ThresholdedReLu': 'thresholdedReLuLayer',
    'LSTM': 'rLSTMLayer',
    'GRU': 'rGRULayer',
    'JZS1': 'rJZS1Layer',
    'JZS2': 'rJZS2Layer',
    'JZS3': 'rJZS3Layer',
    'Convolution2D': 'convolution2DLayer',
    'MaxPooling2D': 'maxPooling2DLayer'
}

layer_params_dict = {
    'Dense': ['weights', 'activation'],
    'Dropout': ['p'],
    'Flatten': [],
    'Embedding': ['weights'],
    'BatchNormalization': ['weights', 'epsilon'],
    'LeakyReLU': ['alpha'],
    'PReLU': ['weights'],
    'ParametricSoftplus': ['weights'],
    'ThresholdedLinear': ['theta'],
    'ThresholdedReLu': ['theta'],
    'LSTM': ['weights', 'activation', 'inner_activation', 'return_sequences'],
    'GRU': ['weights', 'activation', 'inner_activation', 'return_sequences'],
    'JZS1': ['weights', 'activation', 'inner_activation', 'return_sequences'],
    'JZS2': ['weights', 'activation', 'inner_activation', 'return_sequences'],
    'JZS3': ['weights', 'activation', 'inner_activation', 'return_sequences'],
    'Convolution2D': ['weights', 'nb_filter', 'nb_row', 'nb_col', 'border_mode', 'subsample', 'activation'],
    'MaxPooling2D': ['pool_size', 'stride', 'ignore_border']
}

layer_weights_dict = {
    'Dense': ['W', 'b'],
    'Embedding': ['E'],
    'BatchNormalization': ['gamma', 'beta', 'mean', 'std'],
    'PReLU': ['alphas'],
    'ParametricSoftplus': ['alphas', 'betas'],
    'LSTM': ['W_xi', 'W_hi', 'b_i', 'W_xc', 'W_hc', 'b_c', 'W_xf', 'W_hf', 'b_f', 'W_xo', 'W_ho', 'b_o'],
    'GRU': ['W_xz', 'W_hz', 'b_z', 'W_xr', 'W_hr', 'b_r', 'W_xh', 'W_hh', 'b_h'],
    'JZS1': ['W_xz', 'b_z', 'W_xr', 'W_hr', 'b_r', 'W_hh', 'b_h', 'Pmat'],
    'JZS2': ['W_xz', 'W_hz', 'b_z', 'W_hr', 'b_r', 'W_xh', 'W_hh', 'b_h', 'Pmat'],
    'JZS3': ['W_xz', 'W_hz', 'b_z', 'W_xr', 'W_hr', 'b_r', 'W_xh', 'W_hh', 'b_h'],
    'Convolution2D': ['W', 'b']
}

def serialize(model_json_file, weights_hdf5_file, save_filepath, compress):
    with open(model_json_file, 'r') as f:
        model_metadata = json.load(f)
    weights_file = h5py.File(weights_hdf5_file, 'r')

    layers = []

    num_activation_layers = 0
    for k, layer in enumerate(model_metadata['layers']):
        if layer['name'] == 'Activation':
            num_activation_layers += 1
            prev_layer_name = model_metadata['layers'][k-1]['name']
            idx_activation = layer_params_dict[prev_layer_name].index('activation')
            layers[k-num_activation_layers]['parameters'][idx_activation] = layer['activation']
            continue

        layer_params = []

        for param in layer_params_dict[layer['name']]:
            if param == 'weights':
                layer_weights = list(weights_file.get('layer_{}'.format(k)))
                weights = {}
                weight_names = layer_weights_dict[layer['name']]
                for name, w in zip(weight_names, layer_weights):
                    weights[name] = weights_file.get('layer_{}/{}'.format(k, w)).value.tolist()
                layer_params.append(weights)
            else:
                layer_params.append(layer[param])

        layers.append({
            'layerName': layer_name_dict[layer['name']],
            'parameters': layer_params
        })

    if compress:
        with gzip.open(save_filepath, 'wb') as f:
            f.write(json.dumps(layers).encode('utf8'))
    else:
        with open(save_filepath, 'w') as f:
            json.dump(layers, f)

In [6]:
import json
model_metadata = json.loads(model.to_json())

with open('mnist_mlp_keras_model.json', 'w') as f:
    json.dump(model_metadata, f)

In [7]:
model_metadata


Out[7]:
{'class_mode': 'categorical',
 'layers': [{'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'init': 'glorot_uniform',
   'input_dim': 784,
   'input_shape': [784],
   'name': 'Dense',
   'output_dim': 128},
  {'activation': 'relu', 'beta': 0.1, 'name': 'Activation', 'target': 0},
  {'name': 'Dropout', 'p': 0.2},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'init': 'glorot_uniform',
   'input_dim': None,
   'name': 'Dense',
   'output_dim': 128},
  {'activation': 'relu', 'beta': 0.1, 'name': 'Activation', 'target': 0},
  {'name': 'Dropout', 'p': 0.2},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'init': 'glorot_uniform',
   'input_dim': None,
   'name': 'Dense',
   'output_dim': 10},
  {'activation': 'softmax', 'beta': 0.1, 'name': 'Activation', 'target': 0}],
 'loss': 'categorical_crossentropy',
 'name': 'Sequential',
 'optimizer': {'beta_1': 0.9,
  'beta_2': 0.999,
  'epsilon': 1e-08,
  'lr': 0.0010000000474974513,
  'name': 'Adam'},
 'theano_mode': None}

In [8]:
model.save_weights('mnist_mlp_keras_weights.hdf5')


[WARNING] mnist_mlp_keras_weights.hdf5 already exists - overwrite? [y/n]y
[TIP] Next time specify overwrite=True in save_weights!

In [9]:
serialize('mnist_mlp_keras_model.json', 
          'mnist_mlp_keras_weights.hdf5', 
          'mnist_mlp_model_params.json.gz', 
          True)
serialize('mnist_mlp_keras_model.json', 
          'mnist_mlp_keras_weights.hdf5', 
          'mnist_mlp_model_params.json', 
          False)

In [12]:
randidx = np.random.randint(0, X_test.shape[0], size=2000)
X_rand = X_test[randidx, :]
y_rand = y_test[randidx]

with gzip.open('sample_data.json.gz', 'wb') as f:
    f.write(json.dumps({'data': X_rand.tolist(), 'labels': y_rand.tolist()}).encode('utf8'))
with open('sample_data.json', 'w') as f:
    json.dump({'data': X_rand.tolist(), 'labels': y_rand.tolist()}, f)

In [11]:
model.predict(X_rand[0:1,:])


Out[11]:
array([[  9.99999642e-01,   1.93592386e-12,   3.22102466e-07,
          5.10120501e-10,   8.43486322e-11,   1.41102746e-11,
          1.82862205e-08,   8.58895177e-10,   3.75560418e-08,
          2.18974616e-09]])

In [ ]: