Skip to content

flint-xf-fan/SDCND-Behavioral-Cloning

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Table of Contents


Behavioral Cloning

Check the two Videos Out!

This video shows how my model drives the car in autonomous mode in the precipitous road!

YouTube Video

And this is the additional challenge to ask the car to drive only on the left lane of the road.

YouTube Video


Goal

The goals / steps of this project are the following:

  • Use the simulator to collect data of good driving behavior
  • Build a convolution neural network in Keras that predicts steering angles from images
  • Train and validate the model using the driving data collected from simulator
  • Test that the model successfully drives around track one without leaving the road
  • Summarize the results with a written report

Files & Code Quality

Files

My project includes the following files:

  • model_track1.py containing the script to create and train the model
  • model_track2.py containing the script to create and train a new model for track2
  • drive.py for driving the car in autonomous mode
  • model_track1.h5 containing a trained convolution neural network model
  • model_track2.h5 containing a trained model with the same architecture, but trained on data from track 2
  • README.md summarizing the development process and results (you reading it!)
  • videos Please find the links to YouTube videos I recorded at the bottom of this README

Functional Code

Using the Udacity provided simulator and my drive.py file, the car can be driven autonomously around track 1 by executing

python drive.py model_track1.h5

and track 2

python drive.py model_track2.h5

Code readability

The model_track1.py & model_track2.py files contain the code for training and saving the convolution neural network model. The file shows the pipeline I used for training and validating the model, and it contains comments to explain how the code works.

Model Architecture

Architecture: NVIDIA End-to-End Deep Learning Network

My model is using the NVIDIA Architecture implemented in Keras.

[NVIDIA Architecture]

The model includes RELU layers to introduce nonlinearity, and the data is normalized in the model using a Keras lambda layer (code line 143 in model_track1.py).

Objective, Loss function, Learning rate

The objective is to build a regressor to predict the steering angle, so I use Mean Square Error as loss metric.

I use Adam as my optimizer since it is a proven good choice for many tasks. I used Keras' default setting for Adam optimizer so the learning rate was not tuned manually.

Overfitting Handling

The model contains dropout layers in order to reduce overfitting (lines 153, 162). I also tried max_pooling. However, it did not significantly improve the performance so I decided not to use pooling.

Data Preprocessing Strategy

Training data was chosen to keep the vehicle driving on the road. I keep driving in the center of the road as much as possible. And because I only used data from the car's front camera, I recorded data recovering from the left and right sides of the road to the center of the road. That said, I drive to the left and right sides of the road purposely but without recording it down, then I drive back to the center with recording on. This technique should help tell the model that the edges of the road are the areas it should definitely avoid. And it performs great. An alternative solution to this, should be using side cameras for training which is what I am gonna try out next.

Image Preprocessing

To capture good driving behavior, I first recorded two laps on track one using center lane driving. Here is an example image of center lane driving:

![alt text][image2]

I then recorded the vehicle recovering from the left side and right sides of the road back to center so that the vehicle would learn to avoid those edges as much as possible. These images show what a recovery looks like:

alt text

alt text

alt text

The same process was applied to track two's model as well.

Cropping

To fit the NVIDIA Architecture, I used Keras cropping2d layer to crop the input images.

text

This image is what my model is actually seeing:

text

Normalization

To be able to normalize the training data and the test data from simulator while in autonomous mode, I decided to add a Keras lambda layer into the structure.

Rotation

The default color scheme used by cv2.imread is BGR. However, the image supplied for test in the simulator will be RGB. So it makes sense to convert the color scheme from BGR back to RGB.

Image red by cv2

alt text

Rotated using image[:,:,::-1]

alt text

Augmentation

To augment the data sat, I also flipped images and angles thinking that this would double my data size and also make the model more generalised. For example, here is an image that has then been flipped:

Original image

alt text

Flipped image using np.fliplr(img)

alt text

Steering Angle Preprocessing

This analysis of labels (Steering Angles) distribution is quite important.

This is the histogram of steering angle data I collected from track1.

alt text

