TensorFlow is one of the most popular deep learning framework developed by Google. If you are new to TensorFlow, please read and play with the sample in Getting started with TensorFlow to get started.
In [5]:
# Import required libraries
# Add whatever you want
import os
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# for auto-reloading external modules
# see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython
%load_ext autoreload
%autoreload 2
print "TensorFlow Version {}".format(tf.__version__)
In [6]:
# Test matplotlib
x = np.linspace(-3, 3, 100)
plt.plot(x, np.maximum(0, x), label='relu')
plt.plot(x, 1/(1 + np.exp(-x)), label='sigmoid')
plt.plot(x, (1 - np.exp(-2 * x))/(1 + np.exp(-2 * x)), label='tanh')
plt.xlabel('x')
plt.ylabel('y')
plt.title("Activation functions")
plt.legend()
plt.grid(True)
plt.show()
In [7]:
# Test tensorflow
print('TensorFlow version: ' + tf.__version__)
a = tf.constant(2.0)
b = tf.constant(3.0)
c = a * b
sess = tf.Session()
result = sess.run([a, b, c])
print('%f * %f = %f' % (result[0], result[1], result[2]))
sess.close()
Download CIFAR-10 and load the dataset. In this assignment, we will use all 50,000 images for training and 10,000 images for test.
In [9]:
# Configuration
num_training = 49000
num_validation = 50000 - num_training
num_test = 10000
def unpickle(file):
import sys
if sys.version_info.major == 2:
import cPickle
with open(file, 'rb') as fo:
dict = cPickle.load(fo)
return dict['data'], dict['labels']
else:
import pickle
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
return dict[b'data'], dict[b'labels']
def load_train_data():
#############################################################################
# TODO: Load training data from cifar-10 dataset #
# Load five files from 'data_batch_1' to 'data_batch_5' #
# Reshape images and labels to the shape of [50000, 32, 32, 3] #
# and [50000], respectively #
#############################################################################
data_path = "data/cifar-10-batches-py"
all_batches = []
all_labels = []
for b in range(1,6):
f_train_curr = os.path.join(data_path, 'data_batch_%d' % (b, ))
d = unpickle(f_train_curr)
batch = d[0].reshape(10000, 3, 32, 32).transpose(0,2,3,1).astype("float")
labels = np.array(d[1])
all_batches.append(batch)
all_labels.append(labels)
data_train = np.concatenate(all_batches)
labels_train = np.concatenate(all_labels)
data_val = data_train[range(num_training, num_training+num_validation)]
labels_val = labels_train[range(num_training, num_training+num_validation)]
data_train = data_train[range(num_training)]
labels_train = labels_train[range(num_training)]
return data_train, labels_train, data_val, labels_val
#############################################################################
# END OF YOUR CODE #
#############################################################################
def load_test_data():
#############################################################################
# TODO: Load testing data from cifar-10 dataset #
# Load 'test_batch' file #
# Reshape images and labels to the shape of [10000, 32, 32, 3] #
# and [10000], respectively #
#############################################################################
data_path = "data/cifar-10-batches-py"
f_test = os.path.join(data_path, 'test_batch')
d = unpickle(f_test)
data_test = d[0].reshape(10000, 3, 32, 32).transpose(0,2,3,1).astype("float")
labels_test = np.array(d[1])
return data_test, labels_test
#############################################################################
# END OF YOUR CODE #
#############################################################################
# Load cifar-10 data
X_train, Y_train, X_val, Y_val = load_train_data()
X_test, Y_test = load_test_data()
# Check the shape of the dataset
assert X_train.shape == (num_training, 32, 32, 3)
assert Y_train.shape == (num_training, )
assert X_val.shape == (num_validation, 32, 32, 3)
assert Y_val.shape == (num_validation, )
assert X_test.shape == (num_test, 32, 32, 3)
assert Y_test.shape == (10000, )
Using the code provided, implement a neural network architecture with an optimization routine according to the specification provided below.
Model:
Optimizer:
Learning rate:
Loss:
Your model should achieve about 60% accuracy on validation set in 5 epochs using provided evaluation code.
You can modify the template code as you want.
In [10]:
# Define max pooling and conv layers
def conv2d(input, kernel_size, stride, num_filter):
stride_shape = [1, stride, stride, 1]
filter_shape = [kernel_size, kernel_size, input.get_shape()[3], num_filter]
W = tf.get_variable('w', filter_shape, tf.float32, tf.random_normal_initializer(0.0, 0.02))
b = tf.get_variable('b', [1, 1, 1, num_filter], initializer=tf.constant_initializer(0.0))
return tf.nn.conv2d(input, W, stride_shape, padding='SAME') + b
def max_pool(input, kernel_size, stride):
ksize = [1, kernel_size, kernel_size, 1]
strides = [1, stride, stride, 1]
return tf.nn.max_pool(input, ksize=ksize, strides=strides, padding='SAME')
#############################################################################
# TODO: You can add any layers (fully-connected, normalization) #
#############################################################################
def fully_connected(inputs, units, activation=None, kernel_regularizer=None, bias_regularizer=None):
return tf.layers.dense(inputs=inputs, units=units, activation=activation)
def lrelu(x, alpha):
return tf.nn.relu(x) - alpha * tf.nn.relu(-x)
#############################################################################
# END OF YOUR CODE #
#############################################################################
In [11]:
class BaseModel(object):
def __init__(self):
self.num_epoch = 5
self.batch_size = 128
self.log_step = 50
self._build_model()
def _model(self):
print('-' * 5 + ' Sample model ' + '-' * 5)
print('intput layer: ' + str(self.X.get_shape()))
with tf.variable_scope('conv1'):
self.conv1 = conv2d(self.X, 7, 1, 32)
self.relu1 = tf.nn.relu(self.conv1)
self.pool1 = max_pool(self.relu1, 3, 2)
print('conv1 layer: ' + str(self.pool1.get_shape()))
with tf.variable_scope('conv2'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.conv2 = conv2d(self.pool1, 5, 1, 64)
self.relu2 = tf.nn.relu(self.conv2)
self.pool2 = max_pool(self.relu2, 3, 2)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('conv2 layer: ' + str(self.pool2.get_shape()))
#############################################################################
# TODO: Flatten the output tensor from conv2 layer #
#############################################################################
self.flat = tf.contrib.layers.flatten(self.pool2)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('flat layer: ' + str(self.flat.get_shape()))
with tf.variable_scope('fc3'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.fc3 = fully_connected(self.flat, 384, None)
self.relu3 = tf.nn.relu(self.fc3)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('fc3 layer: ' + str(self.relu3.get_shape()))
with tf.variable_scope('fc4'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.fc4 = fully_connected(self.relu3, 10, None)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('fc4 layer: ' + str(self.fc4.get_shape()))
# Return the last layer
return self.fc4
def _input_ops(self):
# Placeholders
self.X = tf.placeholder(tf.float32, [None, 32, 32, 3])
self.Y = tf.placeholder(tf.int64, [None])
#############################################################################
# TODO: You can add any placeholders #
#############################################################################
self.is_train = tf.placeholder(tf.bool, name='is_train')
self.keep_prob = None
#############################################################################
# END OF YOUR CODE #
#############################################################################
def _build_optimizer(self):
# Adam optimizer 'self.train_op' that minimizes 'self.loss_op'
#############################################################################
# TODO: Complete the following functions #
#############################################################################
global_step = tf.Variable(0, trainable=False)
learning_decay_rate = tf.train.exponential_decay(learning_rate=5e-4,
global_step=global_step,
decay_steps=500,
decay_rate=0.96,
staircase=True
)
self.train_op = tf.train.AdamOptimizer(learning_decay_rate).minimize(self.loss_op, global_step=global_step)
#############################################################################
# END OF YOUR CODE #
#############################################################################
def _loss(self, labels, logits):
# Softmax cross entropy loss 'self.loss_op'
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
labels=labels, logits=logits))
#############################################################################
# END OF YOUR CODE #
#############################################################################
def _build_model(self):
# Define input variables
self._input_ops()
# Convert Y to one-hot vector
labels = tf.one_hot(self.Y, 10)
# Build a model and get logits
logits = self._model()
# Compute loss
self._loss(labels, logits)
# Build optimizer
self._build_optimizer()
# Compute accuracy
predict = tf.argmax(logits, 1)
correct = tf.equal(predict, self.Y)
self.accuracy_op = tf.reduce_mean(tf.cast(correct, tf.float32))
def train(self, sess, X_train, Y_train, X_val, Y_val):
sess.run(tf.global_variables_initializer())
step = 0
losses = []
accuracies = []
print('-' * 5 + ' Start training ' + '-' * 5)
for epoch in range(self.num_epoch):
print('train for epoch %d' % epoch)
for i in range(num_training // self.batch_size):
X_ = X_train[i * self.batch_size:(i + 1) * self.batch_size][:]
Y_ = Y_train[i * self.batch_size:(i + 1) * self.batch_size]
#############################################################################
# TODO: You can change feed data as you want #
#############################################################################
feed_dict = {self.X : X_, self.Y : Y_, self.is_train:True}
#############################################################################
# END OF YOUR CODE #
#############################################################################
fetches = [self.train_op, self.loss_op, self.accuracy_op]
_, loss, accuracy = sess.run(fetches, feed_dict=feed_dict)
losses.append(loss)
accuracies.append(accuracy)
if step % self.log_step == 0:
print('iteration (%d): loss = %.3f, accuracy = %.3f' %
(step, loss, accuracy))
step += 1
#############################################################################
# TODO: Plot training curves #
#############################################################################
# Graph 1. X: epoch, Y: training loss
plt.subplot(2, 1, 1)
plt.title('Training loss')
plt.xlabel('Iteration')
plt.plot(range(len(losses)), losses, label='loss')
# Graph 2. X: epoch, Y: training accuracy
plt.subplot(2, 1, 2)
plt.title('Training accuracy')
plt.xlabel('Epoch')
plt.plot(range(len(accuracies)), accuracies, label='accuracy')
plt.show()
#############################################################################
# END OF YOUR CODE #
#############################################################################
# Print validation results
print('validation for epoch %d' % epoch)
val_accuracy = self.evaluate(sess, X_val, Y_val)
print('- epoch %d: validation accuracy = %.3f' % (epoch, val_accuracy))
def evaluate(self, sess, X_eval, Y_eval):
eval_accuracy = 0.0
eval_iter = 0
for i in range(X_eval.shape[0] // self.batch_size):
X_ = X_eval[i * self.batch_size:(i + 1) * self.batch_size][:]
Y_ = Y_eval[i * self.batch_size:(i + 1) * self.batch_size]
#############################################################################
# TODO: You can change feed data as you want #
#############################################################################
feed_dict = {self.X : X_, self.Y : Y_, self.is_train:False}
#############################################################################
# END OF YOUR CODE #
#############################################################################
accuracy = sess.run(self.accuracy_op, feed_dict=feed_dict)
eval_accuracy += accuracy
eval_iter += 1
return eval_accuracy / eval_iter
In [60]:
# Clear old computation graphs
tf.reset_default_graph()
# Train our sample model
with tf.Session() as sess:
with tf.device('/cpu:0'):
model = BaseModel()
model.train(sess, X_train, Y_train, X_val, Y_val)
accuracy = model.evaluate(sess, X_test, Y_test)
print('***** test accuracy: %.3f' % accuracy)
saver = tf.train.Saver()
model_path = saver.save(sess, "lib/tf_models/problem2/csci-599_sample.ckpt")
print("Model saved in %s" % model_path)
Implement your own model.
You can modify the template code as you want and you can use GPU for fast training.
These are the techniques that you can try:
Your model should achieve >= 70% accuracy on the test set of CIFAR-10.
If the accuracy of the model reaches to 80% on the test set, you will get 5 extra points.
In [14]:
class YourModel(BaseModel):
def __init__(self):
super(YourModel, self).__init__()
self.num_epoch = 50
def _model(self):
print('-' * 5 + ' Your model ' + '-' * 5)
print('intput layer: ' + str(self.X.get_shape()))
with tf.variable_scope('conv1'):
self.conv1 = conv2d(self.X, 7, 1, 32)
self.relu1 = lrelu(self.conv1, 0.01)
self.norm1 = tf.nn.lrn(self.relu1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75,
name='norm1')
self.pool1 = max_pool(self.norm1, 3, 2)
print('conv1 layer: ' + str(self.pool1.get_shape()))
with tf.variable_scope('conv2'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.conv2 = conv2d(self.pool1, 5, 1, 64)
self.relu2 = lrelu(self.conv2, 0.01)
self.norm2 = tf.nn.lrn(self.relu2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75,
name='norm2')
self.pool2 = max_pool(self.relu2, 3, 2)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('conv2 layer: ' + str(self.pool2.get_shape()))
with tf.variable_scope('conv3'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.conv3 = conv2d(self.pool2, 3, 1, 32)
self.relu3 = lrelu(self.conv3, 0.01)
self.norm3 = tf.nn.lrn(self.relu3, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75,
name='norm3')
self.pool3 = max_pool(self.norm3, 3, 2)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('conv3 layer: ' + str(self.pool3.get_shape()))
#############################################################################
# TODO: Flatten the output tensor from conv2 layer #
#############################################################################
self.flat = tf.contrib.layers.flatten(self.pool3)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('flat layer: ' + str(self.flat.get_shape()))
with tf.variable_scope('fc3'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.fc3 = fully_connected(self.flat,384,None)
dropout_3 = tf.layers.dropout(inputs=self.fc3, rate=self.keep_prob,
training = self.is_train)
self.relu3 = tf.nn.relu(dropout_3)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('fc3 layer: ' + str(self.relu3.get_shape()))
with tf.variable_scope('fc4'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.fc4 = fully_connected(self.relu3, 192, None)
dropout_4 = tf.layers.dropout(inputs=self.fc4, rate=self.keep_prob,
training = self.is_train)
self.relu4 = tf.nn.relu(dropout_4)
#################################4###########################################
# END OF YOUR CODE #
#############################################################################
print('fc4 layer: ' + str(self.fc4.get_shape()))
with tf.variable_scope('fc5'):
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.fc5 = fully_connected(self.relu4, 10)
#############################################################################
# END OF YOUR CODE #
#############################################################################
print('fc4 layer: ' + str(self.fc5.get_shape()))
# Return the last layer
return self.fc5
def _input_ops(self):
# Placeholders
self.X = tf.placeholder(tf.float32, [None, 32, 32, 3])
self.Y = tf.placeholder(tf.int64, [None])
#############################################################################
# TODO: You can add any placeholders #
#############################################################################
self.is_train = tf.placeholder(tf.bool, name='is_train')
self.keep_prob = tf.placeholder(tf.float32)
#############################################################################
# END OF YOUR CODE #
#############################################################################
def _build_optimizer(self):
# Adam optimizer 'self.train_op' that minimizes 'self.loss_op'
#############################################################################
# TODO: Complete the following functions #
#############################################################################
global_step = tf.Variable(0, trainable=False)
learning_rate = tf.train.exponential_decay(5e-4, global_step, 1500, 0.96, staircase=True)
self.train_op = tf.train.AdamOptimizer(learning_rate).minimize(self.loss_op, global_step=global_step)
#############################################################################
# END OF YOUR CODE #
#############################################################################
def _loss(self, labels, logits):
# Softmax cross entropy loss 'self.loss_op'
#############################################################################
# TODO: Complete the following functions #
#############################################################################
self.loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
labels=labels, logits=logits)
)
#############################################################################
# END OF YOUR CODE #
#############################################################################
def _build_model(self):
# Define input variables
self._input_ops()
# Convert Y to one-hot vector
labels = tf.one_hot(self.Y, 10)
# Build a model and get logits
logits = self._model()
# Compute loss
self._loss(labels, logits)
# Build optimizer
self._build_optimizer()
# Compute accuracy
predict = tf.argmax(logits, 1)
correct = tf.equal(predict, self.Y)
self.accuracy_op = tf.reduce_mean(tf.cast(correct, tf.float32))
def train(self, sess, X_train, Y_train, X_val, Y_val):
sess.run(tf.global_variables_initializer())
step = 0
losses = []
accuracies = []
print('-' * 5 + ' Start training ' + '-' * 5)
for epoch in range(self.num_epoch):
print('train for epoch %d' % epoch)
for i in range(num_training // self.batch_size):
X_ = X_train[i * self.batch_size:(i + 1) * self.batch_size][:]
Y_ = Y_train[i * self.batch_size:(i + 1) * self.batch_size]
#############################################################################
# TODO: You can change feed data as you want #
#############################################################################
feed_dict = {self.X : X_, self.Y : Y_, self.is_train : True, self.keep_prob: 0.4}
#############################################################################
# END OF YOUR CODE #
#############################################################################
fetches = [self.train_op, self.loss_op, self.accuracy_op]
_, loss, accuracy = sess.run(fetches, feed_dict=feed_dict)
losses.append(loss)
accuracies.append(accuracy)
if step % self.log_step == 0:
print('iteration (%d): loss = %.3f, accuracy = %.3f' %
(step, loss, accuracy))
step += 1
#############################################################################
# TODO: Plot training curves #
#############################################################################
plt.plot(range(len(losses)), losses, label='loss')
# Graph 2. X: epoch, Y: training accuracy
plt.plot(range(len(accuracies)), accuracies, label='accuracy')
plt.xlabel('Epoch')
plt.ylabel('Loss/ Accuracy')
plt.title("Loss vs Accuracy")
plt.show()
#############################################################################
# END OF YOUR CODE #
#############################################################################
# Print validation results
print('validation for epoch %d' % epoch)
val_accuracy = self.evaluate(sess, X_val, Y_val)
print('- epoch %d: validation accuracy = %.3f' % (epoch, val_accuracy))
def evaluate(self, sess, X_eval, Y_eval):
eval_accuracy = 0.0
eval_iter = 0
for i in range(X_eval.shape[0] // self.batch_size):
X_ = X_eval[i * self.batch_size:(i + 1) * self.batch_size][:]
Y_ = Y_eval[i * self.batch_size:(i + 1) * self.batch_size]
#############################################################################
# TODO: You can change feed data as you want #
#############################################################################
feed_dict = {self.X : X_, self.Y : Y_, self.is_train : False, self.keep_prob: 1.0}
#############################################################################
# END OF YOUR CODE #
#############################################################################
accuracy = sess.run(self.accuracy_op, feed_dict=feed_dict)
eval_accuracy += accuracy
eval_iter += 1
return eval_accuracy / eval_iter
#############################################################################
# TODO: You can redefine BaseModel's methods #
#############################################################################
#############################################################################
# END OF YOUR CODE #
#############################################################################
In [15]:
# Clear old computation graphs
tf.reset_default_graph()
sess = tf.Session()
#############################################################################
# TODO: Preprocessing #
#############################################################################
mean_image = np.mean(X_train, axis=0)
X_train_ = X_train - mean_image
X_val_ = X_val - mean_image
X_test_ = X_test - mean_image
#############################################################################
# END OF YOUR CODE #
#############################################################################
model = YourModel()
model.train(sess, X_train_, Y_train, X_val_, Y_val)
accuracy = model.evaluate(sess, X_test_, Y_test)
print('***** test accuracy: %.3f' % accuracy)
# Save your model
saver = tf.train.Saver()
model_path = saver.save(sess, "lib/tf_models/problem2/csci-599_mine.ckpt")
print("Model saved in %s" % model_path)
sess.close()
In [16]:
tf.reset_default_graph()
# Load your model
model = YourModel()
sess = tf.Session()
saver = tf.train.Saver()
saver.restore(sess, "lib/tf_models/problem2/csci-599_mine.ckpt")
In [ ]: