Introduction

In this notebook, I want to continue working with the model form the experiment 1. The model was able to learn the steering angles for the three hand-picked images but the question is can it learn to actually steer the car in the simulator's autonomous mode. Given the discussion about recovery in the project material, it is unlikely that the provided sample training data is enough to teach the model to drive, but doing a test with that data would give at least a baseline to work from.

Here is the overall plan

  1. Recreate the model from experiment 1
  2. Create training data using the provided sample data
  3. Train the model using the whole training data and see if it any learning takes place
  4. If needed, tweak the model to get better training performance
  5. Test the model with the simulator to see how it performs

Here are some utility functions.


In [1]:
import os
from PIL import Image

def get_record_and_image(index):
    record = df.iloc[index]
    path = os.path.join('data', record.center)
    return record, Image.open(path)

def layer_info(model):
    for n, layer in enumerate(model.layers, 1):
        print('Layer {:2} {:16} input shape {} output shape {}'.format(n, layer.name, layer.input_shape, layer.output_shape))

Step 1: Recreate the model from experiment 1

This is an exact copy of the model from experiment 1 with one difference: the input image size is halved, because the images will be downscaled this time. The reason for the downscaling is explained in Step 2.


In [2]:
from keras.models import Sequential
from keras.layers.core import Dense, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D

