Convolutional Neural Networks for Behavioral Cloning – Udacity Self Driving Car Engineer Term 1 Project 3

In the last project we showed, by using python and tensorflow, that we can create a ConvNet to classify traffic signs with a relatively low error rate. What if we want to do something a little more complex, though? Say, something like replicate behaviors that a system should take given a set of inputs.

This is just the problem posed to students with the 3rd project in term 1 of the self driving car engineer nano degree series.

Regression vs Classification

In order to replicate a behavior, we are dealing with a regression problem, which is unlike our previous problem of classification. The main difference being that we are no longer concerned with our network outputs corresponding to a probability that something belongs to a class, in such case it is predicting a discrete class label, but rather, they predict a continuous quantity, such as throttle and steering angles.

If you read the previous post, you will remember that we used a softmax cross-entropy function to convert the outputs of our last layer to probabilities of something belonging to each of our classes. Instead, we will use a mean squared error function for our loss layer, which is then again fed into an adam optimizer.

Project Problem Statement

The goals of this project are the following:

  • Use the provided simulator to collect data of good driving behavior. This includes steering angle, camera imagery, throttle position and brake pressure.
  • Build a convolutional neural network in Keras that predicts steering angles from images.
  • Train and validate the model with a training and validation set.
  • Test that the model successfully drives around the track without leaving the road.

Write up and Results

The model constructed is basically the same as the Nvidia model shown below, with the exception of added dropout layers.

The model used includes ReLU activation layers to introduce nonlinearity, and the data is normalized using Keras’ lambda layer. Additionally, cropping was performed to help normalize images.

Attempts were made to use ELU activation functions, but those proved harder to train and performed worse than when using ReLUs.

In order to prevent overfitting dropout layers were incorporated. Additionally, the model was trained and validated on different data sets to prevent overfitting.

The model was trained using an Adam optimizer with a learning rate of 0.0001.

Training data was chosen that I thought would give the best probability of keeping the vehicle on the road. I used a combination of center lane driving, recovering from left and right side departures from the road, driving around a second track, and spending additional time connecting data from very sharp, “extreme” turns.

After collection of training data I wrote a python sript to normalize the distribution of angles that are fed into the training script. I divided the range of [-1.0 rad, 1.0 rad] into 21 bins and thresholded the number allowed in these bins to 1000. After a lot of data recording the training data distribution appeared as follows:

As is the case with many machine learning problems using neural networks, my goal was to use a previously existing model architecture and re-train it for my application.

My first handful of attempts at training a model indicated that overfitting was occurring as the training set showed a low mean squared error, but the validation MSE was quite high. To combat this I used dropout layers as indicated above.

After final construction of the model and testing with my own data set, the CNN still showed it was having a difficult time keeping the car on track. As with most neural network tasks, it seems that the distribution of the data set is more important than the actual format of the network. I therefore created a script to bin the steering angles into 21 bins and threshold the acceptable number of items in each bin to 1000. After quite a bit of data collection and binning I was able to have 21 bins of nearly 1000 items each, which produced a relatively flat distribution. With this new data set of nearly uniform distribution the trained model seemed to perform quite well and kept the car on track.

The mean squared error loss during training can be seen below:

Keras Implementation of the Nvidia CNN Model

def nvidia():

	shape = (160,320,3)
	model = Sequential()
	model.add(Lambda(lambda x: x / 255.0 - 0.5, input_shape = shape))
	model.add(Cropping2D(cropping = ((50,20),(0,0))))
	model.add(Convolution2D(24,5,5, subsample=(2,2), activation = 'relu'))
	model.add(Convolution2D(36,5,5, subsample=(2,2), activation = 'relu'))
	model.add(Convolution2D(48,5,5, subsample=(2,2), activation = 'relu'))
	model.add(Convolution2D(64,3,3, activation = 'relu'))
	model.add(Convolution2D(64,3,3, activation = 'relu'))
	model.add(Dropout(0.5))
	model.add(Flatten())
	model.add(Dense(100))
	model.add(Dropout(0.5))
	model.add(Dense(50))
	model.add(Dense(10))
	model.add(Dense(1))

	return model

Leave a Reply

Your email address will not be published. Required fields are marked *