Deep Learning and Transfer Learning with pre-trained models

This notebook uses a pretrained model to build a classifier (CNN)

In [1]:
# import required libs
import os
import keras
import numpy as np
from keras import backend as K
from keras import applications
from keras.datasets import cifar10
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten

import matplotlib.pyplot as plt
params = {'legend.fontsize': 'x-large',
          'figure.figsize': (15, 5),
         'axes.labelsize': 'x-large',
         'axes.titlesize':'x-large',
         'xtick.labelsize':'x-large',
         'ytick.labelsize':'x-large'}

plt.rcParams.update(params)

%matplotlib inline
Using TensorFlow backend.

Load VGG

In [2]:
vgg_model = applications.VGG19(include_top=False, weights='imagenet')
In [3]:
vgg_model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, None, None, 3)     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, None, None, 64)    1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, None, None, 64)    36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, None, None, 64)    0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, None, None, 128)   73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, None, None, 128)   147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, None, None, 128)   0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, None, None, 256)   295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_conv4 (Conv2D)        (None, None, None, 256)   590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, None, None, 256)   0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, None, None, 512)   1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_conv4 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, None, None, 512)   0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_conv4 (Conv2D)        (None, None, None, 512)   2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, None, None, 512)   0         
=================================================================
Total params: 20,024,384
Trainable params: 20,024,384
Non-trainable params: 0
_________________________________________________________________

Set Parameters

In [4]:
batch_size = 128
num_classes = 10
epochs = 50

bottleneck_path = r'F:\work\kaggle\cifar10_cnn\bottleneck_features_train_vgg19.npy'

Get CIFAR10 Dataset

In [5]:
# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
In [6]:
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, 32, 32, 3)
50000 train samples
10000 test samples
In [7]:
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

y_train.shape
Out[7]:
(50000, 10)

Pretrained Model for Feature Extraction

In [8]:
if not os.path.exists(bottleneck_path):
    bottleneck_features_train = vgg_model.predict(x_train,verbose=1)
    np.save(open(bottleneck_path, 'wb'),
            bottleneck_features_train)
else:
    bottleneck_features_train = np.load(open(bottleneck_path,'rb'))
In [9]:
bottleneck_features_train[0].shape
Out[9]:
(1, 1, 512)
In [10]:
bottleneck_features_test = vgg_model.predict(x_test,verbose=1)
10000/10000 [==============================] - 238s   

Custom Classifier

In [11]:
clf_model = Sequential()
clf_model.add(Flatten(input_shape=bottleneck_features_train.shape[1:]))
clf_model.add(Dense(512, activation='relu'))
clf_model.add(Dropout(0.5))
clf_model.add(Dense(256, activation='relu'))
clf_model.add(Dropout(0.5))
clf_model.add(Dense(num_classes, activation='softmax'))

Visualize the network architecture

In [12]:
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot

SVG(model_to_dot(clf_model, show_shapes=True, 
                 show_layer_names=True, rankdir='TB').create(prog='dot', format='svg'))
Out[12]:
G 2250072534264 flatten_1_input: InputLayer input: output: (None, 1, 1, 512) (None, 1, 1, 512) 2250072533760 flatten_1: Flatten input: output: (None, 1, 1, 512) (None, 512) 2250072534264->2250072533760 2250072541952 dense_1: Dense input: output: (None, 512) (None, 512) 2250072533760->2250072541952 2250072541392 dropout_1: Dropout input: output: (None, 512) (None, 512) 2250072541952->2250072541392 2249866395832 dense_2: Dense input: output: (None, 512) (None, 256) 2250072541392->2249866395832 2250072534488 dropout_2: Dropout input: output: (None, 256) (None, 256) 2249866395832->2250072534488 2250083045048 dense_3: Dense input: output: (None, 256) (None, 10) 2250072534488->2250083045048

Compile the model

In [13]:
clf_model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

Train the classifier

In [14]:
clf_model.fit(bottleneck_features_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1)
Epoch 1/50
50000/50000 [==============================] - 8s - loss: 7.2495 - acc: 0.2799     
Epoch 2/50
50000/50000 [==============================] - 7s - loss: 2.2513 - acc: 0.2768     
Epoch 3/50
50000/50000 [==============================] - 7s - loss: 1.9096 - acc: 0.3521     
Epoch 4/50
50000/50000 [==============================] - 7s - loss: 1.7601 - acc: 0.4020     
Epoch 5/50
50000/50000 [==============================] - 7s - loss: 1.6501 - acc: 0.4355     
Epoch 6/50
50000/50000 [==============================] - 8s - loss: 1.5804 - acc: 0.4581     
Epoch 7/50
50000/50000 [==============================] - 7s - loss: 1.5295 - acc: 0.4766     
Epoch 8/50
50000/50000 [==============================] - 7s - loss: 1.4790 - acc: 0.4953     
Epoch 9/50
50000/50000 [==============================] - 7s - loss: 1.4420 - acc: 0.5078     
Epoch 10/50
50000/50000 [==============================] - 7s - loss: 1.4102 - acc: 0.5183     
Epoch 11/50
50000/50000 [==============================] - 7s - loss: 1.3822 - acc: 0.5278     
Epoch 12/50
50000/50000 [==============================] - 7s - loss: 1.3569 - acc: 0.5389     
Epoch 13/50
50000/50000 [==============================] - 7s - loss: 1.3359 - acc: 0.5461     
Epoch 14/50
50000/50000 [==============================] - 7s - loss: 1.3148 - acc: 0.5534     
Epoch 15/50
50000/50000 [==============================] - 7s - loss: 1.2919 - acc: 0.5628     
Epoch 16/50
50000/50000 [==============================] - 7s - loss: 1.2676 - acc: 0.5674     
Epoch 17/50
50000/50000 [==============================] - 7s - loss: 1.2588 - acc: 0.5713     
Epoch 18/50
50000/50000 [==============================] - 7s - loss: 1.2441 - acc: 0.5776     
Epoch 19/50
50000/50000 [==============================] - 7s - loss: 1.2225 - acc: 0.5861     
Epoch 20/50
50000/50000 [==============================] - 7s - loss: 1.2082 - acc: 0.5909     
Epoch 21/50
50000/50000 [==============================] - 7s - loss: 1.1935 - acc: 0.5966     
Epoch 22/50
50000/50000 [==============================] - 7s - loss: 1.1786 - acc: 0.5999     
Epoch 23/50
50000/50000 [==============================] - 7s - loss: 1.1657 - acc: 0.6026     
Epoch 24/50
50000/50000 [==============================] - 7s - loss: 1.1531 - acc: 0.6085     
Epoch 25/50
50000/50000 [==============================] - 7s - loss: 1.1421 - acc: 0.6138     
Epoch 26/50
50000/50000 [==============================] - 7s - loss: 1.1328 - acc: 0.6158     
Epoch 27/50
50000/50000 [==============================] - 7s - loss: 1.1204 - acc: 0.6191     
Epoch 28/50
50000/50000 [==============================] - 7s - loss: 1.1085 - acc: 0.6228     
Epoch 29/50
50000/50000 [==============================] - 7s - loss: 1.0986 - acc: 0.6274     
Epoch 30/50
50000/50000 [==============================] - 7s - loss: 1.0914 - acc: 0.6313     
Epoch 31/50
50000/50000 [==============================] - 7s - loss: 1.0770 - acc: 0.6341     
Epoch 32/50
50000/50000 [==============================] - 7s - loss: 1.0714 - acc: 0.6366     
Epoch 33/50
50000/50000 [==============================] - 7s - loss: 1.0603 - acc: 0.6417     
Epoch 34/50
50000/50000 [==============================] - 8s - loss: 1.0459 - acc: 0.6433     
Epoch 35/50
50000/50000 [==============================] - 8s - loss: 1.0400 - acc: 0.6483     
Epoch 36/50
50000/50000 [==============================] - 8s - loss: 1.0305 - acc: 0.6465     
Epoch 37/50
50000/50000 [==============================] - 8s - loss: 1.0145 - acc: 0.6547     
Epoch 38/50
50000/50000 [==============================] - 8s - loss: 1.0149 - acc: 0.6531     
Epoch 39/50
50000/50000 [==============================] - 8s - loss: 0.9974 - acc: 0.6587     
Epoch 40/50
50000/50000 [==============================] - 8s - loss: 0.9915 - acc: 0.6622     
Epoch 41/50
50000/50000 [==============================] - 8s - loss: 0.9863 - acc: 0.6618     
Epoch 42/50
50000/50000 [==============================] - 8s - loss: 0.9816 - acc: 0.6644     
Epoch 43/50
50000/50000 [==============================] - 8s - loss: 0.9754 - acc: 0.6666     
Epoch 44/50
50000/50000 [==============================] - 8s - loss: 0.9630 - acc: 0.6686     
Epoch 45/50
50000/50000 [==============================] - 8s - loss: 0.9503 - acc: 0.6755     
Epoch 46/50
50000/50000 [==============================] - 8s - loss: 0.9479 - acc: 0.6752     
Epoch 47/50
50000/50000 [==============================] - 8s - loss: 0.9403 - acc: 0.6787     
Epoch 48/50
50000/50000 [==============================] - 8s - loss: 0.9368 - acc: 0.6814     
Epoch 49/50
50000/50000 [==============================] - 8s - loss: 0.9223 - acc: 0.6832     
Epoch 50/50
50000/50000 [==============================] - 8s - loss: 0.9197 - acc: 0.6830     
Out[14]:
<keras.callbacks.History at 0x20b81e25320>

Predict and test model performance

In [15]:
score = clf_model.evaluate(bottleneck_features_test, y_test, verbose=1)
 9600/10000 [===========================>..] - ETA: 0s
In [16]:
print('Test loss:', score[0])
print('Test accuracy:', score[1])
Test loss: 1.20768193054
Test accuracy: 0.6352

Assign label to a test image

In [53]:
def predict_label(img_idx,show_proba=True):
    plt.imshow(x_test[img_idx],aspect='auto')
    plt.title("Image to be Labeled")
    plt.show()
    
    print("Actual Class:{}".format(np.nonzero(y_test[img_idx])[0][0]))
    
    test_image =np.expand_dims(x_test[img_idx], axis=0)
    bf = vgg_model.predict(test_image,verbose=0)
    pred_label = clf_model.predict_classes(bf,batch_size=1,verbose=0)
    
    print("Predicted Class:{}".format(pred_label[0]))
    if show_proba:
        print("Predicted Probabilities")
        print(clf_model.predict_proba(bf))
In [54]:
img_idx = 3999 # sample indices : 999,1999 and 3999
for img_idx in [999,1999,3999]:
    predict_label(img_idx)
Actual Class:8
Predicted Class:8
Predicted Probabilities
1/1 [==============================] - 0s
[[  1.48474507e-03   3.18384357e-03   2.22270580e-09   1.51026228e-07
    3.13638199e-10   5.12283584e-11   8.54018176e-11   5.50038418e-11
    9.84005570e-01   1.13256825e-02]]
Actual Class:5
Predicted Class:5
Predicted Probabilities
1/1 [==============================] - 0s
[[  3.66592516e-08   3.57114695e-05   7.51468833e-05   1.46524936e-01
    9.77872929e-08   8.52767646e-01   5.81625965e-04   1.08531840e-05
    2.67574318e-08   3.92325774e-06]]
Actual Class:9
Predicted Class:9
Predicted Probabilities
1/1 [==============================] - 0s
[[  1.07423693e-01   1.45525947e-01   9.38104291e-04   4.14230488e-03
    3.73754185e-03   3.26172536e-04   4.70715531e-05   6.63721003e-03
    1.52519494e-01   5.78702450e-01]]