In [1]:
# Visualisation parameters
display_output = 1
train_verbose_style = 2 # 1 every training image, 2 once very epoch
# Training parameters
use_generator = 0
epoch_num = 30
train_model = 1
In [2]:
import glob
import numpy as np
from sklearn.model_selection import train_test_split
cars = glob.glob("./dataset/vehicles/*/*.png")
non_cars = glob.glob("./dataset/non-vehicles/*/*.png")
# feature list
X = []
# Append cars and non-cars image file paths to the feature list
for car in cars:
X.append(car)
for non_car in non_cars:
X.append(non_car)
X = np.array(X)
# Generate y Vector (Cars = 1, Non-Cars = -1)
y = np.concatenate([np.ones(len(cars)), np.zeros(len(non_cars))-1])
# Randomly split the file paths in a validation set and a training set
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.1)
print("Loading done!")
In [3]:
import matplotlib.image as mpimg
%matplotlib inline
if display_output == 1:
# Load the 1rst image to get its size
train_img = mpimg.imread(X_train[0])
# Dataset image shape
image_shape = train_img.shape
# Number of unique classes/labels there are in the dataset.
n_classes = np.unique(y_train).size
print("Number of training examples =", X_train.shape[0])
print("Number of validation examples =", X_valid.shape[0])
print("Image data shape =", image_shape)
print("Number of classes =", n_classes)
In [4]:
import matplotlib.pyplot as plt
import random
def show_dataset_classes_histogram(labels_train, labels_valid):
f, ax = plt.subplots(figsize=(5, 5))
# Generate histogram and bins
hist_train, bins = np.histogram(labels_train, 2)
hist_valid, bins = np.histogram(labels_valid, 2)
# Bar width
width = 1.0 * (bins[1] - bins[0])
ax.bar([-1, 1], hist_train, width=width, label="Train")
ax.bar([-1, 1], hist_valid, width=width, label="Valid")
ax.set_xlabel('Classes')
ax.set_ylabel('Number of occurence')
ax.set_title('Histogram of the data set')
ax.legend(bbox_to_anchor=(1.01, 1), loc="upper left")
f.tight_layout()
plt.savefig("./output_images/histogram_dataset.png")
def show_sample(features, labels, preprocess=0, sample_num=1, sample_index=-1):
col_num = 2
# Create training sample + histogram plot
f, axarr = plt.subplots(sample_num, col_num, figsize=(col_num * 4, sample_num * 3))
index = sample_index - 1
for i in range(0, sample_num, 1):
if sample_index == -1:
index = random.randint(0, len(features))
else:
index = index + 1
if labels[index] == 1:
label_str = "Car"
else:
label_str = "Non-Car"
image = (mpimg.imread(features[index]) * 255).astype(np.uint8)
if preprocess == 1:
image = image_preprocessing(image)
axarr[i, 0].set_title('%s' % label_str)
axarr[i, 0].imshow(image)
hist, bins = np.histogram(image.flatten(), 256, [0, 256])
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()
axarr[i, 1].plot(cdf_normalized, color='b')
axarr[i, 1].plot(hist, color='r')
axarr[i, 1].legend(('cdf', 'histogram'), loc='upper left')
axarr[i, 0].axis('off')
# Tweak spacing to prevent clipping of title labels
f.tight_layout()
if preprocess == 1:
plt.savefig("./output_images/dataset_sample_preprocessed.png")
else:
plt.savefig("./output_images/dataset_sample.png")
if display_output == 1:
show_dataset_classes_histogram(y_train, y_valid)
show_sample(X_train, y_train, sample_num=6, sample_index=110)
As we have seen in the "intro to convolutionnal network" lesson, a nice property of a convolutional filter is that is reuses the weights gwhile slidding through the image and feature maps, the weight number is thus not dependent on the input image size. Therefore, it is possible to train a full ConvNet to classify small size images (64x64) as an image classifier (like we have done for Project 2) and output the result on one neuron.
In our case the output will be either there is a car in the image or not (tanh=1 or tanh=-1). The weights resulting from the training can then be reused on the same full ConvNet to build an output feature map from larger images. This feature map can be seen as a heatmap in which each pixel represents the output of the original trained ConvNet for a section of the input image. These pixels thus give the "car probability" for a specific location in the input image.
This cell:
In [5]:
from model import get_model
from keras.layers import Flatten
# Get the "base" ConvNet Model
model = get_model()
# Flat out the last layer for training
model.add(Flatten())
# Print out model summary
if display_output == 1:
model.summary()
In [6]:
from sklearn.utils import shuffle
def keras_generator(features, labels, batch_size=32):
num_features = len(features)
# Loop forever so the generator never terminates
while 1:
# shuffles the input sample
shuffle(features, labels)
for offset in range(0, num_features, batch_size):
# File path subset
batch_features = features[offset:offset + batch_size]
batch_labels = labels[offset:offset + batch_size]
imgs = []
for feature in batch_features:
image = (mpimg.imread(feature) * 255).astype(np.uint8)
# Image preprocessing
# none..
imgs.append(image)
# Convert images to numpy arrays
X = np.array(imgs, dtype=np.uint8)
y = np.array(batch_labels)
yield shuffle(X, y)
def loader(features, labels):
for iterable in keras_generator(features, labels, batch_size=len(features)):
return iterable
# Prepare generator functions /dataset
if use_generator == 1:
# Use the generator function
train_generator = keras_generator(X_train, y_train, batch_size=32)
validation_generator = keras_generator(X_valid, y_valid, batch_size=32)
else:
# Load all the preprocessed images in memory
train_set = loader(X_train, y_train)
validation_set = loader(X_valid, y_valid)
This cell:
plot_train_result())
In [7]:
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adam
def plot_train_results(history_object):
f, ax = plt.subplots(figsize=(10, 5))
ax.plot(history_object.history['acc'])
ax.plot(history_object.history['val_acc'])
ax.set_ylabel('Model accuracy')
ax.set_xlabel('Epoch')
ax.set_title('Model accuracy vs epochs')
plt.legend(['training accuracy', 'validation accuracy'], bbox_to_anchor=(1.01, 1.0))
f.tight_layout()
plt.savefig("./output_images/accuracy_over_epochs.png")
if train_model == 1:
# Compile the model using an Adam optimizer
model.compile(optimizer=Adam(), loss='mse', metrics=['accuracy'])
# saves the model weights after each epoch if the validation loss decreased
filepath = './weights/best-weights.hdf5'
checkpointer = ModelCheckpoint(filepath=filepath,
monitor='val_loss',
verbose=1,
save_best_only=True,
mode='min')
# Train the model, with or without a generator
if use_generator == 1:
history_object = model.fit_generator(train_generator,
steps_per_epoch=len(X_train),
epochs=epoch_num,
verbose=train_verbose_style,
callbacks=[checkpointer],
validation_data=validation_generator,
validation_steps=len(X_valid))
else:
history_object = model.fit(train_set[0],
train_set[1],
batch_size=64,
epochs=epoch_num,
verbose=train_verbose_style,
callbacks=[checkpointer],
validation_data=(validation_set[0], validation_set[1]))
if display_output == 1:
plot_train_results(history_object)
In [8]:
# Load the weight
model.load_weights('./weights/best-weights.hdf5')
print("Weights loaded!")
This cell:
In [9]:
if display_output == 1:
import matplotlib.pyplot as plt
%matplotlib inline
import time
import numpy as np
sample_num = 12
col_num = 4
row_num = int(sample_num/col_num)
# Create training sample + histogram plot
f, axarr = plt.subplots(row_num, col_num, figsize=(col_num * 4, row_num * 3))
for i in range(sample_num):
# Pick a random image from the validation set
index = np.random.randint(validation_set[0].shape[0])
# Add one dimension to the image to fit the CNN input shape...
sample = np.reshape(validation_set[0][index], (1, 64,64,3))
# Record starting time
start_time = time.time()
# Infer the label
inference = model.predict(sample, batch_size=64, verbose=0)
# Print time difference...
print("Image %2d inference time : %.4f s" % (i, time.time() - start_time))
# Extract inference value
inference = inference[0][0]
# Show the image
color_str = 'green'
if inference >= 0.0:
title_str = "Car: {:4.2f}" .format(inference)
if validation_set[1][index] != 1:
color_str = 'red'
else:
title_str = "No Car: {:4.2f}" .format(inference)
if validation_set[1][index] != -1:
color_str = 'red'
axarr[int(i/col_num), i % col_num].imshow(validation_set[0][index])
axarr[int(i/col_num), i % col_num].set_title(title_str, color = color_str)
axarr[int(i/col_num), i % col_num].axis('off')
f.tight_layout()
plt.savefig("./output_images/inference.png")
In [ ]: