CIFAR 10 Abalation study

1) LeNET scratch (59%)

2) Use MaxPool instead of Average pool (Slight improvement : 61% )

3) Use ReLu instead of TanH (Fast training but not much improvement)

4) L2 regularizer with Relu (Slight improvement : 63%)

5) Increase convolution filters (Improves to 70%, which is the benchmark for model of this size and its training settings)

In [1]:
import tensorflow as tf
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import glob
%matplotlib inline

Data pipeline

In [2]:
def get_accuracy(predict:'eg: [2,4,1,...]',true: 'eg: [2,4,1,...]') -> int:
    correct_pred = tf.equal(predict,true)
    #We have to cast [True,False,True,...] --> [1,0,1...]
    acc = tf.reduce_mean(tf.cast(correct_pred,tf.float32))
    return acc

file_path = "datasets/cifar-10-batches-bin/data_batch_*"
train_bins = glob.glob(file_path)


def cifar_dataset(files_list:list) -> tf.data.Dataset:

    data = tf.data.FixedLengthRecordDataset(files_list,1+3*32*32)
    data = data.map(lambda x: tf.decode_raw(x,tf.uint8),num_parallel_calls=4)
    data = data.map(lambda x: (x[1:],tf.expand_dims(x[0],0)),num_parallel_calls=4) 
    data = data.map(lambda x,y: (tf.reshape(x,(3,32,32)),y),num_parallel_calls=4)
    data = data.map(lambda x,y: (tf.transpose(x,(1,2,0)),y),num_parallel_calls=4)
    data = data.map(lambda x,y: (tf.image.convert_image_dtype(x,tf.float32),y),num_parallel_calls=4)
        
    return data

with tf.device('/cpu:0'):
    train_dataset = cifar_dataset(train_bins)
    train_dataset = train_dataset.shuffle(20000)
    train_dataset = train_dataset.repeat(20)
    train_dataset = train_dataset.batch(10)
    train_dataset = train_dataset.prefetch(2)

handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle,train_dataset.output_types,train_dataset.output_shapes)
model_input,label = iterator.get_next()

train_iterator = train_dataset.make_one_shot_iterator()

with tf.device('/cpu:0'):
    test_dataset = cifar_dataset(['datasets/cifar-10-batches-bin/test_batch.bin'])
    test_dataset = test_dataset.batch(10)
    test_dataset = test_dataset.prefetch(2)
    
test_iterator = test_dataset.make_one_shot_iterator()
In [3]:
train_dataset.output_shapes,train_dataset.output_types
Out[3]:
((TensorShape([Dimension(None), Dimension(32), Dimension(32), Dimension(3)]),
  TensorShape([Dimension(None), Dimension(1)])),
 (tf.float32, tf.uint8))

Train and Validate function

In [4]:
DROPOUT = tf.placeholder(tf.bool)
def trainval():
    import time

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())

        #Training
        hdl = sess.run(train_iterator.string_handle())   
        start = time.time()
        try:
            i = 1
            tmp = []
            while True:
                i = i+1
                l,_ = sess.run([loss,train],{handle:hdl,DROPOUT:True})
                tmp.append(l)
                if i%5000 == 0:
                    avg_loss = np.array(tmp).mean()
                    print("Batch: ",i,avg_loss)
                    tmp = []

        except tf.errors.OutOfRangeError:
            pass

        end = time.time()
        elapsed = end-start
        print("Elapsed time : ", elapsed, " s")

        #Testing
        print("Testing : ")
        hdl = sess.run(test_iterator.string_handle())    
        acc = get_accuracy(tf.argmax(classifier,axis=1),tf.transpose(tf.argmax(tf.one_hot(label,10),axis=2)))

        try:
            i = 0
            acc_list = []
            while True:
                i = i+1
                a = sess.run(acc,{handle:hdl,DROPOUT:False})
                acc_list.append(a)
                if i%100 == 0:
                    print(i, "Mean Acc : ", np.array(acc_list).mean())
                    acc_list = []

        except tf.errors.OutOfRangeError:
            pass 

Model 1: LeNET Scratch

Base Accuracy : 59%

In [4]:
def cnn_features(model_input):
    
    conv1 = tf.layers.conv2d(model_input,6,(5,5),(1,1),activation=tf.nn.tanh,name="Conv1")
    avgpool1 = tf.layers.average_pooling2d(conv1,(2,2),(2,2),name="AvgPool1")
    
    conv2 = tf.layers.conv2d(avgpool1,16,(5,5),(1,1),activation=tf.nn.tanh,name="Conv2")
    avgpool2 = tf.layers.average_pooling2d(conv2,(2,2),(2,2),name="AvgPool2")
    
    conv3 = tf.layers.conv2d(avgpool2,120,(5,5),(1,1),activation=tf.nn.tanh,name="Conv3")
    
    flatten = tf.layers.Flatten()(conv3)
    
    features = tf.layers.dense(flatten,84,activation=tf.nn.tanh,name="Dense_84")
    
    return features
In [5]:
features = cnn_features(model_input)
classifier = tf.layers.dense(features,10,name="Dense_10")

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=tf.one_hot(label,10),logits=classifier))
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
In [7]:
trainval()
Batch:  5000 1.8475738
Batch:  10000 1.5774492
Batch:  15000 1.4366148
Batch:  20000 1.3506023
Batch:  25000 1.2912809
Batch:  30000 1.2428441
Batch:  35000 1.2014774
Batch:  40000 1.164475
Batch:  45000 1.1318848
Batch:  50000 1.100357
Batch:  55000 1.0726489
Batch:  60000 1.0479746
Batch:  65000 1.0217873
Batch:  70000 0.9982334
Batch:  75000 0.97316056
Batch:  80000 0.9523098
Batch:  85000 0.928825
Batch:  90000 0.90928185
Batch:  95000 0.8877957
Batch:  100000 0.8699004
Elapsed time :  132.51710152626038  s
Testing : 
100 Mean Acc :  0.5989999
200 Mean Acc :  0.59700006
300 Mean Acc :  0.589
400 Mean Acc :  0.602
500 Mean Acc :  0.60300004
600 Mean Acc :  0.574
700 Mean Acc :  0.573
800 Mean Acc :  0.608
900 Mean Acc :  0.5799999
1000 Mean Acc :  0.5870001

Model 2: LeNET but with Maxpool

Slight improvement (61%)

In [4]:
def cnn_features(model_input):
    
    conv1 = tf.layers.conv2d(model_input,6,(5,5),(1,1),activation=tf.nn.tanh,name="Conv1")
    maxpool1 = tf.layers.max_pooling2d(conv1,(2,2),(2,2),name="MaxPool1")
    
    conv2 = tf.layers.conv2d(maxpool1,16,(5,5),(1,1),activation=tf.nn.tanh,name="Conv2")
    maxpool2 = tf.layers.max_pooling2d(conv2,(2,2),(2,2),name="MaxPool2")
    
    conv3 = tf.layers.conv2d(maxpool2,120,(5,5),(1,1),activation=tf.nn.tanh,name="Conv3")
    
    flatten = tf.layers.Flatten()(conv3)
    
    features = tf.layers.dense(flatten,84,activation=tf.nn.tanh,name="Dense_84")
    
    return features

features = cnn_features(model_input)
classifier = tf.layers.dense(features,10,name="Dense_10")

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=tf.one_hot(label,10),logits=classifier))
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
In [6]:
trainval()
Batch:  5000 1.6675485
Batch:  10000 1.3732225
Batch:  15000 1.2616618
Batch:  20000 1.1835613
Batch:  25000 1.1243168
Batch:  30000 1.0753567
Batch:  35000 1.0307881
Batch:  40000 0.9922322
Batch:  45000 0.9570381
Batch:  50000 0.92365265
Batch:  55000 0.8934568
Batch:  60000 0.8650314
Batch:  65000 0.8358092
Batch:  70000 0.81065595
Batch:  75000 0.7840318
Batch:  80000 0.7584776
Batch:  85000 0.7320794
Batch:  90000 0.708358
Batch:  95000 0.6857122
Batch:  100000 0.66245407
Elapsed time :  131.8530716896057  s
Testing : 
100 Mean Acc :  0.62100005
200 Mean Acc :  0.63100004
300 Mean Acc :  0.577
400 Mean Acc :  0.60999995
500 Mean Acc :  0.62600005
600 Mean Acc :  0.616
700 Mean Acc :  0.608
800 Mean Acc :  0.61800003
900 Mean Acc :  0.6
1000 Mean Acc :  0.62899995

Model 3: ReLU

ReLU if fast, but does not show improvement without regularization

In [5]:
def cnn_features(model_input):
    
    conv1 = tf.layers.conv2d(model_input,6,(5,5),(1,1),activation=tf.nn.relu,name="Conv1")
    maxpool1 = tf.layers.max_pooling2d(conv1,(2,2),(2,2),name="MaxPool1")
    
    conv2 = tf.layers.conv2d(maxpool1,16,(5,5),(1,1),activation=tf.nn.relu,name="Conv2")
    maxpool2 = tf.layers.max_pooling2d(conv2,(2,2),(2,2),name="MaxPool2")
    
    conv3 = tf.layers.conv2d(maxpool2,120,(5,5),(1,1),activation=tf.nn.relu,name="Conv3")
    
    flatten = tf.layers.Flatten()(conv3)
    
    features = tf.layers.dense(flatten,84,activation=tf.nn.relu,name="Dense_84")
    
    return features

features = cnn_features(model_input)
classifier = tf.layers.dense(features,10,name="Dense_10")

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=tf.one_hot(label,10),logits=classifier))
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
In [6]:
trainval()
Batch:  5000 1.7889365
Batch:  10000 1.4177151
Batch:  15000 1.2917476
Batch:  20000 1.2078041
Batch:  25000 1.1424283
Batch:  30000 1.0895842
Batch:  35000 1.0419424
Batch:  40000 0.9986101
Batch:  45000 0.9605549
Batch:  50000 0.92250764
Batch:  55000 0.8892804
Batch:  60000 0.85587186
Batch:  65000 0.8264523
Batch:  70000 0.80096054
Batch:  75000 0.77150655
Batch:  80000 0.7439104
Batch:  85000 0.71845305
Batch:  90000 0.69797635
Batch:  95000 0.6725598
Batch:  100000 0.6565832
Elapsed time :  138.70953798294067  s
Testing : 
100 Mean Acc :  0.5889999
200 Mean Acc :  0.62
300 Mean Acc :  0.588
400 Mean Acc :  0.604
500 Mean Acc :  0.606
600 Mean Acc :  0.613
700 Mean Acc :  0.581
800 Mean Acc :  0.623
900 Mean Acc :  0.58
1000 Mean Acc :  0.597

Model 4: L2 regularization

Slight improvement (63%)

In [6]:
def cnn_features(model_input):
    
    conv1 = tf.layers.conv2d(model_input,6,(5,5),(1,1),
                             kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.001), 
                             activation=tf.nn.relu,
                             name="Conv1")
    maxpool1 = tf.layers.max_pooling2d(conv1,(2,2),(2,2),name="MaxPool1")
    
    conv2 = tf.layers.conv2d(maxpool1,16,(5,5),(1,1),
                             kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.01),
                             activation=tf.nn.relu,
                             name="Conv2")
    maxpool2 = tf.layers.max_pooling2d(conv2,(2,2),(2,2),name="MaxPool2")
    
    conv3 = tf.layers.conv2d(maxpool2,120,(5,5),(1,1),
                             kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.01), 
                             activation=tf.nn.relu,
                             name="Conv3")
    
    flatten = tf.layers.Flatten()(conv3)
    
    features = tf.layers.dense(flatten,84,
                               kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.01), 
                               activation=tf.nn.relu,
                               name="Dense_84")
    
    
    return features

