In [ ]:
from urllib.request import urlretrieve
from os.path import isfile, isdir
from tqdm import tqdm
import problem_unittests as tests
import tarfile

cifar10_dataset_folder_path = 'cifar-10-batches-py'

Check Point

This is your first checkpoint. If you ever decide to come back to this notebook or have to restart the notebook, you can start from here. The preprocessed data has been saved to disk.


In [ ]:
"""
DON'T MODIFY ANYTHING IN THIS CELL
"""
import pickle
import problem_unittests as tests
import helper

# Load the Preprocessed Validation data
valid_features, valid_labels = pickle.load(open('preprocess_validation.p', mode='rb'))

In [ ]:
import tensorflow as tf

def neural_net_image_input(image_shape):
    """
    Return a Tensor for a batch of image input
    : image_shape: Shape of the images
    : return: Tensor for image input.
    """
    # TODO: Implement Function
    shape = list(image_shape)
    shape.insert (0, None)
    return tf.placeholder (tf.float32, shape=shape, name='x')


def neural_net_label_input(n_classes):
    """
    Return a Tensor for a batch of label input
    : n_classes: Number of classes
    : return: Tensor for label input.
    """
    # TODO: Implement Function
    return tf.placeholder (tf.float32, shape=[None, n_classes], name='y')


def neural_net_keep_prob_input():
    """
    Return a Tensor for keep probability
    : return: Tensor for keep probability.
    """
    # TODO: Implement Function
    return tf.placeholder (tf.float32, name='keep_prob')


"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""
tf.reset_default_graph()
tests.test_nn_image_inputs(neural_net_image_input)
tests.test_nn_label_inputs(neural_net_label_input)
tests.test_nn_keep_prob_inputs(neural_net_keep_prob_input)

In [ ]:
def conv2d_maxpool(x_tensor, conv_num_outputs, conv_ksize, conv_strides, pool_ksize, pool_strides):
    """
    Apply convolution then max pooling to x_tensor
    :param x_tensor: TensorFlow Tensor
    :param conv_num_outputs: Number of outputs for the convolutional layer
    :param conv_ksize: kernal size 2-D Tuple for the convolutional layer
    :param conv_strides: Stride 2-D Tuple for convolution
    :param pool_ksize: kernal size 2-D Tuple for pool
    :param pool_strides: Stride 2-D Tuple for pool
    : return: A tensor that represents convolution and max pooling of x_tensor
    """
    # TODO: Implement Function
    input_shape = [conv_ksize[0], conv_ksize[1], x_tensor.get_shape().as_list()[3], conv_num_outputs]
    weights = tf.Variable (tf.truncated_normal (input_shape, mean=0.0, stddev=0.10, dtype=tf.float32))
    biases  = tf.Variable (tf.zeros (conv_num_outputs, dtype=tf.float32))
    strides = [1, conv_strides[0], conv_strides[1], 1]
    
    conv = tf.nn.conv2d (x_tensor, weights, strides=strides, padding='SAME')
    conv = tf.nn.bias_add (conv, biases)
    conv = tf.nn.relu (conv)
    
    ksize = [1, pool_ksize[0], pool_ksize[1], 1]
    strides = [1, pool_strides[0], pool_strides[1], 1]
    maxpool = tf.nn.max_pool (conv, ksize=ksize, strides=strides, padding='SAME')
    return maxpool 


"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""
tests.test_con_pool(conv2d_maxpool)

In [ ]:
import operator
import functools

def flatten(x_tensor):
    """
    Flatten x_tensor to (Batch Size, Flattened Image Size)
    : x_tensor: A tensor of size (Batch Size, ...), where ... are the image dimensions.
    : return: A tensor of size (Batch Size, Flattened Image Size).
    """
    # TODO: Implement Function
    image_size = functools.reduce(operator.mul, x_tensor.get_shape().as_list()[1:], 1)
    return tf.reshape (x_tensor, [-1, image_size])


"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""
tests.test_flatten(flatten)

In [ ]:
def fully_conn(x_tensor, num_outputs):
    """
    Apply a fully connected layer to x_tensor using weight and bias
    : x_tensor: A 2-D tensor where the first dimension is batch size.
    : num_outputs: The number of output that the new tensor should be.
    : return: A 2-D tensor where the second dimension is num_outputs.
    """
    # TODO: Implement Function
    weights = tf.Variable (tf.truncated_normal ([x_tensor.get_shape().as_list()[1], num_outputs], mean=0.0, stddev=0.10, dtype=tf.float32))
    biases  = tf.Variable (tf.zeros (num_outputs, dtype=tf.float32))
    activations = tf.add (tf.matmul (x_tensor, weights), biases)
    return tf.nn.relu (activations)

"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""
tests.test_fully_conn(fully_conn)

