{"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":"# **Détection de conducteur distrait**\n### Par : KANGA OI KANGA PIERRE STEPHANE","metadata":{"execution":{"iopub.status.busy":"2022-02-23T06:42:57.834852Z","iopub.execute_input":"2022-02-23T06:42:57.835239Z","iopub.status.idle":"2022-02-23T06:43:03.235466Z","shell.execute_reply.started":"2022-02-23T06:42:57.835125Z","shell.execute_reply":"2022-02-23T06:43:03.234726Z"}}},{"cell_type":"code","source":"import os.path as osp\nimport random\nimport time\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-02-24T19:58:45.020968Z","iopub.execute_input":"2022-02-24T19:58:45.021537Z","iopub.status.idle":"2022-02-24T19:58:45.025894Z","shell.execute_reply.started":"2022-02-24T19:58:45.021498Z","shell.execute_reply":"2022-02-24T19:58:45.024911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import fastai\nfrom fastai.vision.all import *\nfrom fastai.metrics import error_rate\nfastai.__version__","metadata":{"execution":{"iopub.status.busy":"2022-02-24T20:00:16.553839Z","iopub.execute_input":"2022-02-24T20:00:16.554422Z","iopub.status.idle":"2022-02-24T20:00:19.425949Z","shell.execute_reply.started":"2022-02-24T20:00:16.554384Z","shell.execute_reply":"2022-02-24T20:00:19.425253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Fixation de la graine dans tout le projet","metadata":{}},{"cell_type":"code","source":"SEED = 2021\nnp.random.seed(SEED)\nrandom.seed(SEED)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T20:00:20.649565Z","iopub.execute_input":"2022-02-24T20:00:20.649825Z","iopub.status.idle":"2022-02-24T20:00:20.655028Z","shell.execute_reply.started":"2022-02-24T20:00:20.649796Z","shell.execute_reply":"2022-02-24T20:00:20.654209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Chargeons les images avec la librairie fastai et visualisons un lot (batch)","metadata":{}},{"cell_type":"code","source":"chemin_acces = '/kaggle/input/state-farm-distracted-driver-detection/'\ncsv_file_path = osp.join(chemin_acces, 'driver_imgs_list.csv')\n\ndf = pd.read_csv(csv_file_path) \ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T20:00:24.769987Z","iopub.execute_input":"2022-02-24T20:00:24.770294Z","iopub.status.idle":"2022-02-24T20:00:24.820080Z","shell.execute_reply.started":"2022-02-24T20:00:24.770263Z","shell.execute_reply":"2022-02-24T20:00:24.819396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Les données d'apprentissage sont composées d'images de conducteurs repartis en 10 classes à savoir :\n\n*   c0: normal 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","metadata":{}},{"cell_type":"code","source":"def label_classe(x):\n    return (df.loc[df.img==x, \"classname\"].values[0])\n\npath = osp.join(chemin_acces, \"imgs/train\")\ndls = ImageDataLoaders.from_name_func(path, get_image_files(path), valid_pct=0.25, seed=SEED, label_func=label_classe, item_tfms=Resize(224))\n\ndls.show_batch()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:34:25.769553Z","iopub.execute_input":"2022-02-24T13:34:25.770020Z","iopub.status.idle":"2022-02-24T13:35:31.935082Z","shell.execute_reply.started":"2022-02-24T13:34:25.769981Z","shell.execute_reply":"2022-02-24T13:35:31.934271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Déterminons les différentes strates ou aspects de ces images","metadata":{}},{"cell_type":"code","source":"by_drivers = df.groupby('subject') # \nunique_drivers = by_drivers.groups.keys() #\n\nprint('Nombre image dans le dataset train : ', df.shape[0])\n# determinon le nombre de conducteurs\nprint('Nombre de conducteurs unique : ',len(unique_drivers)) ","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:36:30.932035Z","iopub.execute_input":"2022-02-24T13:36:30.932297Z","iopub.status.idle":"2022-02-24T13:36:30.945868Z","shell.execute_reply.started":"2022-02-24T13:36:30.932267Z","shell.execute_reply":"2022-02-24T13:36:30.944903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Notre jeux de données train contient **22424 images**. Ces images sont celles de **26** conducteurs.\n\nL'histogramme de la repartition des images par classe nous permet de voir une repartition équilibré du nombre d'images par classe. ","metadata":{}},{"cell_type":"code","source":"classe = df.classname.value_counts()\nfig = classe.plot(kind='bar')","metadata":{"execution":{"iopub.status.busy":"2022-02-24T20:24:09.890987Z","iopub.execute_input":"2022-02-24T20:24:09.891561Z","iopub.status.idle":"2022-02-24T20:24:10.105567Z","shell.execute_reply.started":"2022-02-24T20:24:09.891522Z","shell.execute_reply":"2022-02-24T20:24:10.104894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Par contre une distribution des images par conducteurs nous presente une répartition déséquilibré.","metadata":{}},{"cell_type":"code","source":"subject = df.subject.value_counts()\nfig = subject.plot(kind='bar')","metadata":{"execution":{"iopub.status.busy":"2022-02-24T20:24:44.233209Z","iopub.execute_input":"2022-02-24T20:24:44.233696Z","iopub.status.idle":"2022-02-24T20:24:44.533580Z","shell.execute_reply.started":"2022-02-24T20:24:44.233659Z","shell.execute_reply":"2022-02-24T20:24:44.532923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Construction d'un ensemble de validation équilibré avec un ratio de 25%","metadata":{}},{"cell_type":"markdown","source":"Afin d'avoir un ensemble de validation équilibré, nous choissisons les conducteurs dont leur image devront faire partie uniquement de l'ensemble de validation tout en respectant la proportion des 25%.","metadata":{}},{"cell_type":"code","source":"choix_conducteur = ['p081','p050','p022','p012', 'p021','p002']\n\ndef ens_validation(df, subject):\n  df_return = pd.DataFrame(columns = df.columns)\n  df_return[\"is_valid\"] = \"\"\n  for i in df[\"classname\"].unique():\n    groupe = df[df[\"classname\"]==i]\n    validation = groupe[groupe.subject.isin(subject)].assign(is_valid=True)\n    train = groupe[~groupe.subject.isin(subject)].assign(is_valid=False)\n    resultat = pd.concat([validation, train],ignore_index=True)\n    df_return = pd.concat([df_return, resultat],ignore_index=True)\n    \n  return df_return","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:36:48.329782Z","iopub.execute_input":"2022-02-24T13:36:48.330035Z","iopub.status.idle":"2022-02-24T13:36:48.337023Z","shell.execute_reply.started":"2022-02-24T13:36:48.330006Z","shell.execute_reply":"2022-02-24T13:36:48.336184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df1 = ens_validation(df,choix_conducteur)\n\ndf_final = pd.DataFrame(columns = [\"img\",\"classname\",\"is_valid\"])\ndf_final[\"img\"]=df1[\"img\"]\ndf_final[\"classname\"]=df1[\"classname\"]\ndf_final[\"is_valid\"]=df1[\"is_valid\"]\ndf_final['img'] = df.apply(lambda x: osp.join(x.classname, x.img), axis=1)\ndf_final.head()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:36:53.949771Z","iopub.execute_input":"2022-02-24T13:36:53.950037Z","iopub.status.idle":"2022-02-24T13:36:55.009511Z","shell.execute_reply.started":"2022-02-24T13:36:53.950007Z","shell.execute_reply":"2022-02-24T13:36:55.008856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"La vérification des résultats nous donne :","metadata":{}},{"cell_type":"code","source":"print('Ensemble de validation : ',df_final[df_final[\"is_valid\"]==True].shape[0], ' images')\nprint('Ensemble de train : ',df_final[df_final[\"is_valid\"]==False].shape[0], ' images')","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:37:00.705777Z","iopub.execute_input":"2022-02-24T13:37:00.706025Z","iopub.status.idle":"2022-02-24T13:37:00.722548Z","shell.execute_reply.started":"2022-02-24T13:37:00.705997Z","shell.execute_reply":"2022-02-24T13:37:00.721786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Chargement des images avec la librairie fastai avec la methode from_df","metadata":{}},{"cell_type":"code","source":"path = Path('/kaggle/input/state-farm-distracted-driver-detection/imgs/')\ndls = ImageDataLoaders.from_df(df_final, path, folder='train', label_col=1, valid_col='is_valid',\n                               seed=SEED, item_tfms=Resize(224))","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:37:05.731993Z","iopub.execute_input":"2022-02-24T13:37:05.732247Z","iopub.status.idle":"2022-02-24T13:37:06.891874Z","shell.execute_reply.started":"2022-02-24T13:37:05.732213Z","shell.execute_reply":"2022-02-24T13:37:06.891144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualisons les images avec un lot :","metadata":{}},{"cell_type":"code","source":"dls.show_batch()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:37:14.131710Z","iopub.execute_input":"2022-02-24T13:37:14.131959Z","iopub.status.idle":"2022-02-24T13:37:15.494222Z","shell.execute_reply.started":"2022-02-24T13:37:14.131930Z","shell.execute_reply":"2022-02-24T13:37:15.493490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4. Entraînons notre modèle (apprentissage par transfert) pendant 5 époques\n\nNous utilisons le reseau resnet18 pour notre apprentissage par transfert.","metadata":{}},{"cell_type":"code","source":"reseau_18 = cnn_learner(dls, resnet18, metrics=[error_rate], model_dir=\"/tmp/model/\")","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:37:34.870335Z","iopub.execute_input":"2022-02-24T13:37:34.871038Z","iopub.status.idle":"2022-02-24T13:37:35.121503Z","shell.execute_reply.started":"2022-02-24T13:37:34.871001Z","shell.execute_reply":"2022-02-24T13:37:35.120746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"recherchons le rythme d’apprentissage optimal fourni par fastai","metadata":{}},{"cell_type":"code","source":"lr_rate = reseau_18.lr_find(suggest_funcs=(minimum, steep, valley, slide))","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:37:42.725846Z","iopub.execute_input":"2022-02-24T13:37:42.726116Z","iopub.status.idle":"2022-02-24T13:38:28.647123Z","shell.execute_reply.started":"2022-02-24T13:37:42.726084Z","shell.execute_reply":"2022-02-24T13:38:28.646303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('le rythme fourni par fastai est : ', lr_rate.minimum)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:42:39.218804Z","iopub.execute_input":"2022-02-24T13:42:39.219072Z","iopub.status.idle":"2022-02-24T13:42:39.225086Z","shell.execute_reply.started":"2022-02-24T13:42:39.219038Z","shell.execute_reply":"2022-02-24T13:42:39.224348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nous entrainons maintenant notre modèle avec ce rythme d'apprentissage pendant **5 époques**","metadata":{}},{"cell_type":"code","source":"reseau_18.fine_tune(epochs=5, base_lr=lr_rate.minimum, cbs=[ShowGraphCallback(),])","metadata":{"execution":{"iopub.status.busy":"2022-02-24T13:42:46.467627Z","iopub.execute_input":"2022-02-24T13:42:46.468252Z","iopub.status.idle":"2022-02-24T13:59:58.716011Z","shell.execute_reply.started":"2022-02-24T13:42:46.468213Z","shell.execute_reply":"2022-02-24T13:59:58.715197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#sauvegarde du modele\nreseau_18.save(\"./sauvegarde_model18_1\")","metadata":{"execution":{"iopub.status.busy":"2022-02-24T14:07:47.892399Z","iopub.execute_input":"2022-02-24T14:07:47.893154Z","iopub.status.idle":"2022-02-24T14:07:48.123605Z","shell.execute_reply.started":"2022-02-24T14:07:47.893110Z","shell.execute_reply":"2022-02-24T14:07:48.122860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Entraînons notre modèle à nouveau jusqu’à la dégradation (forte ameliorementation) du loss de l’ensemble de validation. Précisons le numéro de l’époque où cette divergence du loss a débuté et la meilleure performance obtenue.","metadata":{}},{"cell_type":"code","source":"reseau_18.fine_tune(epochs=15, base_lr=lr_rate.minimum, cbs=[ShowGraphCallback(),])","metadata":{"execution":{"iopub.status.busy":"2022-02-24T14:07:56.446834Z","iopub.execute_input":"2022-02-24T14:07:56.447089Z","iopub.status.idle":"2022-02-24T14:52:53.075031Z","shell.execute_reply.started":"2022-02-24T14:07:56.447059Z","shell.execute_reply":"2022-02-24T14:52:53.074274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nous avons une divergence a la **4e** epoque. La valeur de la meilleur performance est **0.456580** en terme de taux d'erreur","metadata":{}},{"cell_type":"code","source":"# sauvegarde du modèle\nreseau_18.save(\"./sauvegarde_model18_2\")","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:02:32.856882Z","iopub.execute_input":"2022-02-24T15:02:32.857850Z","iopub.status.idle":"2022-02-24T15:02:33.093978Z","shell.execute_reply.started":"2022-02-24T15:02:32.857804Z","shell.execute_reply":"2022-02-24T15:02:33.092978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 6. Entraînons de nouveau notre modèle en effectuant des changements de sorte à améliorer la performance du modèle.","metadata":{}},{"cell_type":"code","source":"changement = [Rotate(360, p=1, mode='bilinear'), Brightness(max_lighting=0.9, p=0.35),Contrast(max_lighting=0.4, p=0.25),\n              RandomErasing(p=0.2, sl=0.0, sh=0.2, min_aspect=0.3, max_count=2), Flip(p=1), Zoom(max_zoom=1.1,p=0.1), RandomResizedCrop(224)]\n\ndls_new = ImageDataLoaders.from_df(df_final, path, folder='train', label_col=1, valid_col='is_valid',\n                               seed=SEED, batch_tfms=changement, item_tfms=Resize(224))","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:02:42.447724Z","iopub.execute_input":"2022-02-24T15:02:42.447993Z","iopub.status.idle":"2022-02-24T15:02:43.599069Z","shell.execute_reply.started":"2022-02-24T15:02:42.447962Z","shell.execute_reply":"2022-02-24T15:02:43.598380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reseau_18_new = cnn_learner(dls_new, resnet18, metrics=[error_rate], model_dir=\"/tmp/model/\")","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:02:54.167791Z","iopub.execute_input":"2022-02-24T15:02:54.168040Z","iopub.status.idle":"2022-02-24T15:02:54.416629Z","shell.execute_reply.started":"2022-02-24T15:02:54.168011Z","shell.execute_reply":"2022-02-24T15:02:54.415845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lr_rate_new = reseau_18_new.lr_find(suggest_funcs=(minimum, steep, valley, slide))","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:07:27.613364Z","iopub.execute_input":"2022-02-24T15:07:27.613842Z","iopub.status.idle":"2022-02-24T15:08:12.518087Z","shell.execute_reply.started":"2022-02-24T15:07:27.613804Z","shell.execute_reply":"2022-02-24T15:08:12.517308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('le nouveau rythme après changement fourni par fastai est : ', lr_rate_new.minimum)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:15:50.101522Z","iopub.execute_input":"2022-02-24T15:15:50.101970Z","iopub.status.idle":"2022-02-24T15:15:50.106673Z","shell.execute_reply.started":"2022-02-24T15:15:50.101933Z","shell.execute_reply":"2022-02-24T15:15:50.105916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reseau_18_new.fine_tune(epochs=10, base_lr=lr_rate_new.minimum, cbs=[ShowGraphCallback(),])","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:15:54.263199Z","iopub.execute_input":"2022-02-24T15:15:54.263480Z","iopub.status.idle":"2022-02-24T15:47:06.611138Z","shell.execute_reply.started":"2022-02-24T15:15:54.263447Z","shell.execute_reply":"2022-02-24T15:47:06.610398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sauvegarde du modèle\nreseau_18_new.save(\"./sauvegarde_model18_3\")","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:50:38.214264Z","iopub.execute_input":"2022-02-24T15:50:38.214550Z","iopub.status.idle":"2022-02-24T15:50:38.445313Z","shell.execute_reply.started":"2022-02-24T15:50:38.214515Z","shell.execute_reply":"2022-02-24T15:50:38.444489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 7. Présentons les résultats de notre modèle et critiquons-le.","metadata":{}},{"cell_type":"code","source":"interpretation = ClassificationInterpretation.from_learner(reseau_18_new)\ninterpretation.plot_confusion_matrix(figsize=(12,12), dpi=60)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:50:53.968849Z","iopub.execute_input":"2022-02-24T15:50:53.969100Z","iopub.status.idle":"2022-02-24T15:51:42.477209Z","shell.execute_reply.started":"2022-02-24T15:50:53.969070Z","shell.execute_reply":"2022-02-24T15:51:42.476484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interpretation.print_classification_report()","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:51:59.627279Z","iopub.execute_input":"2022-02-24T15:51:59.627954Z","iopub.status.idle":"2022-02-24T15:51:59.645004Z","shell.execute_reply.started":"2022-02-24T15:51:59.627912Z","shell.execute_reply":"2022-02-24T15:51:59.644299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 8. À l’aide des outils vus en cours, diagnostiquons 6 prédictions à raison de 2 prédictions pour chacune des 3 classes ayant enregistré les plus mauvaises performances. Expliquons les raisons de ces erreurs pour chaque classe. Quelles suggestions pouvez vous faire pour l’amélioration du modèle ?","metadata":{}},{"cell_type":"code","source":"interpretation.most_confused(min_val=50)","metadata":{"execution":{"iopub.status.busy":"2022-02-24T15:52:25.081668Z","iopub.execute_input":"2022-02-24T15:52:25.081914Z","iopub.status.idle":"2022-02-24T15:52:25.094041Z","shell.execute_reply.started":"2022-02-24T15:52:25.081886Z","shell.execute_reply":"2022-02-24T15:52:25.093126Z"},"trusted":true},"execution_count":null,"outputs":[]}]}