model = Sequential()
model.add(Convolution2D(6, 5, 5, border_mode='valid', subsample=(5, 5), input_shape=(80, 160, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(16, 5, 5, border_mode='valid', subsample=(2, 2)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(120))
model.add(Activation('relu'))
model.add(Dense(84))
model.add(Activation('relu'))
model.add(Dense(1))
model.add(Activation('tanh'))

layer_info(model)


Using TensorFlow backend.
Layer  1 convolution2d_1  input shape (None, 80, 160, 3) output shape (None, 16, 32, 6)
Layer  2 activation_1     input shape (None, 16, 32, 6) output shape (None, 16, 32, 6)
Layer  3 maxpooling2d_1   input shape (None, 16, 32, 6) output shape (None, 8, 16, 6)
Layer  4 convolution2d_2  input shape (None, 8, 16, 6) output shape (None, 2, 6, 16)
Layer  5 activation_2     input shape (None, 2, 6, 16) output shape (None, 2, 6, 16)
Layer  6 maxpooling2d_2   input shape (None, 2, 6, 16) output shape (None, 1, 3, 16)
Layer  7 flatten_1        input shape (None, 1, 3, 16) output shape (None, 48)
Layer  8 dense_1          input shape (None, 48) output shape (None, 120)
Layer  9 activation_3     input shape (None, 120) output shape (None, 120)
Layer 10 dense_2          input shape (None, 120) output shape (None, 84)
Layer 11 activation_4     input shape (None, 84) output shape (None, 84)
Layer 12 dense_3          input shape (None, 84) output shape (None, 1)
Layer 13 activation_5     input shape (None, 1) output shape (None, 1)

Step 2: Create training set


In [3]:
import numpy as np
import pandas as pd

df = pd.read_csv('data/driving_log.csv')

Now I need to create the actual training data, X_train and y_train. I will just read all the images and store them as NumPy arrays to X_train. Similary, I read the corresponding steering angles and store them to y_train.

Note: I ended up scaling the images down to half size to conserve memory and speed up training. This was also mentioned in the project cheat sheet (https://carnd-forums.udacity.com/questions/26214464/behavioral-cloning-cheatsheet).


In [4]:
from tqdm import tqdm

X_train = []
y_train = []
for i in tqdm(range(len(df))):
    record, image = get_record_and_image(i)
    image = image.resize((image.width // 2, image.height // 2))
    X_train.append(np.array(image))
    image.close()
    y_train.append(record['steering'])


100%|██████████| 8036/8036 [00:12<00:00, 638.86it/s]

Some preprocessing: normalize the images and convert the y_train to a NumPy array because that is what the Keras fit() seems to want. This step takes some time and consumes also a lot of memory; downscaling the images above helps.


In [59]:
X_min = np.min(X_train)
X_max = np.max(X_train)
X_normalized = (X_train - X_min) / (X_max - X_min) - 0.5
y_train = np.array(y_train)

Step 3: Train the model

Here I use all the data from the sample training data, 8036 images and their steering angles. Instead of using the training data generator as in the experiment 1, I just give the whole training set to model.fit and let it split it to training and validation sets. After training, I save the model so it can be loaded to the simulator for testing if the training seems to proceed well.


In [30]:
import keras.optimizers

def train(model, nb_epoch=10, learning_rate=0.001):
    adam = keras.optimizers.Adam(lr=learning_rate)
    model.compile(loss='mse', optimizer=adam)
    model.fit(X_normalized, y_train, validation_split=0.2, nb_epoch=nb_epoch, verbose=2)
    model.save('model.h5')

In [8]:
train(model)


Train on 6428 samples, validate on 1608 samples
Epoch 1/10
6s - loss: 0.0124 - val_loss: 0.0114
Epoch 2/10
2s - loss: 0.0099 - val_loss: 0.0113
Epoch 3/10
2s - loss: 0.0092 - val_loss: 0.0107
Epoch 4/10
2s - loss: 0.0086 - val_loss: 0.0116
Epoch 5/10
2s - loss: 0.0082 - val_loss: 0.0106
Epoch 6/10
2s - loss: 0.0078 - val_loss: 0.0107
Epoch 7/10
2s - loss: 0.0075 - val_loss: 0.0109
Epoch 8/10
2s - loss: 0.0070 - val_loss: 0.0111
Epoch 9/10
2s - loss: 0.0066 - val_loss: 0.0112
Epoch 10/10
2s - loss: 0.0063 - val_loss: 0.0117

The validation error does not get much lower after epoch 4 or so, whereas the training error keeps falling. This indicates overtraining and poor generalization ability.

Lets do a bit of random sampling of the predicted steering angles to get a feeling how they match with the actual angles.


In [9]:
from random import randrange

def sample_predictions(model):
    for i in range(10):
        index = randrange(len(df))
        X = np.expand_dims(X_normalized[index], axis=0)
        y = y_train[index]
        print('Actual steering angle {} model prediction {}'.format(y, model.predict(X)[0][0]))
        
sample_predictions(model)


Actual steering angle 0.0 model prediction 0.04371071606874466
Actual steering angle -0.22116129999999998 model prediction -0.26435205340385437
Actual steering angle 0.09046549999999999 model prediction 0.051914017647504807
Actual steering angle 0.1287396 model prediction 0.008762470446527004
Actual steering angle 0.03305431 model prediction 0.05218489095568657
Actual steering angle 0.1670138 model prediction 0.024041639640927315
Actual steering angle 0.3488158 model prediction 0.30565115809440613
Actual steering angle 0.0 model prediction 0.015904072672128677
Actual steering angle 0.0 model prediction 0.020633550360798836
Actual steering angle 0.0 model prediction -0.005549779627472162

The sample predictions do not look very good. Some tweaks to the model are in place.

Step 4: Tweaking the model

So what could be done to the model to improve it? Basically there are three different approaches for changing the model:

  1. Keep the model as it is, but try to improve its generalization ability
  2. Keep the current architecture, but increase the amount of weights
  3. Do some changes to the model's architecture

Before going for options 2 or 3, let's consider option 1 as it is more conservative than the other. A simple way to try to increase the generalization ability is add dropout layers, which force the model to learn redundant connections. Let's try that.


In [11]:
from keras.layers import Dropout

model_2 = Sequential()
model_2.add(Convolution2D(6, 5, 5, border_mode='valid', subsample=(5, 5), input_shape=(80, 160, 3)))
model_2.add(Dropout(0.5))
model_2.add(Activation('relu'))
model_2.add(MaxPooling2D(pool_size=(2, 2)))
model_2.add(Convolution2D(16, 5, 5, border_mode='valid', subsample=(2, 2)))
model_2.add(Dropout(0.5))
model_2.add(Activation('relu'))
model_2.add(MaxPooling2D(pool_size=(2, 2)))
model_2.add(Flatten())
model_2.add(Dense(120))
model_2.add(Activation('relu'))
model_2.add(Dense(84))
model_2.add(Activation('relu'))
model_2.add(Dense(1))
model_2.add(Activation('tanh'))

layer_info(model_2)


Layer  1 convolution2d_4  input shape (None, 80, 160, 3) output shape (None, 16, 32, 6)
Layer  2 dropout_1        input shape (None, 16, 32, 6) output shape (None, 16, 32, 6)
Layer  3 activation_6     input shape (None, 16, 32, 6) output shape (None, 16, 32, 6)
Layer  4 maxpooling2d_3   input shape (None, 16, 32, 6) output shape (None, 8, 16, 6)
Layer  5 convolution2d_5  input shape (None, 8, 16, 6) output shape (None, 2, 6, 16)
Layer  6 dropout_2        input shape (None, 2, 6, 16) output shape (None, 2, 6, 16)
Layer  7 activation_7     input shape (None, 2, 6, 16) output shape (None, 2, 6, 16)
Layer  8 maxpooling2d_4   input shape (None, 2, 6, 16) output shape (None, 1, 3, 16)
Layer  9 flatten_2        input shape (None, 1, 3, 16) output shape (None, 48)
Layer 10 dense_4          input shape (None, 48) output shape (None, 120)
Layer 11 activation_8     input shape (None, 120) output shape (None, 120)
Layer 12 dense_5          input shape (None, 120) output shape (None, 84)
Layer 13 activation_9     input shape (None, 84) output shape (None, 84)
Layer 14 dense_6          input shape (None, 84) output shape (None, 1)
Layer 15 activation_10    input shape (None, 1) output shape (None, 1)

In [12]:
train(model_2)
sample_predictions(model_2)


Train on 6428 samples, validate on 1608 samples
Epoch 1/10
3s - loss: 0.0163 - val_loss: 0.0164
Epoch 2/10
2s - loss: 0.0144 - val_loss: 0.0159
Epoch 3/10
2s - loss: 0.0131 - val_loss: 0.0151
Epoch 4/10
2s - loss: 0.0128 - val_loss: 0.0144
Epoch 5/10
2s - loss: 0.0123 - val_loss: 0.0133
Epoch 6/10
2s - loss: 0.0119 - val_loss: 0.0142
Epoch 7/10
2s - loss: 0.0115 - val_loss: 0.0130
Epoch 8/10
2s - loss: 0.0113 - val_loss: 0.0131
Epoch 9/10
2s - loss: 0.0112 - val_loss: 0.0131
Epoch 10/10
2s - loss: 0.0111 - val_loss: 0.0131
Actual steering angle 0.0 model prediction 0.03387485072016716
Actual steering angle 0.0 model prediction 0.01597663387656212
Actual steering angle 0.0 model prediction 0.02428283914923668
Actual steering angle 0.0 model prediction 0.0340711735188961
Actual steering angle -0.14520639999999999 model prediction -0.0008674438577145338
Actual steering angle 0.05219137 model prediction 0.04443788528442383
Actual steering angle 0.0 model prediction -0.008976426906883717
Actual steering angle 0.0 model prediction -0.01802789978682995
Actual steering angle 0.04262284 model prediction 0.06426456570625305
Actual steering angle -0.32559920000000003 model prediction -0.04883846640586853

The performace is even poorer now so the model is probably not complex enough to learn the given data set. I could increase the layer dimensions directly, but there is another way: remove the pooling layers. Pooling is analogous to downsampling and it reduces the amount of weights in the model. Let's strip the pooling layers and see what happens.


In [13]:
model_3 = Sequential()
model_3.add(Convolution2D(6, 5, 5, border_mode='valid', subsample=(5, 5), input_shape=(80, 160, 3)))
model_3.add(Dropout(0.5))
model_3.add(Activation('relu'))
#model_3.add(MaxPooling2D(pool_size=(2, 2)))
model_3.add(Convolution2D(16, 5, 5, border_mode='valid'))
model_3.add(Dropout(0.5))
model_3.add(Activation('relu'))
#model_3.add(MaxPooling2D(pool_size=(2, 2)))
model_3.add(Flatten())
model_3.add(Dense(120))
model_3.add(Activation('relu'))
model_3.add(Dense(84))
model_3.add(Activation('relu'))
model_3.add(Dense(1))
model_3.add(Activation('tanh'))

layer_info(model_3)


Layer  1 convolution2d_6  input shape (None, 80, 160, 3) output shape (None, 16, 32, 6)
Layer  2 dropout_3        input shape (None, 16, 32, 6) output shape (None, 16, 32, 6)
Layer  3 activation_11    input shape (None, 16, 32, 6) output shape (None, 16, 32, 6)
Layer  4 convolution2d_7  input shape (None, 16, 32, 6) output shape (None, 12, 28, 16)
Layer  5 dropout_4        input shape (None, 12, 28, 16) output shape (None, 12, 28, 16)
Layer  6 activation_12    input shape (None, 12, 28, 16) output shape (None, 12, 28, 16)
Layer  7 flatten_3        input shape (None, 12, 28, 16) output shape (None, 5376)
Layer  8 dense_7          input shape (None, 5376) output shape (None, 120)
Layer  9 activation_13    input shape (None, 120) output shape (None, 120)
Layer 10 dense_8          input shape (None, 120) output shape (None, 84)
Layer 11 activation_14    input shape (None, 84) output shape (None, 84)
Layer 12 dense_9          input shape (None, 84) output shape (None, 1)
Layer 13 activation_15    input shape (None, 1) output shape (None, 1)

In [14]:
train(model_3, 20)
sample_predictions(model_3)


Train on 6428 samples, validate on 1608 samples
Epoch 1/20
4s - loss: 0.0135 - val_loss: 0.0112
Epoch 2/20
3s - loss: 0.0107 - val_loss: 0.0124
Epoch 3/20
3s - loss: 0.0100 - val_loss: 0.0103
Epoch 4/20
3s - loss: 0.0095 - val_loss: 0.0116
Epoch 5/20
3s - loss: 0.0091 - val_loss: 0.0103
Epoch 6/20
3s - loss: 0.0089 - val_loss: 0.0103
Epoch 7/20
3s - loss: 0.0087 - val_loss: 0.0100
Epoch 8/20
3s - loss: 0.0085 - val_loss: 0.0112
Epoch 9/20
3s - loss: 0.0083 - val_loss: 0.0114
Epoch 10/20
3s - loss: 0.0082 - val_loss: 0.0104
Epoch 11/20
3s - loss: 0.0082 - val_loss: 0.0107
Epoch 12/20
3s - loss: 0.0077 - val_loss: 0.0108
Epoch 13/20
3s - loss: 0.0077 - val_loss: 0.0104
Epoch 14/20
3s - loss: 0.0076 - val_loss: 0.0100
Epoch 15/20
3s - loss: 0.0073 - val_loss: 0.0101
Epoch 16/20
3s - loss: 0.0072 - val_loss: 0.0107
Epoch 17/20
3s - loss: 0.0072 - val_loss: 0.0104
Epoch 18/20
3s - loss: 0.0071 - val_loss: 0.0118
Epoch 19/20
3s - loss: 0.0068 - val_loss: 0.0102
Epoch 20/20
3s - loss: 0.0066 - val_loss: 0.0114
Actual steering angle 0.0 model prediction 0.007433527614921331
Actual steering angle 0.3583844 model prediction 0.2920953631401062
Actual steering angle 0.10960260000000001 model prediction 0.14672048389911652
Actual steering angle 0.0 model prediction 0.003169712610542774
Actual steering angle 0.08089697 model prediction 0.04634883627295494
Actual steering angle -0.35408229999999996 model prediction -0.3030298948287964
Actual steering angle 0.0 model prediction 0.06416530162096024
Actual steering angle 0.0 model prediction -0.0014916735235601664
Actual steering angle 0.0 model prediction 0.017649848014116287
Actual steering angle -0.1736895 model prediction -0.03422090411186218

A bit better but even after 20 epochs not that much of an improvement. I begin to suspect that I need to increase the model's complexity quite a bit. At this point I will try to replicate the architecture from the NVidia paper (http://images.nvidia.com/content/tegra/automotive/images/2016/solutions/pdf/end-to-end-dl-using-px.pdf) and see what kind of difference it makes.


In [15]:
model_4 = Sequential()
model_4.add(Convolution2D(24, 5, 5, border_mode='valid', subsample=(2, 2), input_shape=(80, 160, 3)))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(36, 5, 5, border_mode='valid', subsample=(2, 2)))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(48, 5, 5, border_mode='valid', subsample=(2, 2)))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(64, 3, 3, border_mode='valid'))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(64, 3, 3, border_mode='valid'))
model_4.add(Activation('relu'))
model_4.add(Flatten())
model_4.add(Dense(100))
model_4.add(Activation('relu'))
model_4.add(Dense(50))
model_4.add(Activation('relu'))
model_4.add(Dense(10))
model_4.add(Activation('relu'))
model_4.add(Dense(1))
model_4.add(Activation('tanh'))

layer_info(model_4)


Layer  1 convolution2d_8  input shape (None, 80, 160, 3) output shape (None, 38, 78, 24)
Layer  2 activation_16    input shape (None, 38, 78, 24) output shape (None, 38, 78, 24)
Layer  3 convolution2d_9  input shape (None, 38, 78, 24) output shape (None, 17, 37, 36)
Layer  4 activation_17    input shape (None, 17, 37, 36) output shape (None, 17, 37, 36)
Layer  5 convolution2d_10 input shape (None, 17, 37, 36) output shape (None, 7, 17, 48)
Layer  6 activation_18    input shape (None, 7, 17, 48) output shape (None, 7, 17, 48)
Layer  7 convolution2d_11 input shape (None, 7, 17, 48) output shape (None, 5, 15, 64)
Layer  8 activation_19    input shape (None, 5, 15, 64) output shape (None, 5, 15, 64)
Layer  9 convolution2d_12 input shape (None, 5, 15, 64) output shape (None, 3, 13, 64)
Layer 10 activation_20    input shape (None, 3, 13, 64) output shape (None, 3, 13, 64)
Layer 11 flatten_4        input shape (None, 3, 13, 64) output shape (None, 2496)
Layer 12 dense_10         input shape (None, 2496) output shape (None, 100)
Layer 13 activation_21    input shape (None, 100) output shape (None, 100)
Layer 14 dense_11         input shape (None, 100) output shape (None, 50)
Layer 15 activation_22    input shape (None, 50) output shape (None, 50)
Layer 16 dense_12         input shape (None, 50) output shape (None, 10)
Layer 17 activation_23    input shape (None, 10) output shape (None, 10)
Layer 18 dense_13         input shape (None, 10) output shape (None, 1)
Layer 19 activation_24    input shape (None, 1) output shape (None, 1)

In [16]:
train(model_4)
sample_predictions(model_4)


Train on 6428 samples, validate on 1608 samples
Epoch 1/10
8s - loss: 0.0131 - val_loss: 0.0123
Epoch 2/10
7s - loss: 0.0105 - val_loss: 0.0109
Epoch 3/10
7s - loss: 0.0097 - val_loss: 0.0105
Epoch 4/10
7s - loss: 0.0092 - val_loss: 0.0102
Epoch 5/10
7s - loss: 0.0086 - val_loss: 0.0099
Epoch 6/10
7s - loss: 0.0081 - val_loss: 0.0105
Epoch 7/10
7s - loss: 0.0075 - val_loss: 0.0107
Epoch 8/10
7s - loss: 0.0069 - val_loss: 0.0102
Epoch 9/10
7s - loss: 0.0063 - val_loss: 0.0110
Epoch 10/10
7s - loss: 0.0055 - val_loss: 0.0114
Actual steering angle 0.0 model prediction 0.05460153520107269
Actual steering angle 0.04262284 model prediction 0.019047563895583153
Actual steering angle 0.0 model prediction -0.00044491884182207286
Actual steering angle -0.3066105 model prediction -0.012816531583666801
Actual steering angle 0.0 model prediction -0.011746209114789963
Actual steering angle 0.1765823 model prediction 0.1348859667778015
Actual steering angle 0.01391724 model prediction 0.14430499076843262
Actual steering angle 0.21485639999999998 model prediction 0.22075293958187103
Actual steering angle -0.08824026 model prediction -0.11307830363512039
Actual steering angle 0.1765823 model prediction 0.2046814262866974

In [17]:
model_4 = Sequential()
model_4.add(Convolution2D(24, 5, 5, border_mode='valid', subsample=(2, 2), input_shape=(80, 160, 3)))
model_4.add(Activation('relu'))
model_4.add(Dropout(0.5))
model_4.add(Convolution2D(36, 5, 5, border_mode='valid', subsample=(2, 2)))
model_4.add(Activation('relu'))
model_4.add(Dropout(0.5))
model_4.add(Convolution2D(48, 5, 5, border_mode='valid', subsample=(2, 2)))
model_4.add(Activation('relu'))
model_4.add(Dropout(0.5))
model_4.add(Convolution2D(64, 3, 3, border_mode='valid'))
model_4.add(Activation('relu'))
model_4.add(Dropout(0.5))
model_4.add(Convolution2D(64, 3, 3, border_mode='valid'))
model_4.add(Activation('relu'))
model_4.add(Dropout(0.5))
model_4.add(Flatten())
model_4.add(Dense(100))
model_4.add(Activation('relu'))
model_4.add(Dense(50))
model_4.add(Activation('relu'))
model_4.add(Dense(10))
model_4.add(Activation('relu'))
model_4.add(Dense(1))
model_4.add(Activation('tanh'))

layer_info(model_4)


Layer  1 convolution2d_13 input shape (None, 80, 160, 3) output shape (None, 38, 78, 24)
Layer  2 activation_25    input shape (None, 38, 78, 24) output shape (None, 38, 78, 24)
Layer  3 dropout_5        input shape (None, 38, 78, 24) output shape (None, 38, 78, 24)
Layer  4 convolution2d_14 input shape (None, 38, 78, 24) output shape (None, 17, 37, 36)
Layer  5 activation_26    input shape (None, 17, 37, 36) output shape (None, 17, 37, 36)
Layer  6 dropout_6        input shape (None, 17, 37, 36) output shape (None, 17, 37, 36)
Layer  7 convolution2d_15 input shape (None, 17, 37, 36) output shape (None, 7, 17, 48)
Layer  8 activation_27    input shape (None, 7, 17, 48) output shape (None, 7, 17, 48)
Layer  9 dropout_7        input shape (None, 7, 17, 48) output shape (None, 7, 17, 48)
Layer 10 convolution2d_16 input shape (None, 7, 17, 48) output shape (None, 5, 15, 64)
Layer 11 activation_28    input shape (None, 5, 15, 64) output shape (None, 5, 15, 64)
Layer 12 dropout_8        input shape (None, 5, 15, 64) output shape (None, 5, 15, 64)
Layer 13 convolution2d_17 input shape (None, 5, 15, 64) output shape (None, 3, 13, 64)
Layer 14 activation_29    input shape (None, 3, 13, 64) output shape (None, 3, 13, 64)
Layer 15 dropout_9        input shape (None, 3, 13, 64) output shape (None, 3, 13, 64)
Layer 16 flatten_5        input shape (None, 3, 13, 64) output shape (None, 2496)
Layer 17 dense_14         input shape (None, 2496) output shape (None, 100)
Layer 18 activation_30    input shape (None, 100) output shape (None, 100)
Layer 19 dense_15         input shape (None, 100) output shape (None, 50)
Layer 20 activation_31    input shape (None, 50) output shape (None, 50)
Layer 21 dense_16         input shape (None, 50) output shape (None, 10)
Layer 22 activation_32    input shape (None, 10) output shape (None, 10)
Layer 23 dense_17         input shape (None, 10) output shape (None, 1)
Layer 24 activation_33    input shape (None, 1) output shape (None, 1)

In [18]:
train(model_4)
sample_predictions(model_4)


Train on 6428 samples, validate on 1608 samples
Epoch 1/10
9s - loss: 0.0141 - val_loss: 0.0134
Epoch 2/10
8s - loss: 0.0116 - val_loss: 0.0131
Epoch 3/10
8s - loss: 0.0109 - val_loss: 0.0146
Epoch 4/10
8s - loss: 0.0105 - val_loss: 0.0106
Epoch 5/10
8s - loss: 0.0100 - val_loss: 0.0101
Epoch 6/10
8s - loss: 0.0098 - val_loss: 0.0096
Epoch 7/10
8s - loss: 0.0097 - val_loss: 0.0106
Epoch 8/10
8s - loss: 0.0096 - val_loss: 0.0105
Epoch 9/10
8s - loss: 0.0093 - val_loss: 0.0102
Epoch 10/10
8s - loss: 0.0092 - val_loss: 0.0098
Actual steering angle 0.0 model prediction -0.022434452548623085
Actual steering angle 0.3583844 model prediction 0.1620214730501175
Actual steering angle -0.0787459 model prediction -0.02869386598467827
Actual steering angle 0.09046549999999999 model prediction 0.011646218597888947
Actual steering angle 0.100034 model prediction 0.05777847766876221
Actual steering angle 0.0 model prediction 0.00262237386777997
Actual steering angle 0.0 model prediction -0.03472411632537842
Actual steering angle 0.07132844 model prediction 0.006533768028020859
Actual steering angle 0.0 model prediction 0.03093511424958706
Actual steering angle 0.0 model prediction 0.01404853630810976

In [39]:
model_4 = Sequential()
model_4.add(Convolution2D(24, 5, 5, border_mode='valid', subsample=(2, 2), input_shape=(80, 160, 3)))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(36, 5, 5, border_mode='valid', subsample=(2, 2)))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(48, 5, 5, border_mode='valid', subsample=(2, 2)))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(64, 3, 3, border_mode='valid'))
model_4.add(Activation('relu'))
model_4.add(Convolution2D(64, 3, 3, border_mode='valid'))
model_4.add(Activation('relu'))
model_4.add(Flatten())
model_4.add(Dense(100))
model_4.add(Dropout(0.5))
model_4.add(Activation('relu'))
model_4.add(Dense(50))
model_4.add(Activation('relu'))
model_4.add(Dense(10))
model_4.add(Activation('relu'))
model_4.add(Dense(1))

layer_info(model_4)


Layer  1 convolution2d_48 input shape (None, 80, 160, 3) output shape (None, 38, 78, 24)
Layer  2 activation_88    input shape (None, 38, 78, 24) output shape (None, 38, 78, 24)
Layer  3 convolution2d_49 input shape (None, 38, 78, 24) output shape (None, 17, 37, 36)
Layer  4 activation_89    input shape (None, 17, 37, 36) output shape (None, 17, 37, 36)
Layer  5 convolution2d_50 input shape (None, 17, 37, 36) output shape (None, 7, 17, 48)
Layer  6 activation_90    input shape (None, 7, 17, 48) output shape (None, 7, 17, 48)
Layer  7 convolution2d_51 input shape (None, 7, 17, 48) output shape (None, 5, 15, 64)
Layer  8 activation_91    input shape (None, 5, 15, 64) output shape (None, 5, 15, 64)
Layer  9 convolution2d_52 input shape (None, 5, 15, 64) output shape (None, 3, 13, 64)
Layer 10 activation_92    input shape (None, 3, 13, 64) output shape (None, 3, 13, 64)
Layer 11 flatten_12       input shape (None, 3, 13, 64) output shape (None, 2496)
Layer 12 dense_42         input shape (None, 2496) output shape (None, 100)
Layer 13 dropout_47       input shape (None, 100) output shape (None, 100)
Layer 14 activation_93    input shape (None, 100) output shape (None, 100)
Layer 15 dense_43         input shape (None, 100) output shape (None, 50)
Layer 16 activation_94    input shape (None, 50) output shape (None, 50)
Layer 17 dense_44         input shape (None, 50) output shape (None, 10)
Layer 18 activation_95    input shape (None, 10) output shape (None, 10)
Layer 19 dense_45         input shape (None, 10) output shape (None, 1)

In [40]:
train(model_4, 50, learning_rate=0.001)
sample_predictions(model_4)


Train on 6428 samples, validate on 1608 samples
Epoch 1/50
9s - loss: 0.0127 - val_loss: 0.0112
Epoch 2/50
7s - loss: 0.0101 - val_loss: 0.0110
Epoch 3/50
7s - loss: 0.0094 - val_loss: 0.0105
Epoch 4/50
7s - loss: 0.0090 - val_loss: 0.0107
Epoch 5/50
7s - loss: 0.0087 - val_loss: 0.0103
Epoch 6/50
7s - loss: 0.0084 - val_loss: 0.0100
Epoch 7/50
7s - loss: 0.0076 - val_loss: 0.0108
Epoch 8/50
7s - loss: 0.0072 - val_loss: 0.0108
Epoch 9/50
7s - loss: 0.0067 - val_loss: 0.0105
Epoch 10/50
7s - loss: 0.0061 - val_loss: 0.0113
Epoch 11/50
7s - loss: 0.0053 - val_loss: 0.0133
Epoch 12/50
7s - loss: 0.0048 - val_loss: 0.0121
Epoch 13/50
7s - loss: 0.0041 - val_loss: 0.0112
Epoch 14/50
7s - loss: 0.0035 - val_loss: 0.0118
Epoch 15/50
7s - loss: 0.0030 - val_loss: 0.0121
Epoch 16/50
7s - loss: 0.0029 - val_loss: 0.0142
Epoch 17/50
7s - loss: 0.0026 - val_loss: 0.0133
Epoch 18/50
7s - loss: 0.0022 - val_loss: 0.0142
Epoch 19/50
7s - loss: 0.0020 - val_loss: 0.0141
Epoch 20/50
7s - loss: 0.0018 - val_loss: 0.0130
Epoch 21/50
7s - loss: 0.0015 - val_loss: 0.0138
Epoch 22/50
7s - loss: 0.0017 - val_loss: 0.0128
Epoch 23/50
7s - loss: 0.0015 - val_loss: 0.0129
Epoch 24/50
7s - loss: 0.0014 - val_loss: 0.0123
Epoch 25/50
7s - loss: 0.0014 - val_loss: 0.0123
Epoch 26/50
7s - loss: 0.0014 - val_loss: 0.0136
Epoch 27/50
7s - loss: 0.0013 - val_loss: 0.0131
Epoch 28/50
7s - loss: 0.0014 - val_loss: 0.0117
Epoch 29/50
7s - loss: 0.0014 - val_loss: 0.0142
Epoch 30/50
7s - loss: 0.0013 - val_loss: 0.0121
Epoch 31/50
7s - loss: 0.0013 - val_loss: 0.0120
Epoch 32/50
7s - loss: 0.0011 - val_loss: 0.0125
Epoch 33/50
7s - loss: 0.0011 - val_loss: 0.0131
Epoch 34/50
7s - loss: 9.7220e-04 - val_loss: 0.0128
Epoch 35/50
7s - loss: 9.4868e-04 - val_loss: 0.0123
Epoch 36/50
7s - loss: 9.9995e-04 - val_loss: 0.0129
Epoch 37/50
7s - loss: 0.0011 - val_loss: 0.0124
Epoch 38/50
7s - loss: 0.0012 - val_loss: 0.0124
Epoch 39/50
7s - loss: 0.0011 - val_loss: 0.0115
Epoch 40/50
7s - loss: 0.0011 - val_loss: 0.0121
Epoch 41/50
7s - loss: 9.6353e-04 - val_loss: 0.0122
Epoch 42/50
7s - loss: 9.7532e-04 - val_loss: 0.0126
Epoch 43/50
7s - loss: 0.0010 - val_loss: 0.0123
Epoch 44/50
7s - loss: 9.7824e-04 - val_loss: 0.0131
Epoch 45/50
7s - loss: 9.1034e-04 - val_loss: 0.0124
Epoch 46/50
7s - loss: 9.1195e-04 - val_loss: 0.0127
Epoch 47/50
7s - loss: 9.7430e-04 - val_loss: 0.0129
Epoch 48/50
7s - loss: 0.0010 - val_loss: 0.0123
Epoch 49/50
7s - loss: 9.5785e-04 - val_loss: 0.0122
Epoch 50/50
7s - loss: 8.3990e-04 - val_loss: 0.0123
Actual steering angle 0.0 model prediction 0.026736818253993988
Actual steering angle 0.01391724 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.09046549999999999 model prediction 0.042016007006168365
Actual steering angle 0.061759900000000006 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction 0.0025174468755722046

In [46]:
sample_predictions(model_4)


Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle -0.04076847 model prediction -0.026189584285020828
Actual steering angle 0.1287396 model prediction 0.1220826581120491
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle -0.08824026 model prediction -0.09228046238422394
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.1957194 model prediction 0.14779014885425568
Actual steering angle 0.0 model prediction 0.0025174468755722046
Actual steering angle 0.0 model prediction -0.010257076472043991
Actual steering angle 0.07132844 model prediction 0.08812379837036133

In [ ]: