In [1]:
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.layers.advanced_activations import LeakyReLU, PReLU, ParametricSoftplus
from keras.utils import np_utils, generic_utils
from keras.callbacks import ModelCheckpoint, EarlyStopping


Using gpu device 3: Tesla K80 (CNMeM is disabled)

In [2]:
import numpy as np

In [3]:
batch_size = 64
nb_classes = 10
nb_epoch = 100

img_channels = 3
img_rows = 32
img_cols = 32

# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')


X_train shape: (50000, 3, 32, 32)
50000 train samples
10000 test samples

In [4]:
datagen = ImageDataGenerator(
    featurewise_center=False,
    samplewise_center=False,
    featurewise_std_normalization=False,
    samplewise_std_normalization=False,
    zca_whitening=False,
    rotation_range=None,
    width_shift_range=None,
    height_shift_range=None,
    horizontal_flip=True,
    vertical_flip=False)

batch = 0
for X_batch, y_batch in datagen.flow(X_train, y_train, batch_size=2048):
    print(batch, end='...', flush=True)
    X_train = np.vstack((X_train, X_batch))
    y_train = np.vstack((y_train, y_batch))
    batch += 1
    
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')


0...1...2...3...4...5...6...7...8...9...10...11...12...13...14...15...16...17...18...19...20...21...22...23...24...X_train shape: (100000, 3, 32, 32)
100000 train samples
10000 test samples

In [5]:
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
print('Y_train shape:', Y_train.shape)
print('Y_test shape:', Y_test.shape)


Y_train shape: (100000, 10)
Y_test shape: (10000, 10)

In [6]:
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255

In [7]:
model = Sequential()

model.add(Convolution2D(32, 3, 3, border_mode='full',
                        input_shape=(img_channels, img_rows, img_cols)))
model.add(LeakyReLU(alpha=0.2))
model.add(Convolution2D(32, 3, 3))
model.add(LeakyReLU(alpha=0.2))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))

model.add(Convolution2D(64, 3, 3, border_mode='full'))
model.add(LeakyReLU(alpha=0.2))
model.add(Convolution2D(64, 3, 3))
model.add(LeakyReLU(alpha=0.2))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.3))

model.add(Convolution2D(128, 3, 3, border_mode='full'))
model.add(LeakyReLU(alpha=0.2))
model.add(Convolution2D(128, 3, 3))
model.add(LeakyReLU(alpha=0.2))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.4))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(nb_classes))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', class_mode='categorical')
    
checkpointer = ModelCheckpoint(filepath='cifar10_cnn_keras_weights.hdf5', verbose=1, save_best_only=True)
earlystopping = EarlyStopping(monitor='val_loss', patience=10, verbose=1)

model.fit(X_train, Y_train, 
          batch_size=batch_size, 
          nb_epoch=nb_epoch, 
          show_accuracy=True,
          validation_data=(X_test, Y_test),
          callbacks=[checkpointer, earlystopping])


Train on 100000 samples, validate on 10000 samples
Epoch 1/100
100000/100000 [==============================] - 55s - loss: 1.2535 - acc: 0.5512 - val_loss: 0.7868 - val_acc: 0.7219
Epoch 00000: val_loss improved from inf to 0.78679, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 2/100
100000/100000 [==============================] - 54s - loss: 0.8126 - acc: 0.7169 - val_loss: 0.6505 - val_acc: 0.7741
Epoch 00001: val_loss improved from 0.78679 to 0.65051, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 3/100
100000/100000 [==============================] - 54s - loss: 0.6964 - acc: 0.7586 - val_loss: 0.5674 - val_acc: 0.8044
Epoch 00002: val_loss improved from 0.65051 to 0.56742, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 4/100
100000/100000 [==============================] - 54s - loss: 0.6299 - acc: 0.7814 - val_loss: 0.5577 - val_acc: 0.8079
Epoch 00003: val_loss improved from 0.56742 to 0.55768, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 5/100
100000/100000 [==============================] - 54s - loss: 0.5878 - acc: 0.7951 - val_loss: 0.5649 - val_acc: 0.8123
Epoch 00004: val_loss did not improve
Epoch 6/100
100000/100000 [==============================] - 54s - loss: 0.5578 - acc: 0.8086 - val_loss: 0.5003 - val_acc: 0.8311
Epoch 00005: val_loss improved from 0.55768 to 0.50028, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 7/100
100000/100000 [==============================] - 54s - loss: 0.5376 - acc: 0.8139 - val_loss: 0.4991 - val_acc: 0.8314
Epoch 00006: val_loss improved from 0.50028 to 0.49913, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 8/100
100000/100000 [==============================] - 54s - loss: 0.5176 - acc: 0.8216 - val_loss: 0.5188 - val_acc: 0.8231
Epoch 00007: val_loss did not improve
Epoch 9/100
100000/100000 [==============================] - 54s - loss: 0.5003 - acc: 0.8261 - val_loss: 0.5392 - val_acc: 0.8173
Epoch 00008: val_loss did not improve
Epoch 10/100
100000/100000 [==============================] - 54s - loss: 0.4860 - acc: 0.8317 - val_loss: 0.4797 - val_acc: 0.8392
Epoch 00009: val_loss improved from 0.49913 to 0.47974, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 11/100
100000/100000 [==============================] - 54s - loss: 0.4818 - acc: 0.8335 - val_loss: 0.4676 - val_acc: 0.8412
Epoch 00010: val_loss improved from 0.47974 to 0.46760, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 12/100
100000/100000 [==============================] - 54s - loss: 0.4688 - acc: 0.8383 - val_loss: 0.4626 - val_acc: 0.8440
Epoch 00011: val_loss improved from 0.46760 to 0.46257, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 13/100
100000/100000 [==============================] - 54s - loss: 0.4578 - acc: 0.8433 - val_loss: 0.4951 - val_acc: 0.8412
Epoch 00012: val_loss did not improve
Epoch 14/100
100000/100000 [==============================] - 54s - loss: 0.4540 - acc: 0.8444 - val_loss: 0.4660 - val_acc: 0.8503
Epoch 00013: val_loss did not improve
Epoch 15/100
100000/100000 [==============================] - 54s - loss: 0.4486 - acc: 0.8467 - val_loss: 0.4894 - val_acc: 0.8407
Epoch 00014: val_loss did not improve
Epoch 16/100
100000/100000 [==============================] - 54s - loss: 0.4379 - acc: 0.8497 - val_loss: 0.4476 - val_acc: 0.8486
Epoch 00015: val_loss improved from 0.46257 to 0.44760, saving model to cifar10_cnn_keras_weights.hdf5
Epoch 17/100
100000/100000 [==============================] - 54s - loss: 0.4333 - acc: 0.8515 - val_loss: 0.4832 - val_acc: 0.8516
Epoch 00016: val_loss did not improve
Epoch 18/100
100000/100000 [==============================] - 54s - loss: 0.4276 - acc: 0.8529 - val_loss: 0.4804 - val_acc: 0.8502
Epoch 00017: val_loss did not improve
Epoch 19/100
100000/100000 [==============================] - 54s - loss: 0.4289 - acc: 0.8531 - val_loss: 0.4509 - val_acc: 0.8566
Epoch 00018: val_loss did not improve
Epoch 20/100
100000/100000 [==============================] - 54s - loss: 0.4229 - acc: 0.8565 - val_loss: 0.4490 - val_acc: 0.8563
Epoch 00019: val_loss did not improve
Epoch 21/100
100000/100000 [==============================] - 54s - loss: 0.4180 - acc: 0.8562 - val_loss: 0.4726 - val_acc: 0.8502
Epoch 00020: val_loss did not improve
Epoch 22/100
100000/100000 [==============================] - 54s - loss: 0.4151 - acc: 0.8590 - val_loss: 0.4749 - val_acc: 0.8468
Epoch 00021: val_loss did not improve
Epoch 23/100
100000/100000 [==============================] - 54s - loss: 0.4109 - acc: 0.8596 - val_loss: 0.4801 - val_acc: 0.8553
Epoch 00022: val_loss did not improve
Epoch 24/100
100000/100000 [==============================] - 54s - loss: 0.4080 - acc: 0.8608 - val_loss: 0.4700 - val_acc: 0.8495
Epoch 00023: val_loss did not improve
Epoch 25/100
100000/100000 [==============================] - 54s - loss: 0.4045 - acc: 0.8625 - val_loss: 0.4621 - val_acc: 0.8540
Epoch 00024: val_loss did not improve
Epoch 26/100
100000/100000 [==============================] - 54s - loss: 0.4070 - acc: 0.8625 - val_loss: 0.4793 - val_acc: 0.8510
Epoch 00025: val_loss did not improve
Epoch 27/100
100000/100000 [==============================] - 54s - loss: 0.3998 - acc: 0.8641 - val_loss: 0.4788 - val_acc: 0.8545
Epoch 00026: val_loss did not improve
Epoch 00026: early stopping
Out[7]:
<keras.callbacks.History at 0x7ff89f2ba6d8>

In [8]:
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':
                weights = {}
                weight_names = layer_weights_dict[layer['name']]
                for p, name in enumerate(weight_names):
                    weights[name] = weights_file.get('layer_{}/param_{}'.format(k, p)).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 [9]:
import json
model_metadata = json.loads(model.to_json())

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

In [10]:
model_metadata


Out[10]:
{'class_mode': 'categorical',
 'layers': [{'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'border_mode': 'full',
   'init': 'glorot_uniform',
   'input_shape': [3, 32, 32],
   'name': 'Convolution2D',
   'nb_col': 3,
   'nb_filter': 32,
   'nb_row': 3,
   'subsample': [1, 1]},
  {'alpha': 0.2, 'name': 'LeakyReLU'},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'border_mode': 'valid',
   'init': 'glorot_uniform',
   'name': 'Convolution2D',
   'nb_col': 3,
   'nb_filter': 32,
   'nb_row': 3,
   'subsample': [1, 1]},
  {'alpha': 0.2, 'name': 'LeakyReLU'},
  {'ignore_border': True,
   'name': 'MaxPooling2D',
   'pool_size': [2, 2],
   'stride': [2, 2]},
  {'name': 'Dropout', 'p': 0.2},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'border_mode': 'full',
   'init': 'glorot_uniform',
   'name': 'Convolution2D',
   'nb_col': 3,
   'nb_filter': 64,
   'nb_row': 3,
   'subsample': [1, 1]},
  {'alpha': 0.2, 'name': 'LeakyReLU'},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'border_mode': 'valid',
   'init': 'glorot_uniform',
   'name': 'Convolution2D',
   'nb_col': 3,
   'nb_filter': 64,
   'nb_row': 3,
   'subsample': [1, 1]},
  {'alpha': 0.2, 'name': 'LeakyReLU'},
  {'ignore_border': True,
   'name': 'MaxPooling2D',
   'pool_size': [2, 2],
   'stride': [2, 2]},
  {'name': 'Dropout', 'p': 0.3},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'border_mode': 'full',
   'init': 'glorot_uniform',
   'name': 'Convolution2D',
   'nb_col': 3,
   'nb_filter': 128,
   'nb_row': 3,
   'subsample': [1, 1]},
  {'alpha': 0.2, 'name': 'LeakyReLU'},
  {'W_constraint': None,
   'W_regularizer': None,
   'activation': 'linear',
   'activity_regularizer': None,
   'b_constraint': None,
   'b_regularizer': None,
   'border_mode': 'valid',
   'init': 'glorot_uniform',
   'name': 'Convolution2D',
   'nb_col': 3,
   'nb_filter': 128,
   'nb_row': 3,
   'subsample': [1, 1]},
  {'alpha': 0.2, 'name': 'LeakyReLU'},
  {'ignore_border': True,
   'name': 'MaxPooling2D',
   'pool_size': [2, 2],
   'stride': [2, 2]},
  {'name': 'Dropout', 'p': 0.4},
  {'name': 'Flatten'},
  {'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': 512},
  {'activation': 'relu', 'beta': 0.1, 'name': 'Activation', 'target': 0},
  {'name': 'Dropout', 'p': 0.5},
  {'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 [11]:
serialize('cifar10_cnn_keras_model.json', 
          'cifar10_cnn_keras_weights.hdf5', 
          'cifar10_cnn_model_params.json.gz', 
          True)
serialize('cifar10_cnn_keras_model.json', 
          'cifar10_cnn_keras_weights.hdf5', 
          'cifar10_cnn_model_params.json', 
          False)

In [12]:
import numpy as np
import gzip
randidx = np.random.randint(0, X_test.shape[0], size=500)
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 [13]:
%%time
model.predict(X_rand[0:1,:])


CPU times: user 0 ns, sys: 3.87 ms, total: 3.87 ms
Wall time: 3.14 ms
Out[13]:
array([[  1.74755250e-08,   1.96856378e-10,   6.87712309e-05,
          1.23311373e-04,   2.04585871e-04,   6.30733185e-03,
          1.16306846e-05,   9.93284345e-01,   4.71561568e-10,
          4.12435739e-08]])

In [ ]: