{"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\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-11-20T15:27:26.494049Z","iopub.execute_input":"2021-11-20T15:27:26.494750Z","iopub.status.idle":"2021-11-20T15:27:26.500642Z","shell.execute_reply.started":"2021-11-20T15:27:26.494714Z","shell.execute_reply":"2021-11-20T15:27:26.498133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\ndataset = pd.read_csv('../input/state-farm-distracted-driver-detection/driver_imgs_list.csv')\ndataset.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:27:20.588812Z","iopub.execute_input":"2021-11-20T15:27:20.589107Z","iopub.status.idle":"2021-11-20T15:27:20.614199Z","shell.execute_reply.started":"2021-11-20T15:27:20.589079Z","shell.execute_reply":"2021-11-20T15:27:20.613543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Groupby subjects\nby_drivers = dataset.groupby('subject') \n# Groupby unique drivers\nunique_drivers = by_drivers.groups.keys() # drivers id\nprint('There are : ',len(unique_drivers), ' unique drivers')\nprint('There is a mean of ',round(dataset.groupby('subject').count()['classname'].mean()), ' images by driver.')","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:27:23.941924Z","iopub.execute_input":"2021-11-20T15:27:23.942441Z","iopub.status.idle":"2021-11-20T15:27:23.968826Z","shell.execute_reply.started":"2021-11-20T15:27:23.942404Z","shell.execute_reply":"2021-11-20T15:27:23.968103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The 10 classes to classify are :\n\nc0: safe driving\nc1: texting - right\nc2: talking on the phone - right\nc3: texting - left\nc4: talking on the phone - left\nc5: operating the radio\nc6: drinking\nc7: reaching behind\nc8: hair and makeup\nc9: talking to passenger","metadata":{}},{"cell_type":"code","source":"activity_map = {'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'}\nNUMBER_CLASSES = 10 ","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:27:30.017029Z","iopub.execute_input":"2021-11-20T15:27:30.017589Z","iopub.status.idle":"2021-11-20T15:27:30.022290Z","shell.execute_reply.started":"2021-11-20T15:27:30.017550Z","shell.execute_reply":"2021-11-20T15:27:30.021452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm\nfrom glob import glob\nimport cv2\nfrom keras.utils import np_utils\nfrom sklearn.model_selection import train_test_split\nimport numpy as np\nimport os\n\n\ndef get_cv2_image(path, img_rows, img_cols):\n    \"\"\"\n    Function that return an opencv image from the path and the right number of dimension\n    \"\"\"\n    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n    img = cv2.resize(img, (img_rows, img_cols)) # Reduce size\n    return img\n\n\ndef load_train(img_rows, img_cols):\n    \"\"\"\n    Return train images and train labels from the original path\n    \"\"\"\n    train_images = [] \n    train_labels = []\n    \n    # Loop over the training folder \n    for classed in tqdm(range(NUMBER_CLASSES)):\n        print('Loading directory c{}'.format(classed))\n        files = glob(os.path.join('../input/state-farm-distracted-driver-detection/imgs/train/c' + str(classed), '*.jpg'))\n        for file in files:\n            img = get_cv2_image(file, img_rows, img_cols)\n            train_images.append(img)\n            train_labels.append(classed)\n    return train_images, train_labels \n\ndef read_and_normalize_train_data(img_rows, img_cols):\n    \"\"\"\n    Load + categorical + split\n    \"\"\"\n    X, labels = load_train(img_rows, img_cols)\n    y = np_utils.to_categorical(labels, 10) #categorical train label\n    x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # split into train and test\n    x_train = np.array(x_train, dtype=np.uint8).reshape(-1,img_rows,img_cols,color_type)\n    x_test = np.array(x_test, dtype=np.uint8).reshape(-1,img_rows,img_cols,color_type)\n    \n    return x_train, x_test, y_train, y_test\n\n# Loading validation dataset\ndef load_test(size=200000, img_rows=64, img_cols=64):\n    \"\"\"\n    Same as above but for validation dataset\n    \"\"\"\n    path = os.path.join('../input/state-farm-distracted-driver-detection/imgs/test', '*.jpg')\n    files = sorted(glob(path))\n    X_test, X_test_id = [], []\n    total = 0\n    files_size = len(files)\n    for file in tqdm(files):\n        if total >= size or total >= files_size:\n            break\n        file_base = os.path.basename(file)\n        img = get_cv2_image(file, img_rows, img_cols)\n        X_test.append(img)\n        X_test_id.append(file_base)\n        total += 1\n    return X_test, X_test_id\n\ndef read_and_normalize_sampled_test_data(size, img_rows, img_cols):\n    test_data, test_ids = load_test(size, img_rows, img_cols)   \n    test_data = np.array(test_data, dtype=np.uint8)\n    test_data = test_data.reshape(-1,img_rows,img_cols,color_type)\n    return test_data, test_ids\n\nimg_rows = 64 # dimension of images\nimg_cols = 64\ncolor_type = 1 # grey\nnb_test_samples = 200\n\n# loading train images\nx_train, x_test, y_train, y_test = read_and_normalize_train_data(img_rows, img_cols)\n\n# loading validation images\ntest_files, test_targets = read_and_normalize_sampled_test_data(nb_test_samples, img_rows, img_cols)","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:27:30.472236Z","iopub.execute_input":"2021-11-20T15:27:30.472633Z","iopub.status.idle":"2021-11-20T15:31:17.128178Z","shell.execute_reply.started":"2021-11-20T15:27:30.472601Z","shell.execute_reply":"2021-11-20T15:31:17.127438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Statistics\n# Load the list of names\nnames = [item[17:19] for item in sorted(glob(\"../input/state-farm-distracted-driver-detection/imgs/train/*/\"))]\ntest_files_size = len(np.array(glob(os.path.join('../input/state-farm-distracted-driver-detection/imgs/test', '*.jpg'))))\nx_train_size = len(x_train)\ncategories_size = len(names)\nx_test_size = len(x_test)\nprint('There are %s total images.\\n' % (test_files_size + x_train_size + x_test_size))\nprint('There are %d training images.' % x_train_size)\nprint('There are %d total training categories.' % categories_size)\nprint('There are %d validation images.' % x_test_size)\nprint('There are %d test images.'% test_files_size)","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:31:17.129874Z","iopub.execute_input":"2021-11-20T15:31:17.130234Z","iopub.status.idle":"2021-11-20T15:31:17.425713Z","shell.execute_reply.started":"2021-11-20T15:31:17.130178Z","shell.execute_reply":"2021-11-20T15:31:17.424890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.express as px\n\npx.histogram(dataset, x=\"classname\", color=\"classname\", title=\"Number of images by categories \")","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:31:17.427100Z","iopub.execute_input":"2021-11-20T15:31:17.427364Z","iopub.status.idle":"2021-11-20T15:31:20.780966Z","shell.execute_reply.started":"2021-11-20T15:31:17.427328Z","shell.execute_reply":"2021-11-20T15:31:20.780242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the frequency of images per driver\ndrivers_id = pd.DataFrame((dataset['subject'].value_counts()).reset_index())\ndrivers_id.columns = ['driver_id', 'Counts']\npx.histogram(drivers_id, x=\"driver_id\",y=\"Counts\" ,color=\"driver_id\", title=\"Number of images by subjects \")","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:31:25.781742Z","iopub.execute_input":"2021-11-20T15:31:25.782008Z","iopub.status.idle":"2021-11-20T15:31:25.940119Z","shell.execute_reply.started":"2021-11-20T15:31:25.781978Z","shell.execute_reply":"2021-11-20T15:31:25.939351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\n\nplt.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 = mpimg.imread(BASE_URL + directory + '/' + file)\n                plt.imshow(image)\n                plt.title(activity_map[directory])","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:31:26.760580Z","iopub.execute_input":"2021-11-20T15:31:26.760860Z","iopub.status.idle":"2021-11-20T15:31:28.976833Z","shell.execute_reply.started":"2021-11-20T15:31:26.760831Z","shell.execute_reply":"2021-11-20T15:31:28.976206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.callbacks import ModelCheckpoint, EarlyStopping\nbatch_size = 40 \nnb_epoch = 7\nmodels_dir = \"saved_models\"\nif not os.path.exists(models_dir):\n    os.makedirs(models_dir)\n    \ncheckpointer = ModelCheckpoint(filepath='saved_models/weights_best.hdf5', \n                               monitor='val_loss', mode='min',\n                               verbose=1, save_best_only=True)\nes = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=2)\n","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:31:28.978110Z","iopub.execute_input":"2021-11-20T15:31:28.979358Z","iopub.status.idle":"2021-11-20T15:31:28.985723Z","shell.execute_reply.started":"2021-11-20T15:31:28.979316Z","shell.execute_reply":"2021-11-20T15:31:28.985030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import Sequential, Model\nfrom keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization, GlobalAveragePooling2D\n\ndef create_model():\n    model = Sequential()\n    \n    model.add(Conv2D(64,(3,3),activation='relu',input_shape=(img_rows, img_cols, 1)))\n    model.add(BatchNormalization())\n\n    model.add(MaxPooling2D(pool_size=(2,2),padding='same'))\n    model.add(Dropout(0.3))\n    \n    model.add(Conv2D(128,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization())\n\n    model.add(MaxPooling2D(pool_size=(2,2),padding='same'))\n    model.add(Dropout(0.3))\n    \n    model.add(Conv2D(256,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization())\n\n    model.add(MaxPooling2D(pool_size=(2,2),padding='same'))\n    model.add(Dropout(0.5))\n\n    model.add(Flatten())\n    model.add(Dense(512,activation='relu'))\n    model.add(BatchNormalization())\n    model.add(Dropout(0.5))\n    model.add(Dense(128,activation='relu'))\n    model.add(Dropout(0.25))\n    model.add(Dense(10,activation='softmax'))\n\n    return model\n","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:36:07.782689Z","iopub.execute_input":"2021-11-20T15:36:07.783375Z","iopub.status.idle":"2021-11-20T15:36:07.794289Z","shell.execute_reply.started":"2021-11-20T15:36:07.783333Z","shell.execute_reply":"2021-11-20T15:36:07.793470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nmodel = create_model()\n\nmodel.summary()\nopt = keras.optimizers.Adam()\nmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:36:10.946085Z","iopub.execute_input":"2021-11-20T15:36:10.946646Z","iopub.status.idle":"2021-11-20T15:36:11.077769Z","shell.execute_reply.started":"2021-11-20T15:36:10.946605Z","shell.execute_reply":"2021-11-20T15:36:11.077043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import timeit\nstart=timeit.default_timer()\nhistory = model.fit(x_train, y_train, \n          validation_data=(x_test, y_test),\n          epochs=nb_epoch, batch_size=batch_size, verbose=1)\nend=timeit.default_timer()\nprint(\"time taken : \",end-start)","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:36:22.098078Z","iopub.execute_input":"2021-11-20T15:36:22.098761Z","iopub.status.idle":"2021-11-20T15:37:04.416130Z","shell.execute_reply.started":"2021-11-20T15:36:22.098725Z","shell.execute_reply":"2021-11-20T15:37:04.414913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.plot(history.history['val_accuracy'],label='Valdation accuracy')\nplt.plot(history.history['accuracy'],label='Training accuracy')\nplt.legend()\nplt.show()\n\nplt.plot(history.history['loss'],label='Loss')\nplt.legend()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:39:07.565098Z","iopub.execute_input":"2021-11-20T15:39:07.565937Z","iopub.status.idle":"2021-11-20T15:39:07.961899Z","shell.execute_reply.started":"2021-11-20T15:39:07.565889Z","shell.execute_reply":"2021-11-20T15:39:07.961100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"start=timeit.default_timer()\nscore1 = model.evaluate(x_test, y_test, verbose=1)\nstop=timeit.default_timer()\nprint(\"time taken : \",stop-start)","metadata":{"execution":{"iopub.status.busy":"2021-11-20T15:39:14.323135Z","iopub.execute_input":"2021-11-20T15:39:14.323779Z","iopub.status.idle":"2021-11-20T15:39:15.052398Z","shell.execute_reply.started":"2021-11-20T15:39:14.323739Z","shell.execute_reply":"2021-11-20T15:39:15.051583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Reference https://www.kaggle.com/pierrelouisdanieau/computer-vision-tips-to-increase-accuracy","metadata":{"execution":{"iopub.status.busy":"2021-11-20T04:32:20.931831Z","iopub.execute_input":"2021-11-20T04:32:20.932114Z","iopub.status.idle":"2021-11-20T04:32:20.935839Z","shell.execute_reply.started":"2021-11-20T04:32:20.932083Z","shell.execute_reply":"2021-11-20T04:32:20.934838Z"},"trusted":true},"execution_count":null,"outputs":[]}]}