As the data is highly unbalanced, the model may tend to drive straight ahead for most of the time. Because the data is highly unbalanced, any small noise will confuse the model. So to make the model more robust, I decided to try to balance the data. For this data shown above, it's fairly simple, I just removed 95% of steering angle of zeros.

Histogram of the data after 90% of zeros been removed.

alt text

Final Model Architecture

____________________________________________________________________________________________________
Layer (type)                     Output Shape          Param #     Connected to                     
====================================================================================================
cropping2d_1 (Cropping2D)        (None, 66, 200, 3)    0           cropping2d_input_1[0][0]         
____________________________________________________________________________________________________
lambda_1 (Lambda)                (None, 66, 200, 3)    0           cropping2d_1[0][0]               
____________________________________________________________________________________________________
convolution2d_1 (Convolution2D)  (None, 31, 98, 24)    1824        lambda_1[0][0]                   
____________________________________________________________________________________________________
convolution2d_2 (Convolution2D)  (None, 14, 47, 36)    21636       convolution2d_1[0][0]            
____________________________________________________________________________________________________
dropout_1 (Dropout)              (None, 14, 47, 36)    0           convolution2d_2[0][0]            
____________________________________________________________________________________________________
convolution2d_3 (Convolution2D)  (None, 5, 22, 48)     43248       dropout_1[0][0]                  
____________________________________________________________________________________________________
convolution2d_4 (Convolution2D)  (None, 3, 20, 64)     27712       convolution2d_3[0][0]            
____________________________________________________________________________________________________
dropout_2 (Dropout)              (None, 3, 20, 64)     0           convolution2d_4[0][0]            
____________________________________________________________________________________________________
convolution2d_5 (Convolution2D)  (None, 1, 18, 64)     36928       dropout_2[0][0]                  
____________________________________________________________________________________________________
flatten_1 (Flatten)              (None, 1152)          0           convolution2d_5[0][0]            
____________________________________________________________________________________________________
dense_1 (Dense)                  (None, 1164)          1342092     flatten_1[0][0]                  
____________________________________________________________________________________________________
dense_2 (Dense)                  (None, 100)           116500      dense_1[0][0]                    
____________________________________________________________________________________________________
dense_3 (Dense)                  (None, 50)            5050        dense_2[0][0]                    
____________________________________________________________________________________________________
dense_4 (Dense)                  (None, 10)            510         dense_3[0][0]                    
____________________________________________________________________________________________________
dense_5 (Dense)                  (None, 1)             11          dense_4[0][0]                    
====================================================================================================
Total params: 1,595,511
Trainable params: 1,595,511
Non-trainable params: 0
____________________________________________________________________________________________________

Training Strategy

The model was trained and validated on different data sets to ensure that the model was not overfitting (code line 192). The model was tested by running it through the simulator and ensuring that the vehicle could stay on the track.

I randomly shuffled the data set and put 20% of the data into a validation set.

I used this training data for training the model. The validation set helped determine if the model was over or under fitting. The ideal number of epochs was 3-5 . I used an adam optimizer so that manually tuning the learning rate wasn't necessary.

Transfer Learning

The final step was to run the simulator to see how well the car was driving around track. There were a few spots where the vehicle fell off the track. To improve the driving behavior in these cases, I collected more data at those spots and used those new data to train my pretrained model. This made my new training really fast and aim to teach the model pay extra attention to those failure points.

At the end of the process, the vehicle is able to drive autonomously around the track without leaving the road.

Driving Test Log

Driving Test No.4 (completed second track):

text

Driving Test No.3 (completed first track):

text

The model is using NVIDIA Architecture. Trained on a relatively large set of (highly unbalanced) data. This test looks great and can be further improved.

Next step will try balance the data as much as possible and also try to use images from side cameras(The above tests are using front camera only).

Driving Test No.2:

text

Modified LeNet Trained on data mostly focusing on curves.

Driving Test No.1:

image1

Simple ConvNet Trained on a small set of data using a fairly simple model.

Next Challenge

Build one model trained using data from one track only to be able to complete both two tracks.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages