Driver
Driver
TABLE OF CONTENTS
1. PROJECT DESCRIBTION
• Introduction
• Problem Statment
• Tools
• Dataset
• Implementation
2. PREPARING
1. MODEL 1
• Define model 1
• Train model 1
• Visualize model 1 result
2. MODEL 2
• Define model 2
• Train model 2
• Visualize model 2 result
3. TESTING FINAL MODEL
PROJECT DESCRIBTION
linkcode
Introduction
According to the World Health Organization (WHO) survey, 1.3 million people worldwide die in
traffic accidents each year, making them the eighth leading cause of death and an additional 20-
50 millions are injured/ disabled. As per the report of National Crime Research Bureau (NCRB),
Govt. of India, Indian roads account for the highest fatalities in the world. There has been a
continuous increase in road crash deaths in India since 2006. The report also states that the total
number of deaths have risen to 1.46 lakhs in 2015 and driver error is the most common cause
behind these traffic accidents.The number of accidents because of distracted driver has been
increasing since few years.
National Highway Traffic Safety Administrator of United States (NHTSA) reports deaths of
3477 people and injuries to 391000 people in motor vehicle crashes because of distracted drivers
in 2015. In the United States, everyday approximately 9 people are killed and more than 1,000
are injured in road crashes that are reported to involve a distracted driver. NTHSA describes
distracted driving as “any activity that diverts attention of the driver from the task of driving”
which can be classified into Manual, Visual or Cognitive distraction. As per the definitions of
Center for Disease Control and Prevention (CDC), cognitive distraction is basically “driver’s
mind is off the driving”.
n other words, even though the driver is in safe driving posture, he is mentally distracted from
the task of driving. He might be lost in thoughts, daydreaming etc. Distraction because of
inattention, sleepiness, fatigue or drowsiness falls into visual distraction class where “drivers’s
eyes are off the road”. Manual distractions are concerned with various activities where “driver’s
hands are off the wheel”. Such distractions include talking or texting using mobile phones, eating
and drinking, talking to passengers in the vehicle, adjusting the radio, makeup etc.Nowadays,
Advanced Driver Assistance Systems (ADAS) are being developed to prevent accidents by
offering technologies that alert the driver to potential problems and to keep the car’s driver and
occupants safe if an accident does occur. But even today’s latest autonomous vehicles require the
driver to be attentive and ready to take the control of the wheel back in case of emergency.
Tesla autopilot’s crash with the white truck-trailor in Williston, Florida in May 2016 was the first
fatal crash in testing of autonomous vehicle. Recently in March 2018, Uber’s self driving car
with an emergency backup driver behind the wheel struck and killed a pedestrian in Arizona. In
both of these fatalities, the safety driver could have avoided the crashes but evidences reveal that
he was clearly distracted. This makes detection of distracted driver an essential part of the self
driving cars as well. We believe that distracted driver detection is utmost important for further
preventive measures. If the vehicle could detect such distractions and then warn the driver
against it, number of road crashes can be reduced. In this projects, we focus on detecting manual
distractions where driver is engaged in other activities than safe driving and also identify the
cause of distraction. We present a Convolutional Neural Network based approach for this
problem. We also attempt to reduce the computational complexity and memory requirement
while maintaining good accuracy which is desirable in real time applications.
Problem Statment
Given a dataset of 2D dashboard camera images, an algorithm needs to be developed to classify
each driver's behaviour and determine if they are driving attentively, wearing their seatbelt, or
taking a selfie with their friends in the backseat etc..? This can then be used to automatically
detect drivers engaging in distracted behaviours from dashboard cameras.
Following are needed tasks for the development of the algorithm:
Tools
The project utilizes the following dependencies:
Dataset
The provided data set has driver images, each taken in a car with a driver doing something in the
car (texting, eating, talking on the phone, makeup, reaching behind, etc). This dataset is obtained
from Kaggle.(State Farm Distracted Driver Detection competition).
Following are the file descriptions and URL’s from which the data can be obtained :
Transfer Learning
Most of the time you won't want to train a whole convolutional network yourself. Modern
ConvNets training on huge datasets like ImageNet take weeks on multiple GPUs.
Instead, most people use a pretrained network either as a fixed feature extractor, or as an initial
network to fine tune.
In this notebook, you'll be using [VGGNet] trained on the [ImageNet dataset] as a feature
extractor. Below is a diagram of the VGGNet architecture, with a series of convolutional and
maxpooling layers, then three fully-connected layers at the end that classify the 1000 classes
found in the ImageNet database.
!img[VGG Architecture]
VGGNet is great because it's simple and has great performance, coming in second in the
ImageNet competition. The idea here is that we keep all the convolutional layers, but replace the
final fully-connected layer with our own classifier. This way we can use VGGNet as a fixed
feature extractor for our images then easily train a simple classifier on top of that.
PREPARING
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
import pandas as pd
In [59]:
# Create folder
models_dir = "saved_models"
if not os.path.exists(models_dir):
os.makedirs(models_dir)
In [60]:
Exploration
Data exploration, preprocessing and analy will be conducted in great details to gain as much
information about the dataset as possible. All steps of a machine learning pipeline are included
and a summary is provided at the end of each section.
In [61]:
df =
pd.read_csv("../input/state-farm-distracted-driver-detection/driver_imgs_list.
csv")
df.head()
Out[61]:
subject classname img
0 p002 c0 img_44733.jpg
1 p002 c0 img_72999.jpg
2 p002 c0 img_25094.jpg
3 p002 c0 img_69092.jpg
4 p002 c0 img_92629.jpg
In [62]:
sns.set()
plt.figure(figsize = (10,5))
# Count the number of images per category
sns.countplot(x = 'classname', color = '#169DE3',data = df)
plt.show()
PREPROCESSING
In [64]:
def load_trainning_data(img_size , color_type):
start_time = time.time()
training_images = []
training_labels = []
files = glob(os.path.join('../input/state-farm-distracted-driver-
detection/imgs/train', 'c' + str(class_), '*.jpg'))
In [65]:
Loading directory c0
Loading directory c1
Loading directory c2
Loading directory c3
Loading directory c4
Loading directory c5
Loading directory c7
Loading directory c8
Loading directory c9
In [66]:
X[0]
Out[66]:
...,
[[ 9, 11, 11],
[ 8, 10, 10],
[ 8, 10, 10],
...,
[ 6, 10, 11],
[ 5, 9, 10],
[ 4, 8, 9]],
[[ 9, 11, 11],
[ 8, 10, 10],
[ 7, 9, 9],
...,
[ 6, 10, 11],
[ 5, 9, 10],
[ 4, 8, 9]],
[[ 8, 10, 10],
[ 7, 9, 9],
[ 6, 8, 8],
...,
[ 5, 10, 11],
[ 4, 9, 10],
[ 3, 8, 9]]], dtype=uint8)
In [67]:
Out[67]:
array([1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)
In [68]:
[[[ 36 44 37]
[ 34 43 33]
[ 32 42 30]
...
[255 254 230]
[255 254 227]
[255 253 224]]
[[ 31 39 32]
[ 30 39 29]
[ 29 38 28]
...
[255 255 232]
[255 255 227]
[252 254 222]]
[[ 27 35 28]
[ 27 35 28]
[ 27 36 26]
...
[253 255 236]
[250 255 232]
[245 255 224]]
...
[[ 2 7 6]
[ 2 7 6]
[ 2 7 6]
...
[ 22 24 25]
[ 12 14 14]
[ 13 15 15]]
[[ 2 7 6]
[ 2 7 6]
[ 2 7 6]
...
[ 46 47 50]
[ 9 11 12]
[ 11 12 13]]
[[ 2 7 6]
[ 2 7 6]
[ 2 7 6]
...
[ 21 21 26]
[ 12 13 17]
[ 11 12 16]]]
In [69]:
# import gc
# del X
# gc.collect()
In [70]:
# del y
# gc.collect()
In [71]:
In [72]:
random.shuffle(X_train)
In [73]:
#Normalization
#X_train = np.divide(X_train,255)
In [74]:
# X_valid = np.divide(X_valid,255)
# print(X_train[0],'/n/n')
# print(X_valid[0])
In [75]:
# pickle_out = open("X_train.pickle","wb")
# pickle.dump(X_train,pickle_out)
# pickle_out.close()
# pickle_out = open("y_train.pickle","wb")
# pickle.dump(y_train,pickle_out)
# pickle_out.close()
# pickle_out = open("X_valid.pickle","wb")
# pickle.dump(X_valid,pickle_out)
# pickle_out.close()
# pickle_out = open("y_valid.pickle","wb")
# pickle.dump(y_valid,pickle_out)
# pickle_out.close()
total = 0
files_size = len(files)
if total == test_size:
break
file_base = os.path.basename(file)
img = get_cv2_image(file, img_size, color_type)
testing_image.append(img)
testing_image_id.append(file_base)
total += 1
return testing_image, testing_image_id
In [77]:
In [78]:
# mapping categotical
CAT_MAP = {'c0': 'Safe driving',
'c1': 'Texting - right',
'c2': 'Talking on the phone - right',
'c3': 'Texting - left',
'c4': 'Talking on the phone - left',
'c5': 'Operating the radio',
'c6': 'Drinking',
'c7': 'Reaching behind',
'c8': 'Hair and makeup',
'c9': 'Talking to passenger'}
In [80]:
if directory[0] != '.':
for i, file in enumerate(os.listdir(DIR + directory)):
if i == 2:
break
else:
#fig = plt.subplot(2, 2, image_count)
#image_count += 1
image = mpimg.imread(DIR + directory + '/' + file)
plt.imshow(image)
plt.title(CAT_MAP[directory])
Convert data to batches of tensors
In [81]:
In [82]:
training_generator = train_gen.flow_from_directory('../input/state-farm-
distracted-driver-detection/imgs/train',
target_size = (IMG_SIZE,
IMG_SIZE),
batch_size = BATCHES,
shuffle=True,
class_mode='categorical',
subset="training")
validation_generator = valid_gen.flow_from_directory('../input/state-farm-
distracted-driver-detection/imgs/train',
target_size = (IMG_SIZE,
IMG_SIZE),
batch_size = BATCHES,
shuffle=False,
class_mode='categorical',
subset="validation")
MODEL1
To define a model for training we'll follow these steps:
Freezing simply means that the parameters in the pre-trained model will
not change during training.
Failed Model
In [83]:
# def VGG_16(weights_path=None):
# model = Sequential()
# # Layer 1 (CONV)
#
model.add(ZeroPadding2D((1,1),input_shape=(COLOR_TYPE,IMG_SIZE,IMG_SIZE)))
# model.add(Convolution2D(64, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(64, 3, 3, activation='relu'))
# model.add(MaxPooling2D((2,2), strides=(2,2)))
# # Layer 2 (CONV)
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(128, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(128, 3, 3, activation='relu'))
# model.add(MaxPooling2D((2,2), strides=(2,2)))
# # Layer 3 (CONV)
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(256, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(256, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(256, 3, 3, activation='relu'))
# model.add(MaxPooling2D((2,2), strides=(2,2)))
# # Layer 4 (CONV)
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(512, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(512, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(512, 3, 3, activation='relu'))
# model.add(MaxPooling2D((2,2), strides=(2,2)))
# # Layer 5 (CONV)
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(512, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(512, 3, 3, activation='relu'))
# model.add(ZeroPadding2D((1,1)))
# model.add(Convolution2D(512, 3, 3, activation='relu'))
# model.add(MaxPooling2D((2,2), strides=(2,2)))
# # Layer 6 (MPL)
# model.add(Flatten())
# model.add(Dense(4096, activation='relu'))
# model.add(Dropout(0.5))
# model.add(Dense(4096, activation='relu'))
# model.add(Dropout(0.5))
# model.add(Dense(10, activation='softmax'))
# if weights_path:
# model.load_weights(weights_path)
# return model
In [84]:
''' This callback will stop the training when there is no improvement in
the validation loss for three consecutive epochs.'''
In [85]:
checkpoint =
ModelCheckpoint(filepath='saved_models/weights_best_vgg16_model.hdf5',
monitor='val_loss', mode='max',
verbose=1, save_best_only=True)
In [86]:
train_samples = 17943
valid_samples = 4481
Define model 1
In [87]:
!rm -f input/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels.h5
In [88]:
x = model_vgg16_1.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(CLASSES, activation = 'softmax')(x)
model = Model(input = model_vgg16_1.input, output = predictions)
return model
In [89]:
print("Model 1 network...")
model_vgg16_1 = VGG16_MODEL(img_rows=IMG_SIZE, img_cols=IMG_SIZE)
model_vgg16_1.summary()
model_vgg16_1.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
Model 1 network...
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_3 (InputLayer) (None, None, None, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, None, None, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, None, None, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, None, None, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, None, None, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, None, None, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, None, None, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, None, None, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, None, None, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, None, None, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, None, None, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, None, None, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, None, None, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, None, None, 512) 0
_________________________________________________________________
global_average_pooling2d_3 ( (None, 512) 0
_________________________________________________________________
dense_5 (Dense) (None, 1024) 525312
_________________________________________________________________
dense_6 (Dense) (None, 10) 10250
=================================================================
Total params: 15,250,250
Trainable params: 535,562
Non-trainable params: 14,714,688
_________________________________________________________________
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:16: UserWarning:
Update your `Model` call to the Keras 2 API: `Model(inputs=Tensor("in...,
outputs=Tensor("de...)`
app.launch_new_instance()
Train model 1
In [90]:
history = model_vgg16_1.fit_generator(training_generator,
steps_per_epoch = train_samples // BATCHES,
epochs = EPOCHS,
callbacks=[early_stopping, checkpoint],
verbose = 1,
class_weight='auto',
validation_data = validation_generator,
validation_steps = valid_samples // BATCHES)
Epoch 1/30
358/358 [==============================] - 313s 875ms/step - loss: 2.1577 -
acc: 0.2118 - val_loss: 1.8197 - val_acc: 0.3360
In [91]:
model_vgg16_1.load_weights('saved_models/weights_best_vgg16_model.hdf5')
Plotting the accuracy and loss of the train and validation data to improve our
model
In [92]:
def plot_train_history(history):
# Summarize history for accuracy
plt.figure(figsize = (8, 5))
#plt.xticks(np.arange(0, 10))
#plt.yticks(np.arange(0, 100))
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
In [93]:
plot_train_history(history)
In [94]:
MODEL 2
Define model 2
In [95]:
!rm -f input/vggweights/vgg16_weights.h5
In [96]:
x = vgg16_model_2.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(CLASSES, activation = 'softmax')(x)
return model
In [97]:
print("Loading network...")
model_vgg16_2 = VGG16_MODEL(img_rows=IMG_SIZE, img_cols=IMG_SIZE)
model_vgg16_2.summary()
model_vgg16_2.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
Loading network...
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_4 (InputLayer) (None, None, None, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, None, None, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, None, None, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, None, None, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, None, None, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, None, None, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, None, None, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, None, None, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, None, None, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, None, None, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, None, None, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, None, None, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, None, None, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, None, None, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, None, None, 512) 0
_________________________________________________________________
global_average_pooling2d_4 ( (None, 512) 0
_________________________________________________________________
dense_7 (Dense) (None, 1024) 525312
_________________________________________________________________
dense_8 (Dense) (None, 10) 10250
=================================================================
Total params: 15,250,250
Trainable params: 535,562
Non-trainable params: 14,714,688
_________________________________________________________________
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:16: UserWarning:
Update your `Model` call to the Keras 2 API: `Model(inputs=Tensor("in...,
outputs=Tensor("de...)`
app.launch_new_instance()
Train model 2
In [98]:
history = model_vgg16_2.fit_generator(training_generator,
steps_per_epoch = train_samples // BATCHES,
epochs = EPOCHS,
callbacks=[early_stopping, checkpoint],
verbose = 1,
class_weight='auto',
validation_data = validation_generator,
validation_steps = valid_samples // BATCHES)
Epoch 1/30
358/358 [==============================] - 300s 839ms/step - loss: 2.1503 -
acc: 0.2163 - val_loss: 1.8277 - val_acc: 0.2980
In [99]:
def plot_train_history(history):
# Summarize history for accuracy
plt.figure(figsize = (8, 5))
#plt.xticks(np.arange(0, 10))
#plt.yticks(np.arange(0, 100))
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
In [100]:
plot_train_history(history)
In [101]:
def prediction():
for i in np.arange(10):
img_brute = test_data[i]
im = cv2.resize(cv2.cvtColor(img_brute, cv2.COLOR_BGR2RGB),
(IMG_SIZE,IMG_SIZE)).astype(np.float32) / 255.0
im = np.expand_dims(im, axis =0)
img_display = cv2.resize(img_brute,(IMG_SIZE,IMG_SIZE))
plt.imshow(img_display, cmap='gray')
plt.show()
In [103]:
prediction()