In [1]:
# Imports
import pickle
import tensorflow as tf
from sklearn.utils import shuffle
import os.path
import numpy as np
In [2]:
# Load data augmented training data
with open('./train_data/aug_train_features_ready2.pickle', mode='rb') as f:
X_train = pickle.load(f)
with open('./train_data/aug_train_labels_ready2.pickle', mode='rb') as f:
y_train = pickle.load(f)
with open('./train_data/aug_valid_features_ready2.pickle', mode='rb') as f:
X_valid = pickle.load(f)
with open('./train_data/aug_valid_labels_ready2.pickle', mode='rb') as f:
y_valid = pickle.load(f)
with open('./train_data/aug_test_features_ready2.pickle', mode='rb') as f:
X_test = pickle.load(f)
with open('./train_data/aug_test_labels_ready2.pickle', mode='rb') as f:
y_test = pickle.load(f)
In [3]:
# Check dimensions
assert (len(X_train) == len(y_train))
assert (len(X_valid) == len(y_valid))
assert (len(X_test) == len(y_test))
In [4]:
# Shuffle everything
X_train, y_train = shuffle(X_train, y_train)
In [5]:
def convnet(x_input):
# Parameters used for tf.truncated_normal
mu = 0
sigma = 0.1
# Layer 1: Convolutional. Input = 32x32x1. Output = 28x28x6.
with tf.name_scope("conv1"):
conv1_W = tf.Variable(tf.truncated_normal(shape=(5, 5, 1, 6), mean=mu, stddev=sigma), name='Weights')
conv1_b = tf.Variable(tf.constant(0.1, shape=[6]), name='Bias')
conv1_2d = tf.nn.conv2d(x_input, conv1_W, strides=[1, 1, 1, 1], padding='VALID') + conv1_b
act1 = tf.nn.tanh(conv1_2d)
conv1 = tf.nn.max_pool(act1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID',name="conv1")
tf.summary.histogram("weights", conv1_W)
tf.summary.histogram("biases", conv1_b)
tf.summary.histogram("activations", act1)
# Layer 2: Convolutional. Output = 10x10x16.
with tf.name_scope("conv2"):
conv2_W = tf.Variable(tf.truncated_normal(shape=(5, 5, 6, 16), mean=mu, stddev=sigma), name='Weights')
conv2_b = tf.Variable(tf.constant(0.1, shape=[16]), name='Bias')
conv2_2d = tf.nn.conv2d(conv1, conv2_W, strides=[1, 1, 1, 1], padding='VALID') + conv2_b
act2 = tf.nn.tanh(conv2_2d)
conv2 = tf.nn.max_pool(act2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
tf.summary.histogram("weights", conv2_W)
tf.summary.histogram("biases", conv2_b)
tf.summary.histogram("activations", act2)
# Flatten. Input = 10x10x16. Output = 400.
with tf.name_scope("flat"):
fc0 = tf.contrib.layers.flatten(conv2)
# Layer 3: Fully Connected. Input = 400. Output = 120.
with tf.name_scope("fc1"):
fc1_W = tf.Variable(tf.truncated_normal(shape=(400, 120), mean=mu, stddev=sigma, name='Weights'))
fc1_b = tf.Variable(tf.constant(0.1, shape=[120]), name='Bias')
fc1_1 = tf.matmul(fc0, fc1_W) + fc1_b
fc1 = tf.nn.tanh(fc1_1)
tf.summary.histogram("weights", fc1_W)
tf.summary.histogram("biases", fc1_b)
tf.summary.histogram("activations", fc1)
with tf.name_scope("Dropout1"):
fcd1 = tf.nn.dropout(fc1, keep_prob, name='Dropout1')
# Layer 4: Fully Connected. Input = 120. Output = 84.
with tf.name_scope("fc2"):
fc2_W = tf.Variable(tf.truncated_normal(shape=(120, 84), mean=mu, stddev=sigma, name="W"))
fc2_b = tf.Variable(tf.constant(0.1, shape=[84]), name='Bias')
fc2_1 = tf.matmul(fcd1, fc2_W) + fc2_b
fc2 = tf.nn.tanh(fc2_1)
tf.summary.histogram("weights", fc2_W)
tf.summary.histogram("biases", fc2_b)
tf.summary.histogram("activations", fc2)
with tf.name_scope("Dropout2"):
fcd2 = tf.nn.dropout(fc2, keep_prob, name='Dropout2')
# Layer 5: Fully Connected. Input = 84. Output = 43.
with tf.name_scope("fc3"):
fc3_W = tf.Variable(tf.truncated_normal(shape=(84, 43), mean=mu, stddev=sigma, name='Weights'))
fc3_b = tf.Variable(tf.constant(0.1, shape=[43]), name='Bias')
sign_class = tf.matmul(fcd2, fc3_W, name="fc3") + fc3_b
tf.summary.histogram("weights", fc3_W)
tf.summary.histogram("biases", fc3_b)
tf.summary.histogram("activations", sign_class)
return sign_class
In [6]:
# Global parameters
LOGDIR = "./support/tensorboard_logs/"
EPOCHS = 100
BATCH_SIZE = 128
rate = 0.0005
In [7]:
with tf.name_scope('Input'):
x = tf.placeholder(tf.float32, (None, 32, 32, 1), name='InputData')
y = tf.placeholder(tf.int32, (None), name='LabelData')
keep_prob = tf.placeholder(tf.float32)
tf.summary.image('input', x, 3)
one_hot_y = tf.one_hot(y, 43)
In [8]:
# Call CNN
logits = convnet(x)
In [9]:
# xent or cost function
with tf.name_scope("xent"):
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=one_hot_y, logits=logits)
loss_operation = tf.reduce_mean(cross_entropy, name="xent")
tf.summary.scalar("xent", loss_operation)
In [10]:
with tf.name_scope("train"):
optimizer = tf.train.AdamOptimizer(learning_rate = rate)
training_operation = optimizer.minimize(loss_operation)
In [11]:
with tf.name_scope("accuracy"):
correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(one_hot_y, 1))
accuracy_operation = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.summary.scalar("accuracy", accuracy_operation)
In [12]:
def evaluate(X_data, y_data):
num_examples = len(X_data)
total_accuracy = 0
total_loss = 0
sess = tf.get_default_session()
for offset in range(0, num_examples, BATCH_SIZE):
batch_x, batch_y = X_data[offset:offset + BATCH_SIZE], y_data[offset:offset + BATCH_SIZE]
loss, accuracy = sess.run([loss_operation, accuracy_operation], feed_dict={x: batch_x, y: batch_y, keep_prob: 1.0})
total_accuracy += (accuracy * len(batch_x))
total_loss += (loss * len(batch_x))
return total_loss/num_examples, total_accuracy/num_examples
In [13]:
merged_summary = tf.summary.merge_all()
saver = tf.train.Saver()
In [14]:
with tf.Session() as sess:
# variables need to be initialized before we can use them
sess.run(tf.global_variables_initializer())
writer = tf.summary.FileWriter(LOGDIR)
writer.add_graph(sess.graph)
num_examples = len(X_train)
# perform training cycles
print("Training...")
print()
for i in range(EPOCHS):
X_train, y_train = shuffle(X_train, y_train)
for offset in range(0, num_examples, BATCH_SIZE):
end = offset + BATCH_SIZE
batch_x, batch_y = X_train[offset:end], y_train[offset:end]
summary = sess.run(training_operation, feed_dict={x: batch_x, y: batch_y, keep_prob: 0.5})
[validation_loss, validation_accuracy] = evaluate(X_valid, y_valid)
summary, acc = sess.run([merged_summary, accuracy_operation], feed_dict={x: batch_x, y: batch_y, keep_prob: 1.0})
writer.add_summary(summary, i) # Write summary
saver.save(sess, os.path.join(LOGDIR, "model.ckpt"), i)
print("EPOCH {} ...".format(i + 1))
print("Validation Accuracy = {:.3f}".format(validation_accuracy))
#print("Validation Loss = {:.3f}".format(validation_loss))
print()
with tf.name_scope("accuracy"):
[test_loss, test_accuracy] = evaluate(X_test, y_test)
print("Test Accuracy = {:.3f}".format(test_accuracy))
print("Test Loss = {:.3f}".format(test_loss))
saver = tf.train.Saver()
saver.save(sess, './model/train.data')
print("Model saved!")
In [15]:
# Load dataset of 5 internet images
with open('./test_data/test_img_features.pickle', mode='rb') as f:
X_custom = pickle.load(f)
with open('./test_data/test_img_labels.pickle', mode='rb') as f:
y_custom = pickle.load(f)
In [16]:
with tf.Session() as sess:
loader = tf.train.import_meta_graph('./model/train.data.meta')
loader.restore(sess, tf.train.latest_checkpoint('./model/'))
[test_loss, test_accuracy] = evaluate(X_custom, y_custom)
print("Test Images Accuracy = {:.3f}".format(test_accuracy))
#print("Test Images Loss = {:.3f}".format(test_loss))
print()
softmax = sess.run(tf.nn.softmax(logits), feed_dict={x: X_custom, y: y_custom, keep_prob: 1.0})
result = sess.run(tf.nn.top_k(softmax, k=5))
np.set_printoptions(precision=2, suppress=True)
print("Softmax probablities:")
print(result.values)
print()
print("Predicted indices:")
print(result.indices)
print()
print("Labels of test images:")
print(y_custom)
An observation: I just realized, that the sign Turn right is not on the list of classes. So, the network classified it as a No entry, which is very close, despite of different colour. An RGB neural network would not do this kind of prediction, but this grayscale one does.