CIFAR10 CNN

Train a simple deep CNN on the CIFAR10 small images dataset.

Some constants we’ll use:

In [1]:
batch_size = 32
num_classes = 10
epochs = 200
data_augmentation = True
num_predictions = 20
In [2]:
from conx import *
conx, version 3.4.0
Using Theano backend.
In [3]:
net = Network("CIRAR10")
net.add(ImageLayer("input", (32, 32), 3)) # depends on K.image_data_format(), right?
net.add(Conv2DLayer("conv1", 32, (3, 3), padding='same', activation='relu'))
net.add(Conv2DLayer("conv2", 32, (3, 3), activation='relu'))
net.add(MaxPool2DLayer("pool1", pool_size=(2, 2), dropout=0.25))
net.add(Conv2DLayer("conv3", 64, (3, 3), padding='same', activation='relu'))
net.add(Conv2DLayer("conv4", 64, (3, 3), activation='relu'))
net.add(MaxPool2DLayer("pool2", pool_size=(2, 2), dropout=0.25))
net.add(FlattenLayer("flatten"))
net.add(Layer("hidden1", 512, activation='relu', vshape=(16, 32), dropout=0.5))
net.add(Layer("output", num_classes, activation='softmax'))
net.connect()

# initiate RMSprop optimizer
opt = RMSprop(lr=0.0001, decay=1e-6)

net.compile(loss='categorical_crossentropy',
            optimizer=opt)

# Let's train the model using RMSprop
net.compile(loss='categorical_crossentropy',
              optimizer=opt,
              metrics=['accuracy'])
model = net.model
In [4]:
net.dataset.get("cifar10")
In [5]:
net.dataset.summary()
Input Summary:
   count  : 60000 (60000 for training, 0 for testing)
   shape  : [(32, 32, 3)]
   range  : (0.0, 1.0)
Target Summary:
   count  : 60000 (60000 for training, 0 for testing)
   shape  : [(10,)]
   range  : (0.0, 1.0)
In [6]:
net.dataset.split(50000)
net.dataset.summary()
Input Summary:
   count  : 60000 (10000 for training, 50000 for testing)
   shape  : [(32, 32, 3)]
   range  : (0.0, 1.0)
Target Summary:
   count  : 60000 (10000 for training, 50000 for testing)
   shape  : [(10,)]
   range  : (0.0, 1.0)

Examine Input as Image

In [8]:
net.dataset.inputs.shape
Out[8]:
[(32, 32, 3)]
In [9]:
net.dataset.targets.shape
Out[9]:
[(10,)]
In [10]:
image = array2image(net.dataset.inputs[0], scale=5.0)
image
Out[10]:
_images/CIFAR10_CNN_11_0.png
In [11]:
net.dashboard()
In [12]:
net.propagate(net.dataset.inputs[1])
Out[12]:
[0.09824256598949432,
 0.11341553181409836,
 0.10656856745481491,
 0.09783723950386047,
 0.11487564444541931,
 0.098569855093956,
 0.09011363238096237,
 0.08840988576412201,
 0.09548024833202362,
 0.09648684412240982]

Let Keras Take over from here

In [13]:
import keras
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
In [19]:
import numpy as np
In [24]:
(x_train, y_train), (x_test, y_test) = net.dataset._split_data()
In [25]:
model = net.model
In [26]:
if not data_augmentation:
    print('Not using data augmentation.')
    model.fit(x_train, y_train,
              batch_size=batch_size,
              epochs=epochs,
              validation_data=(x_test, y_test),
              shuffle=True)
else:
    print('Using real-time data augmentation.')
    # This will do preprocessing and realtime data augmentation:
    datagen = ImageDataGenerator(
        featurewise_center=False,  # set input mean to 0 over the dataset
        samplewise_center=False,  # set each sample mean to 0
        featurewise_std_normalization=False,  # divide inputs by std of the dataset
        samplewise_std_normalization=False,  # divide each input by its std
        zca_whitening=False,  # apply ZCA whitening
        rotation_range=0,  # randomly rotate images in the range (degrees, 0 to 180)
        width_shift_range=0.1,  # randomly shift images horizontally (fraction of total width)
        height_shift_range=0.1,  # randomly shift images vertically (fraction of total height)
        horizontal_flip=True,  # randomly flip images
        vertical_flip=False)  # randomly flip images

    # Compute quantities required for feature-wise normalization
    # (std, mean, and principal components if ZCA whitening is applied).
    datagen.fit(x_train)

    # Fit the model on the batches generated by datagen.flow().
    model.fit_generator(datagen.flow(x_train, y_train,
                                     batch_size=batch_size),
                        steps_per_epoch=x_train.shape[0] // batch_size,
                        epochs=epochs,
                        validation_data=(x_test, y_test))
Using real-time data augmentation.
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-26-5b1f85cbe1cb> in <module>()
     23     # Compute quantities required for feature-wise normalization
     24     # (std, mean, and principal components if ZCA whitening is applied).
---> 25     datagen.fit(x_train)
     26
     27     # Fit the model on the batches generated by datagen.flow().

/usr/local/lib/python3.6/dist-packages/keras/preprocessing/image.py in fit(self, x, augment, rounds, seed)
    673         if x.ndim != 4:
    674             raise ValueError('Input to `.fit()` should have rank 4. '
--> 675                              'Got array with shape: ' + str(x.shape))
    676         if x.shape[self.channel_axis] not in {1, 3, 4}:
    677             warnings.warn(

ValueError: Input to `.fit()` should have rank 4. Got array with shape: (1, 10000, 32, 32, 3)
In [31]:
# Evaluate model with test data set and share sample prediction results
evaluation = model.evaluate_generator(datagen.flow(x_test, y_test,
                                      batch_size=batch_size),
                                      steps=x_test.shape[0] // batch_size)

print('Model Accuracy = %.2f' % (evaluation[1]))

predict_gen = model.predict_generator(datagen.flow(x_test, y_test,
                                      batch_size=batch_size),
                                      steps=x_test.shape[0] // batch_size)

for predict_index, predicted_y in enumerate(predict_gen):
    actual_label = labels['label_names'][np.argmax(y_test[predict_index])]
    predicted_label = labels['label_names'][np.argmax(predicted_y)]
    print('Actual Label = %s vs. Predicted Label = %s' % (actual_label,
                                                          predicted_label))
    if predict_index == num_predictions:
        break
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-31-ebd54f7403a8> in <module>()
      1 # Evaluate model with test data set and share sample prediction results
      2 evaluation = model.evaluate_generator(datagen.flow(x_test, y_test,
----> 3                                       batch_size=batch_size),
      4                                       steps=x_test.shape[0] // batch_size)
      5

/usr/local/lib/python3.6/dist-packages/keras/preprocessing/image.py in flow(self, x, y, batch_size, shuffle, seed, save_to_dir, save_prefix, save_format)
    491             save_to_dir=save_to_dir,
    492             save_prefix=save_prefix,
--> 493             save_format=save_format)
    494
    495     def flow_from_directory(self, directory,

/usr/local/lib/python3.6/dist-packages/keras/preprocessing/image.py in __init__(self, x, y, image_data_generator, batch_size, shuffle, seed, data_format, save_to_dir, save_prefix, save_format)
    845             raise ValueError('Input data in `NumpyArrayIterator` '
    846                              'should have rank 4. You passed an array '
--> 847                              'with shape', self.x.shape)
    848         channels_axis = 3 if data_format == 'channels_last' else 1
    849         if self.x.shape[channels_axis] not in {1, 3, 4}:

ValueError: ('Input data in `NumpyArrayIterator` should have rank 4. You passed an array with shape', (1, 50000, 32, 32, 3))