{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# System for Distraction Detection and Monitoring","metadata":{}},{"cell_type":"markdown","source":"State Farm Distracted Driver Detection has divided driving behavior into 10 classes.  \n\n\n| CLASS        | Description          |  \n| :------------- |:-------------|  \n| C0     | Safe Driving | \n| C1     | Texting - Right      |\n| C2     | Talking On The Phone - Right    |\n| C3     | Texting- left | \n| C4     | Talking on the Phone- left | \n| C5     | Operating The Radio   |\n| C6     | Drinking| \n| C7     |  Reaching Behind     |\n| C8     | Hair And Makeup   |\n| C9     | Talking To Passenger   |\n\n\nWe will implement a deep learning model, which will predict the driver activities at the time of driving. ","metadata":{}},{"cell_type":"markdown","source":"# Importing libraries ","metadata":{}},{"cell_type":"code","source":"import cv2\nimport numpy as np \nimport pandas as pd \nimport os\nimport random\nimport shutil\nimport matplotlib.pyplot as plt\n# image processing\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n#keras models\nfrom tensorflow.keras import layers ,models,optimizers\nfrom keras.layers import Dropout, Flatten, Dense\nfrom tensorflow.keras.utils import plot_model\n#resnet50\nfrom tensorflow.keras.applications import resnet50\nfrom tensorflow.keras.applications.imagenet_utils import preprocess_input \n#stop criteria\nfrom tensorflow.keras.callbacks import EarlyStopping\n#cnn_visualisation\nfrom keras.preprocessing import image\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# moving to working directory","metadata":{}},{"cell_type":"code","source":"!cp -r /kaggle/input/state-farm-distracted-driver-detection/imgs/train ./\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = \"/kaggle/working/train/\"\nvalid_dir =\"/kaggle/working/val/\"\ntest_dir  = \"/kaggle/working/test/\" ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# defining classes","metadata":{}},{"cell_type":"code","source":"activity = {   'c0' : \"safe_driving\",\n                      'c1' : \"texting-right\",\n                      'c2' : \"talking_on_the_phone-right\",\n                      'c3' : \"texting-left\",\n                      'c4' : \"talking_on_the_phone-left\",\n                      'c5' : \"operating_the_radio\",\n                      'c6' : \"drinking\",\n                      'c7' : \"reaching_behind\",\n                      'c8' : \"hair-and-makeup\",\n                      'c9' : \"talking_to_passenger\"}\nactivity.keys()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# prepare data\n**contact each image to its path and label it**","metadata":{}},{"cell_type":"code","source":"for file in os.listdir(train_dir):\n    shutil.move(os.path.join(train_dir,file), os.path.join(train_dir,activity[f'{file}']))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for file in os.listdir(train_dir):\n    os.makedirs(valid_dir + '/' + file, exist_ok=True)\n    os.makedirs(test_dir + '/' + file, exist_ok=True)    \n    train_dir_img = train_dir + file\n    file_len = len([sample for sample in os.listdir(train_dir_img)])\n    print(file_len)   # no of sampels for each class\n    \n    for sample in random.sample(os.listdir(train_dir_img) , int(float(0.1) * file_len)):\n        shutil.move(train_dir_img + '/' + sample, valid_dir + file)# Moving source to newly created destination \n    for sample in random.sample(os.listdir(train_dir_img) , int(float(0.1) * file_len)):\n        shutil.move(train_dir_img + '/' + sample, test_dir + file)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# plot one image from each class","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize = (12, 20))\nimage_count = 1\nBASE_URL = '../input/state-farm-distracted-driver-detection/imgs/train/'\nfor directory in os.listdir(BASE_URL):\n    if directory[0] != '.':\n        for i, file in enumerate(os.listdir(BASE_URL + directory)):\n            if i == 1:\n                break\n            else:\n                fig = plt.subplot(5, 2, image_count)\n                image_count += 1\n                image =cv2.imread(BASE_URL + directory + '/' + file)\n                img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n                plt.imshow(img)\n                plt.title(activity[directory])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **RESIZE IMAGES**","metadata":{}},{"cell_type":"markdown","source":"# ImageDataGenerator usually used with rescaling factor 1./255 to rescale the initial values from 0 to 255 to 0 to 1 instead.","metadata":{}},{"cell_type":"code","source":"datagen = ImageDataGenerator(rescale=1 / 255.0)\n# ImageDataGenerator and usually it is used with rescaling factor 1./255 to rescale the initial values from 0 to 255 to 0 to 1 instead.","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ImageDataGenerator\nflow_from_directory (directory), Description:Takes the path to a directory, and generates batches of augmented/normalized data.\n\nhttps://www.datasnips.com/blog/2021/8/30/Image-Augmentation-Using-Keras-ImageDataGenerator-with-Tensorflow/","metadata":{}},{"cell_type":"code","source":"batch_size = 32\ntrain_batches =datagen.flow_from_directory(directory = train_dir,shuffle = True,batch_size = batch_size)\nval_batches =datagen.flow_from_directory(directory = valid_dir,shuffle = True, batch_size = batch_size)\ntest_batches =datagen.flow_from_directory(directory= test_dir,shuffle = False,batch_size = 1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dense model","metadata":{}},{"cell_type":"code","source":"network = models.Sequential()\nnetwork.add(layers.Flatten(input_shape=(256,256,3)))\nnetwork.add(layers.Dense(1024,activation = 'relu',name = 'input'))\nnetwork.add(layers.BatchNormalization())\n#Batch normalization applies a transformation that maintains the mean \n#output close to 0 and the output standard deviation close to 1.\nnetwork.add(layers.Dense(512,activation = 'relu',name = 'l1'))\nnetwork.add(layers.BatchNormalization())\nnetwork.add(layers.Dense(256,activation = 'relu',name = 'l2'))\nnetwork.add(layers.BatchNormalization())\nnetwork.add(layers.Dense(10,activation = 'softmax',name = 'output'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_model(network)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"network.compile(optimizer='Adam',\n                loss='categorical_crossentropy',\n                metrics=['acc'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stop_criteria = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3)\ndense_model=network.fit(x = train_batches,\n          steps_per_epoch=350,\n          epochs=15,\n          validation_data = val_batches,\n          validation_steps= 50\n          , callbacks=[stop_criteria]\n                       )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(dense_model.history['acc'])  # blue line\nplt.plot(dense_model.history['val_acc']) #orange line\nplt.title('model accuracy')\nplt.ylabel('accuracy')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dense_scores= network.evaluate(test_batches)\nprint(\"Accuracy: %.2f%%\" % (dense_scores[1]*100))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DATA Augmentation","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator( rescale=1 / 255.0,\n                                    zoom_range=0.05,\n                                    width_shift_range=0.05,\n                                    height_shift_range=0.05,\n                                    shear_range=0.05,\n                                    fill_mode=\"nearest\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CNN WITH DATA Augmentation","metadata":{}},{"cell_type":"code","source":"cnn_model = models.Sequential()\ncnn_model.add(layers.Conv2D(32,(3,3),activation = 'relu',name = 'Conv_',input_shape = (256,256,3)))\ncnn_model.add(layers.Conv2D(32,(3,3),activation = 'relu',name = 'Conv_2',padding = 'same'))\ncnn_model.add(layers.Conv2D(32,(3,3),activation = 'relu',name = 'Conv_3',padding = 'same'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.MaxPooling2D((2,2),name = 'max_1'))\ncnn_model.add(layers.Conv2D(64,(3,3),activation = 'relu',name = 'Conv_4',padding='same'))\ncnn_model.add(layers.Conv2D(64,(3,3),activation = 'relu',name = 'Conv_5',padding='same'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.MaxPooling2D((2,2),name = 'max_2'))\n\ncnn_model.add(layers.Conv2D(128,(3,3),activation='relu'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.MaxPooling2D((2,2)))\ncnn_model.add(layers.Conv2D(128,(3,3),activation='relu'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.Flatten())\ncnn_model.add(layers.Dense(512,activation = 'relu',name = 'L1',))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.Dense(256,activation = 'relu',name = 'L2'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.Dense(256,activation = 'relu',name = 'L3'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.Dense(128,activation = 'relu' ,name ='L4'))\ncnn_model.add(layers.BatchNormalization())\ncnn_model.add(layers.Dense(10,activation = 'softmax',name = 'output'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_model(cnn_model,\"model.png\",show_shapes=True,show_layer_names=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnn_model.compile(optimizer = 'adam' , loss='categorical_crossentropy', metrics=['acc'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stop_criteria = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3)\ncnn_model_history = cnn_model.fit(x = train_batches,\n          steps_per_epoch=250,\n          epochs=15,\n          validation_data = val_batches,\n          validation_steps= 50,\n          callbacks=[stop_criteria])\n\n# None of the MLIR Optimization Passes are enabled is a bit misleading as it refers to very particular workflow. \n# But it is benign and has no effect - it just means a user didn’t opt in to a specific pass (which is not enabled by default), \n# so it doesn’t indicate any error and was rather used as signal for developers.","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# note\nvalidation accuracy decreased\n250/250 [==============================] - 59s 237ms/step - loss: 0.0788 - acc: 0.9757 - val_loss: 0.3936 - val_acc: 0.9000 \n\nSO we should add stop criteria ^^^^","metadata":{}},{"cell_type":"code","source":"acc = cnn_model_history.history['acc']\nval_acc = cnn_model_history.history['val_acc']\n\nloss = cnn_model_history.history['loss']\nval_loss = cnn_model_history.history['val_loss']\n\nepochs = range(len(acc))\n\nplt.plot(epochs, acc, 'bo', label='Training acc')\nplt.plot(epochs, val_acc, 'b', label='Validation acc')\nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b' ,label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnn_scores = cnn_model.evaluate(test_batches)\nprint(\"Accuracy: %.2f%%\" % (cnn_scores[1]*100))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Transfer learning with resnet50","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(preprocessing_function= resnet50.preprocess_input,\n                                                zoom_range=0.05,\n                                                width_shift_range=0.05,\n                                                height_shift_range=0.05,\n                                                shear_range=0.05,\n                                                fill_mode=\"nearest\")\n\nresnet_datagen = ImageDataGenerator(preprocessing_function= resnet50.preprocess_input)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CNN WITH RESNET","metadata":{}},{"cell_type":"code","source":"conv_model = resnet50.ResNet50(weights='imagenet',include_top=False,input_shape = (256,256,3))\n\nfor layer in conv_model.layers[:-3]:\n    layer.trainable=False  #The role of the embedding layer is to map a category into a dense space in a way that is useful for the task\n\nresnet_model = models.Sequential()\nresnet_model.add(conv_model)\nresnet_model.add(layers.Flatten())\n\ncnn_model.add(layers.Dense(512,activation = 'relu',))\ncnn_model.add(layers.BatchNormalization())\n\nresnet_model.add(layers.Dense(256,activation = 'relu'))\ncnn_model.add(layers.BatchNormalization())\n\nresnet_model.add(layers.Dense(128,activation = 'relu'))\ncnn_model.add(layers.BatchNormalization())\n\nresnet_model.add(layers.Dense(10,activation = 'softmax',name = 'output'))  # MULTICLASSES","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_model(resnet_model,\"model.png\",show_shapes=True,show_layer_names=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resnet_model.compile(optimizer = optimizers.Adam(learning_rate=.0001) ,\n              loss='categorical_crossentropy',\n              metrics=['acc'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stop_criteria = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3)\nresnet_model_history = resnet_model.fit(x = train_batches,\n          steps_per_epoch=250,\n          epochs=15,\n          validation_data = val_batches,\n          validation_steps= 50,\n          callbacks=[stop_criteria])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"acc = resnet_model_history.history['acc']\nval_acc = resnet_model_history.history['val_acc']\n\nloss = resnet_model_history.history['loss']\nval_loss = resnet_model_history.history['val_loss']\n\nepochs = range(len(acc))\n\nplt.plot(epochs, acc, 'bo', label='Training acc')\nplt.plot(epochs, val_acc, 'b', label='Validation acc')\nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b' ,label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resnet_scores= resnet_model.evaluate(test_batches)\nprint(\"Accuracy: %.2f%%\" % (resnet_scores[1]*100))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CNN Visualization","metadata":{}},{"cell_type":"code","source":"# Pre-processing the image\nimages, labels  = next(train_batches)\nimg_tensor = images[1]\nimg_tensor = np.expand_dims(img_tensor, axis=0)\n\n# Print image tensor shape\nprint(img_tensor.shape)\n\n# Print image\nplt.imshow(img_tensor[0])\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"layer_outputs = [layer.output for layer in cnn_model.layers[:10]]\nactivation_model = models.Model(inputs=cnn_model.input, outputs=layer_outputs)\nactivations = activation_model.predict(img_tensor)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"layer_names = []\nfor layer in resnet_model.layers[:10]:\n    layer_names.append(layer.name)\n\nimages_per_row = 16\n\n# Now let's display our feature maps\nfor layer_name, layer_activation in zip(layer_names, activations):\n    # This is the number of features in the feature map\n    n_features = layer_activation.shape[-1]\n\n    # The feature map has shape (1, size, size, n_features)\n    size = layer_activation.shape[1]\n\n    # We will tile the activation channels in this matrix\n    n_cols = n_features // images_per_row\n    display_grid = np.zeros((size * n_cols, images_per_row * size))\n\n    # We'll tile each filter into this big horizontal grid\n    for col in range(n_cols):\n        for row in range(images_per_row):\n            channel_image = layer_activation[0,\n                                             :, :,\n                                             col * images_per_row + row]\n            # Post-process the feature to make it visually palatable\n            channel_image -= channel_image.mean()\n            channel_image /= channel_image.std()\n            channel_image *= 64\n            channel_image += 128\n            channel_image = np.clip(channel_image, 0, 255).astype('uint8')\n            display_grid[col * size : (col + 1) * size,\n                         row * size : (row + 1) * size] = channel_image\n\n    # Display the grid\n    scale = 1. / size\n    plt.figure(figsize=(scale * display_grid.shape[1],\n                        scale * display_grid.shape[0]))\n    plt.title(layer_name)\n    plt.grid(False)\n    plt.imshow(display_grid, aspect='auto', cmap='viridis')\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ACCURACY OF MODELS USED","metadata":{}},{"cell_type":"markdown","source":"# models evaluation","metadata":{}},{"cell_type":"code","source":"# dense_scores\nacc1=dense_model.history['acc'][-1]\nvacc1=dense_model.history['val_acc'][-1]\n# cnn_scores\nacc2=cnn_model_history.history['acc'][-1]\nvacc2=cnn_model_history.history['val_acc'][-1]\n# resnet_scores\nacc3=resnet_model_history.history['acc'][-1]\nvacc3=resnet_model_history.history['val_acc'][-1]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = pd.DataFrame([[\"DENSE model\",acc1,vacc1,dense_scores[1]*100],\n                       [\"CNN_data_augmentation\",acc2,vacc2,cnn_scores[1]*100],\n                       [\"CNN_RESNET model\",acc3,vacc3,resnet_scores[1]*100]],\n                       columns = [\"Model\",\"Training Accuracy %\",\"Validation Accuracy %\",\"Test Evaluation %\"]).sort_values(by=\"Test Evaluation %\",ascending=False)\nresults.style.background_gradient(cmap='BuPu')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}