In [ ]:
def output(x_tensor, num_outputs):
    """
    Apply a output layer to x_tensor using weight and bias
    : x_tensor: A 2-D tensor where the first dimension is batch size.
    : num_outputs: The number of output that the new tensor should be.
    : return: A 2-D tensor where the second dimension is num_outputs.
    """
    # TODO: Implement Function
    weights = tf.Variable (tf.truncated_normal ([x_tensor.get_shape().as_list()[1], num_outputs], mean=0.0, stddev=0.10, dtype=tf.float32))
    biases  = tf.Variable (tf.zeros (num_outputs, dtype=tf.float32))
    return tf.add (tf.matmul (x_tensor, weights), biases)


"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""
tests.test_output(output)

In [ ]:
def conv_net(x, keep_prob):
    """
    Create a convolutional neural network model
    : x: Placeholder tensor that holds image data.
    : keep_prob: Placeholder tensor that hold dropout keep probability.
    : return: Tensor that represents logits
    """
    # TODO: Apply 1, 2, or 3 Convolution and Max Pool layers
    conv1 = conv2d_maxpool (x, conv_num_outputs=64, conv_ksize=(8,8), conv_strides=(2,2), pool_ksize=(2,2), pool_strides=(2,2))
    conv2 = conv2d_maxpool (conv1, conv_num_outputs=128, conv_ksize=(6,6), conv_strides=(2,2), pool_ksize=(2,2), pool_strides=(2,2))

    flat = flatten (conv2)
    
    conn1 = fully_conn (flat, 2048)
    conn1 = tf.nn.dropout (conn1, keep_prob)
    conn2 = fully_conn (conn1, 1024)
    conn2 = tf.nn.dropout (conn2, keep_prob)
    
    out = output (conn2, 10)
    return out


"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""

##############################
## Build the Neural Network ##
##############################

# Remove previous weights, bias, inputs, etc..
tf.reset_default_graph()

# Inputs
x = neural_net_image_input((32, 32, 3))
y = neural_net_label_input(10)
keep_prob = neural_net_keep_prob_input()

# Model
logits = conv_net(x, keep_prob)

# Name logits Tensor, so that is can be loaded from disk after training
logits = tf.identity(logits, name='logits')

# Loss and Optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))
optimizer = tf.train.AdamOptimizer().minimize(cost)

# Accuracy
correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32), name='accuracy')

tests.test_conv_net(conv_net)

In [ ]:
def train_neural_network(session, optimizer, keep_probability, feature_batch, label_batch):
    """
    Optimize the session on a batch of images and labels
    : session: Current TensorFlow session
    : optimizer: TensorFlow optimizer function
    : keep_probability: keep probability
    : feature_batch: Batch of Numpy image data
    : label_batch: Batch of Numpy label data
    """
    # TODO: Implement Function
    session.run (optimizer, feed_dict={x:feature_batch, y:label_batch, keep_prob:keep_probability})


"""
DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE
"""
tests.test_train_nn(train_neural_network)

In [ ]:
def print_stats(session, feature_batch, label_batch, cost, accuracy):
    """
    Print information about loss and validation accuracy
    : session: Current TensorFlow session
    : feature_batch: Batch of Numpy image data
    : label_batch: Batch of Numpy label data
    : cost: TensorFlow cost function
    : accuracy: TensorFlow accuracy function
    """
    # TODO: Implement Function
    loss = session.run (cost, feed_dict={x:feature_batch, y:label_batch, keep_prob:1.0})
    valid_acc = session.run (accuracy, feed_dict={x:valid_features, y:valid_labels, keep_prob:1.0})
    print ('Loss = {:8.6f}, Validation Accuracy = {:.4f}'.format (loss, valid_acc))

In [ ]:
# TODO: Tune Parameters
epochs = 20
batch_size = 128
keep_probability = 0.75

Fully Train the Model

Now that you got a good accuracy with a single CIFAR-10 batch, try it with all five batches.


In [ ]:
"""
DON'T MODIFY ANYTHING IN THIS CELL
"""
save_model_path = './image_classification'

print('Training...')
with tf.Session() as sess:
    print ("Initializing the variables")
    sess.run(tf.global_variables_initializer())
    
    # Training cycle
    for epoch in range(epochs):
        # Loop over all batches
        n_batches = 5
        for batch_i in range(1, n_batches + 1):
            for batch_features, batch_labels in helper.load_preprocess_training_batch(batch_i, batch_size):
                train_neural_network(sess, optimizer, keep_probability, batch_features, batch_labels)
            print('Epoch {:>2}, CIFAR-10 Batch {}:  '.format(epoch + 1, batch_i), end='')
            print_stats(sess, batch_features, batch_labels, cost, accuracy)
            
        if (epoch + 1) % 100 == 0:
            # Save Model
            print ("Save model...")
            saver = tf.train.Saver()
            save_path = saver.save(sess, save_model_path + '-' + str(epoch + 1))                
            
    # Save Model
    saver = tf.train.Saver()
    save_path = saver.save(sess, save_model_path + '-' + str(epoch + 1))