features = cnn_features(model_input)
classifier = tf.layers.dense(features,10,name="Dense_10")

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=tf.one_hot(label,10),logits=classifier))
loss += tf.losses.get_regularization_loss()
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
In [7]:
trainval()
Batch:  5000 2.2963307
Batch:  10000 1.7417562
Batch:  15000 1.5815724
Batch:  20000 1.5106776
Batch:  25000 1.4716152
Batch:  30000 1.4410975
Batch:  35000 1.4193088
Batch:  40000 1.4014232
Batch:  45000 1.3863301
Batch:  50000 1.3702798
Batch:  55000 1.3545686
Batch:  60000 1.3375293
Batch:  65000 1.3281711
Batch:  70000 1.3186255
Batch:  75000 1.3115855
Batch:  80000 1.2989252
Batch:  85000 1.2943399
Batch:  90000 1.2881706
Batch:  95000 1.2838296
Batch:  100000 1.278085
Elapsed time :  137.675359249115  s
Testing : 
100 Mean Acc :  0.62999994
200 Mean Acc :  0.62100005
300 Mean Acc :  0.59300005
400 Mean Acc :  0.635
500 Mean Acc :  0.6619999
600 Mean Acc :  0.64199996
700 Mean Acc :  0.59699994
800 Mean Acc :  0.6319999
900 Mean Acc :  0.612
1000 Mean Acc :  0.622

Model 5: Increase Filters

Achieved 70% accuracy

GPU Util : 60%, GPU Temp: 70 degree

In [5]:
def cnn_features(model_input):
    
    conv1 = tf.layers.conv2d(model_input,32,(5,5),(1,1),
                             kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.001), 
                             activation=tf.nn.relu,
                             name="Conv1")
    maxpool1 = tf.layers.max_pooling2d(conv1,(2,2),(2,2),name="MaxPool1")
    
    conv2 = tf.layers.conv2d(maxpool1,64,(5,5),(1,1),
                             kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.01),
                             activation=tf.nn.relu,
                             name="Conv2")
    maxpool2 = tf.layers.max_pooling2d(conv2,(2,2),(2,2),name="MaxPool2")
    
    conv3 = tf.layers.conv2d(maxpool2,120,(5,5),(1,1),
                             kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.01), 
                             activation=tf.nn.relu,
                             name="Conv3")
    
    flatten = tf.layers.Flatten()(conv3)
    
    
    features = tf.layers.dense(flatten,592,
                               kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.01), 
                               activation=tf.nn.relu,
                               name="Dense_84")
    
    
    return features

features = cnn_features(model_input)
classifier = tf.layers.dense(features,10,name="Dense_10")

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=tf.one_hot(label,10),logits=classifier))
loss += tf.losses.get_regularization_loss()
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
In [6]:
trainval()
Batch:  5000 2.8987796
Batch:  10000 1.9110137
Batch:  15000 1.5600703
Batch:  20000 1.407018
Batch:  25000 1.3275896
Batch:  30000 1.2812109
Batch:  35000 1.2481775
Batch:  40000 1.2185266
Batch:  45000 1.197651
Batch:  50000 1.1789722
Batch:  55000 1.1598485
Batch:  60000 1.1452051
Batch:  65000 1.1309775
Batch:  70000 1.1194522
Batch:  75000 1.1119484
Batch:  80000 1.106407
Batch:  85000 1.0965117
Batch:  90000 1.0920885
Batch:  95000 1.0879949
Batch:  100000 1.0839711
Elapsed time :  208.71310687065125  s
Testing : 
100 Mean Acc :  0.7120001
200 Mean Acc :  0.7190001
300 Mean Acc :  0.69500005
400 Mean Acc :  0.7249999
500 Mean Acc :  0.726
600 Mean Acc :  0.7150001
700 Mean Acc :  0.69499993
800 Mean Acc :  0.7299999
900 Mean Acc :  0.695
1000 Mean Acc :  0.68999994