{"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":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n\n# import packages\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom PIL import Image\nimport tensorflow as tf\nimport pathlib\n\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.models import Sequential\ntf.test.is_gpu_available()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-04-21T01:20:11.621355Z","iopub.execute_input":"2022-04-21T01:20:11.621787Z","iopub.status.idle":"2022-04-21T01:20:16.288264Z","shell.execute_reply.started":"2022-04-21T01:20:11.621601Z","shell.execute_reply":"2022-04-21T01:20:16.287386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load data into datasets\n=","metadata":{}},{"cell_type":"code","source":"# define path to training data and count number of images\ndata_dir1 = '../input/state-farm-distracted-driver-detection/imgs/train'\ndata_dir = pathlib.Path(data_dir1)\n\nimage_count = len(list(data_dir.glob('*/*.jpg')))\nprint(image_count)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T01:20:18.500313Z","iopub.execute_input":"2022-04-21T01:20:18.501327Z","iopub.status.idle":"2022-04-21T01:20:19.492849Z","shell.execute_reply.started":"2022-04-21T01:20:18.501286Z","shell.execute_reply":"2022-04-21T01:20:19.492069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64\nimg_width = 200\nimg_height = int(img_width/640*480)\nprint(img_height)\ntrain_ds = tf.keras.utils.image_dataset_from_directory(\n  data_dir,\n  validation_split=0.2,\n  subset=\"training\",\n  seed=123,\n  shuffle=True,\n  image_size=(img_height, img_width),\n  batch_size=batch_size)\nval_ds = tf.keras.utils.image_dataset_from_directory(\n  data_dir,\n  validation_split=0.2,\n  subset=\"validation\",\n  seed=123,\n  shuffle=True,\n  image_size=(img_height, img_width),\n  batch_size=batch_size)\n\nclass_names = train_ds.class_names\nprint(class_names)\n# train_ds.class_names = ['safe_drive', 'text_r', 'phone_r', 'text_l', 'phone_l', 'radio', 'drink', 'reach_bhd', 'hair_mkup', 'talk_passenger']\n# val_ds.class_names = ['safe_drive', 'text_r', 'phone_r', 'text_l', 'phone_l', 'radio', 'drink', 'reach_bhd', 'hair_mkup', 'talk_passenger']\nclass_names = train_ds.class_names\nprint(class_names)\n","metadata":{"execution":{"iopub.status.busy":"2022-04-21T01:20:19.494586Z","iopub.execute_input":"2022-04-21T01:20:19.495342Z","iopub.status.idle":"2022-04-21T01:20:32.113941Z","shell.execute_reply.started":"2022-04-21T01:20:19.495301Z","shell.execute_reply":"2022-04-21T01:20:32.113253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot selection of training images\nplt.figure(figsize=(25, 25))\nfor images, labels in train_ds.take(3):\n  for i in range(9):\n    ax = plt.subplot(3, 3, i + 1)\n    plt.imshow(images[i].numpy().astype(\"uint8\"))\n    plt.title(class_names[labels[i]])\n    plt.axis(\"off\")\n\nfor image_batch, labels_batch in train_ds:\n  print(image_batch.shape)\n  print(labels_batch.shape)\n  break","metadata":{"execution":{"iopub.status.busy":"2022-04-21T01:20:32.118135Z","iopub.execute_input":"2022-04-21T01:20:32.120026Z","iopub.status.idle":"2022-04-21T01:20:37.749551Z","shell.execute_reply.started":"2022-04-21T01:20:32.119985Z","shell.execute_reply":"2022-04-21T01:20:37.748704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Define data augmentation layers\n==","metadata":{}},{"cell_type":"code","source":"img_augmentation = Sequential(\n    [\n        layers.RandomTranslation(height_factor=0.1, width_factor=(0,0.1), input_shape=(img_height, img_width, 3)),\n        layers.RandomFlip(\"horizontal\"),\n        layers.RandomRotation(factor=0.1),\n        layers.RandomZoom(-0.2, 0.1),\n        layers.RandomContrast(factor=(0.2,0)),\n    ],\n    name=\"img_augmentation\",\n)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T01:42:20.888375Z","iopub.execute_input":"2022-04-21T01:42:20.888674Z","iopub.status.idle":"2022-04-21T01:42:21.089685Z","shell.execute_reply.started":"2022-04-21T01:42:20.888625Z","shell.execute_reply":"2022-04-21T01:42:21.089005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# view augmented images\nplt.figure(figsize=(25, 25))\nfor image, labels in train_ds.take(1):\n    for i in range(9):\n        ax = plt.subplot(3, 3, i + 1)\n        aug_img = img_augmentation(tf.expand_dims(image[0], axis=0))\n        plt.imshow(aug_img[0].numpy().astype(\"uint8\"))\n        plt.title(class_names[labels[i]])\n        plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-04-21T01:42:21.091416Z","iopub.execute_input":"2022-04-21T01:42:21.091677Z","iopub.status.idle":"2022-04-21T01:42:22.638204Z","shell.execute_reply.started":"2022-04-21T01:42:21.091642Z","shell.execute_reply":"2022-04-21T01:42:22.635833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Speed up data loading with cache and prefetch\n==","metadata":{}},{"cell_type":"code","source":"AUTOTUNE = tf.data.AUTOTUNE\n\ntrain_ds = train_ds.cache().shuffle(100).prefetch(buffer_size=AUTOTUNE)\nval_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T01:33:33.047305Z","iopub.execute_input":"2022-04-21T01:33:33.048105Z","iopub.status.idle":"2022-04-21T01:33:33.056048Z","shell.execute_reply.started":"2022-04-21T01:33:33.048061Z","shell.execute_reply":"2022-04-21T01:33:33.055261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Build simple CNN model\n=","metadata":{}},{"cell_type":"code","source":"num_classes = len(class_names)\n\nmodel = Sequential([\n\n    img_augmentation,\n    layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),\n    \n    layers.Conv2D(16, 3, padding='same'),\n#     layers.BatchNormalization(),\n    layers.Activation('relu'),\n    layers.MaxPooling2D(),\n    \n    layers.Conv2D(32, 3, padding='same'),\n#     layers.BatchNormalization(),\n    layers.Activation('relu'),\n    layers.MaxPooling2D(),\n    \n    layers.Conv2D(64, 3, padding='same'),\n#     layers.BatchNormalization(),\n    layers.Activation('relu'),\n    layers.MaxPooling2D(),\n    \n    layers.Flatten(),\n    layers.Dense(128, activation='relu'),\n    layers.Dense(num_classes, activation='softmax')\n])\noptimizer = tf.keras.optimizers.Adam()\nmodel.compile(optimizer=optimizer,\n              loss=tf.keras.losses.SparseCategoricalCrossentropy(),\n              metrics=['sparse_categorical_accuracy'])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-04-21T02:58:04.21593Z","iopub.execute_input":"2022-04-21T02:58:04.216229Z","iopub.status.idle":"2022-04-21T02:58:04.474321Z","shell.execute_reply.started":"2022-04-21T02:58:04.216189Z","shell.execute_reply":"2022-04-21T02:58:04.472613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs=200\nhistory = model.fit(\n  train_ds,\n  validation_data=val_ds,\n  epochs=epochs\n)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T02:58:11.25875Z","iopub.execute_input":"2022-04-21T02:58:11.259041Z","iopub.status.idle":"2022-04-21T03:28:46.792572Z","shell.execute_reply.started":"2022-04-21T02:58:11.259011Z","shell.execute_reply":"2022-04-21T03:28:46.7918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(x=val_ds)\nmodel.evaluate(x=train_ds)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T03:36:44.233025Z","iopub.execute_input":"2022-04-21T03:36:44.23392Z","iopub.status.idle":"2022-04-21T03:36:48.00824Z","shell.execute_reply.started":"2022-04-21T03:36:44.233879Z","shell.execute_reply":"2022-04-21T03:36:48.007539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Analyse results\n=","metadata":{}},{"cell_type":"code","source":"# plot accuracy and loss history\nacc = history.history['sparse_categorical_accuracy']\nval_acc = history.history['val_sparse_categorical_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nplt.figure(figsize=(20, 8))\nplt.subplot(1, 2, 1)\nplt.plot(acc, label='Training Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.ylim((0.8,1))\nplt.grid(True)\nplt.xlabel(\"Epochs (-)\")\nplt.ylabel(\"Accuracy (-)\")\nplt.legend(loc='lower right')\nplt.title('Training and Validation Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(loss, label='Training Loss')\nplt.plot(val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.ylim((0.0,0.5))\nplt.grid(True)\nplt.xlabel(\"Epochs (-)\")\nplt.ylabel(\"Loss (-)\")\nplt.title('Training and Validation Loss')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-21T03:40:37.970989Z","iopub.execute_input":"2022-04-21T03:40:37.971732Z","iopub.status.idle":"2022-04-21T03:40:38.331306Z","shell.execute_reply.started":"2022-04-21T03:40:37.971692Z","shell.execute_reply":"2022-04-21T03:40:38.330621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check log loss equation\np = model.predict(val_ds)\nlabels = np.concatenate([y for x, y in val_ds], axis=0)\ny = tf.one_hot(labels, 10)\np = p / np.sum(p, axis=1, keepdims=True)\np[p > 1-1E-15] = 1-1E-15\np[p < 1e-15] = 1e-15\n\nlog_loss = - np.sum(y * np.log(p))/p.shape[0]\nprint(log_loss)\n","metadata":{"execution":{"iopub.status.busy":"2022-04-21T04:46:49.803136Z","iopub.execute_input":"2022-04-21T04:46:49.803898Z","iopub.status.idle":"2022-04-21T04:46:50.471409Z","shell.execute_reply.started":"2022-04-21T04:46:49.803859Z","shell.execute_reply":"2022-04-21T04:46:50.470449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot confusion matrix\npredictions = np.argmax(model.predict(val_ds), axis=1)\nlabels = np.concatenate([y for x, y in val_ds], axis=0)\nconfusMatrx = tf.math.confusion_matrix(labels, predictions)\nprint(confusMatrx)\n\nimport seaborn as sns\nplt.figure(figsize=(20, 12))\n# ax = sns.heatmap(10*confusMatrx/np.sum(confusMatrx), annot=True, cmap='Blues')\nax = sns.heatmap(confusMatrx, annot=True, cmap='Blues')\n\nax.set_xlabel('\\nPredicted Values')\nax.set_ylabel('Actual Values ');\n\n## Ticket labels - List must be in alphabetical order\nax.xaxis.set_ticklabels(['safe_drive', 'text_r', 'phone_r', 'text_l', 'phone_l', 'radio', 'drink', 'reach_bhd', 'hair_mkup', 'talk_passenger'])\nax.yaxis.set_ticklabels(['safe_drive', 'text_r', 'phone_r', 'text_l', 'phone_l', 'radio', 'drink', 'reach_bhd', 'hair_mkup', 'talk_passenger'])\n\n## Display the visualization of the Confusion Matrix.\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-21T05:16:11.998198Z","iopub.execute_input":"2022-04-21T05:16:11.998529Z","iopub.status.idle":"2022-04-21T05:16:13.280779Z","shell.execute_reply.started":"2022-04-21T05:16:11.998496Z","shell.execute_reply":"2022-04-21T05:16:13.28007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save model\nmodel.save('simple_CNN_v1.h5')","metadata":{"execution":{"iopub.status.busy":"2022-04-21T04:02:23.001154Z","iopub.execute_input":"2022-04-21T04:02:23.001969Z","iopub.status.idle":"2022-04-21T04:02:23.106325Z","shell.execute_reply.started":"2022-04-21T04:02:23.001926Z","shell.execute_reply":"2022-04-21T04:02:23.105556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Generating test set report\n=========","metadata":{}},{"cell_type":"code","source":"# load trained model\nimport tensorflow as tf\nfrom tensorflow import keras\nmodel = tf.keras.models.load_model('simple_CNN.h5')","metadata":{"execution":{"iopub.status.busy":"2022-04-20T07:39:10.328565Z","iopub.execute_input":"2022-04-20T07:39:10.3289Z","iopub.status.idle":"2022-04-20T07:39:10.54237Z","shell.execute_reply.started":"2022-04-20T07:39:10.328868Z","shell.execute_reply":"2022-04-20T07:39:10.541438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check number of test images\nimport fnmatch\nimport os\n\ntest_directory = '../input/state-farm-distracted-driver-detection/imgs/test'\ntest_img_names = fnmatch.filter(os.listdir(test_directory), '*.jpg')\nprint(test_img_names[0:10])\nn_test_images = len(test_img_names)\nprint(n_test_images)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T04:03:02.220177Z","iopub.execute_input":"2022-04-21T04:03:02.220448Z","iopub.status.idle":"2022-04-21T04:03:03.809299Z","shell.execute_reply.started":"2022-04-21T04:03:02.220419Z","shell.execute_reply":"2022-04-21T04:03:03.808486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load test images into a tf dataset\ntest_images = tf.keras.utils.image_dataset_from_directory(\n    test_directory,\n    label_mode=None,\n    image_size=(img_height, img_width))","metadata":{"execution":{"iopub.status.busy":"2022-04-21T04:03:08.024696Z","iopub.execute_input":"2022-04-21T04:03:08.025311Z","iopub.status.idle":"2022-04-21T04:04:14.389364Z","shell.execute_reply.started":"2022-04-21T04:03:08.02527Z","shell.execute_reply":"2022-04-21T04:04:14.388548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# make predictions on test dataset\npredictions = model.predict(test_images)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T04:04:14.391207Z","iopub.execute_input":"2022-04-21T04:04:14.391466Z","iopub.status.idle":"2022-04-21T04:09:26.074416Z","shell.execute_reply.started":"2022-04-21T04:04:14.391429Z","shell.execute_reply":"2022-04-21T04:09:26.073523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# compute scores on predictions using softmax\nscore = tf.nn.softmax(predictions)\nscore = score.numpy()\n\n# export scores to csv through a pandas dataframe\nimport pandas as pd\ndf = pd.DataFrame(score, columns=['c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9'], index=test_img_names)\ndf.to_csv('submit_result_v1.csv')","metadata":{"execution":{"iopub.status.busy":"2022-04-21T04:09:26.076226Z","iopub.execute_input":"2022-04-21T04:09:26.076471Z","iopub.status.idle":"2022-04-21T04:09:26.971225Z","shell.execute_reply.started":"2022-04-21T04:09:26.076436Z","shell.execute_reply":"2022-04-21T04:09:26.970233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check prediction for a single image\nimg_path = test_directory + '/' + test_img_names[0]\nimg = tf.keras.utils.load_img(img_path, target_size=(img_height, img_width))\nimg_array = tf.keras.utils.img_to_array(img)\nimg_array = tf.expand_dims(img_array, 0) # Create a batch\n\nprediction = model.predict(img_array)\nscore = tf.nn.softmax(prediction[0])\n\nprint(\n    \"This image most likely belongs to {} with a {:.2f} percent confidence.\"\n    .format(class_names[np.argmax(score)], 100 * np.max(score)))","metadata":{},"execution_count":null,"outputs":[]}]}