Various Tensorflow Models applied to the MNIST and CIFAR10 image datasets. Code is based on the tensorflow-provided tutorials but with improved performance.

Documentation (Click Here for pdf)



Source Code

import argparse
import numpy as np
import os
import sys
import pickle
from datetime import datetime
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator
from keras.datasets import cifar10
from keras.utils import to_categorical
from tensorflow.examples.tutorials.mnist import input_data


FLAGS = None

def train(_):
    # create new log files
    if tf.gfile.Exists(FLAGS.log_dir):
        tf.gfile.DeleteRecursively(FLAGS.log_dir)
    tf.gfile.MakeDirs(FLAGS.log_dir)

    tf.reset_default_graph()
    tf.set_random_seed(1)
    np.random.seed(1)

    batch_size = 100
    num_classes = 10

    (X_train, y_train), (X_test, y_test) = cifar10.load_data()
    print("Train Images dimensions =", X_train.shape)
    print("Train Labels dimensions =", y_train.shape)

    y_train = to_categorical(y_train, num_classes)
    y_test  = to_categorical(y_test, num_classes)

    X_train = X_train.astype('float32')
    X_test = X_test.astype('float32')
    X_train /= 255.0
    X_test /= 255.0

    label_list_path = '/Users/graham/.keras/datasets/cifar-10-batches-py/batches.meta'
    with open(label_list_path, mode='rb') as f:
        labels = pickle.load(f)
    labels = labels['label_names']

    gen = ImageDataGenerator(rotation_range=6, width_shift_range=0.06, shear_range=0.27,     # could be change to 0.1's
                             height_shift_range=0.06, zoom_range=0.06, horizontal_flip=True) # featurewise_center=False, featurewise_std_normalization=False,
    train_gen = gen.flow(X_train, y_train, batch_size=batch_size, seed=0)

    # Create a multilayer model.
    sess = tf.InteractiveSession()

    # Input placeholders
    with tf.name_scope('input'):
        x  = tf.placeholder(tf.float32, [None, 32*32*3], name='x-input')
        y_ = tf.placeholder(tf.int64,   [None, num_classes], name='y-input')

    def weight_variable(shape):
        """Create a weight variable with appropriate initialization."""
        initial = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(initial)

    def bias_variable(shape):
        """Create a bias variable with appropriate initialization."""
        initial = tf.constant(0.1, shape=shape)
        return tf.Variable(initial)

    def conv2dx(x, num_outputs):
        return tf.contrib.layers.conv2d(x, kernel_size=[3,3], num_outputs=num_outputs,
            stride=[1, 1], padding='SAME',
            normalizer_fn=tf.layers.batch_normalization,
            normalizer_params={"training": False, "reuse": False},
            activation_fn=tf.nn.relu,)


    x_image = tf.reshape(x, [-1,32,32,3])

    #conv1 with batch normalisation
    h_conv1 = conv2dx(x_image, 32)
    print ("h_conv1" + str(h_conv1.get_shape()))

    #conv2 with batch normalisation
    h_conv2 = conv2dx(h_conv1, 64)
    print ("h_conv2" + str(h_conv2.get_shape()))

    #pool1
    h_pool1 = tf.nn.max_pool(h_conv2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    print ("h_pool1" + str(h_pool1.get_shape()))

    #conv3 with batch normalisation
    h_conv3 = conv2dx(h_pool1, 64)
    print ("h_conv1" + str(h_conv3.get_shape()))

    #conv4 with batch normalisation
    h_conv4 = conv2dx(h_conv3, 64)
    print ("h_conv4" + str(h_conv4.get_shape()))

    #pool2
    h_pool2 = tf.nn.max_pool(h_conv4, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    print ("h_pool1" + str(h_pool2.get_shape()))

    # dense1 with flatten
    W_fc1 = weight_variable([32*32*16, 512])
    b_fc1 = bias_variable([512])

    h_flat = tf.reshape(h_conv3, [-1, 32*32*16])
    h_fc1 = tf.nn.relu(tf.matmul(h_flat, W_fc1) + b_fc1)
    print ("h_fc1" + str(h_fc1.get_shape()))

    keep_prob = tf.placeholder(tf.float32)
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
    print ("h_fc1_drop" + str(h_fc1_drop.get_shape()))

    # dense2 then softmax the output
    W_fc2 = weight_variable([512, 10])
    b_fc2 = bias_variable([10])

    y = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
    print ("y" + str(y.get_shape()))


    with tf.name_scope('cross_entropy'):
        with tf.name_scope('total'):
            cross_entropy = tf.reduce_mean(-tf.reduce_sum(
                tf.cast(y_, tf.float32) * tf.log(y+1e-10), reduction_indices=[1]))
            # cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
    tf.summary.scalar('cross_entropy', cross_entropy)

    with tf.name_scope('train'):
        train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize(cross_entropy)

    with tf.name_scope('accuracy'):
        with tf.name_scope('correct_prediction'):
            correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_,1)) 
        with tf.name_scope('accuracy'):
            accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar('accuracy', accuracy)


    # Merge all the summaries and write them out
    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter(FLAGS.log_dir + '/train', sess.graph,flush_secs=10)
    test_writer  = tf.summary.FileWriter(FLAGS.log_dir + '/test',flush_secs=10)
    tf.global_variables_initializer().run()

    def feed_dict(train):
        if train:
            xs, ys = next(train_gen)
            xs = xs.reshape(batch_size, 32*32*3)
            k = FLAGS.dropout
        else:
            xs, ys = X_test, y_test
            xs = xs.reshape(10000, 32*32*3)
            k = 1.0
        return {x: xs, y_: ys, keep_prob: k}

    for i in range(FLAGS.max_steps+1):
        if i % 100 == 0:  # Record summaries and test-set accuracy
            summary, acc = sess.run([merged, accuracy], feed_dict=feed_dict(False))
            test_writer.add_summary(summary, i)
            print('%s Accuracy at step %s: %s' % (datetime.now(), i, acc))
        else:  # Record train set summaries, and train
            if i % 100 == 99:  # Record execution stats
                run_options = tf.RunOptions()
                run_metadata = tf.RunMetadata()
                summary, _ = sess.run([merged, train_step],
                                      feed_dict=feed_dict(True),
                                      options=run_options,
                                      run_metadata=run_metadata)
                train_writer.add_run_metadata(run_metadata, 'step%03d' % i)
                train_writer.add_summary(summary, i)
                # print('Adding run metadata for', i)
            else:  # Record a summary
                summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
                if i % 10 == 0:
                    train_writer.add_summary(summary, i)
    train_writer.close()
    test_writer.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--max_steps', type=int, default=80000, 
                        help='Number of steps to run trainer.')
    parser.add_argument('--learning_rate', type=float, default=0.0005,
                        help='Initial learning rate')
    parser.add_argument('--dropout', type=float, default=0.8,
                        help='Keep probability for training dropout.')
    parser.add_argument('--data_dir', type=str,
                        default=os.path.join(os.getenv('TEST_TMPDIR', '/tmp'), 'tf/cifar10/input_data'),
                        help='Directory for storing input data')
    parser.add_argument('--log_dir', type=str,
                        default=os.path.join(os.getenv('TEST_TMPDIR', '/tmp'), 'tf/cifar10/augm_bn_convelu'),
                        help='Summaries log directory')
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=train, argv=[sys.argv[0]] + unparsed)

Comments

comments powered by Disqus