diff --git a/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/meta.yaml b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/meta.yaml new file mode 100644 index 00000000..0ea4331e --- /dev/null +++ b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/meta.yaml @@ -0,0 +1,14 @@ +artifact_uri: file:///c:/Users/PC/Desktop/sprint5/Churn-Prediction-avec-MLflow/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/artifacts +end_time: 1763553648348 +entry_point_name: '' +experiment_id: '667014208243130233' +lifecycle_stage: active +run_id: 11c997ed8bee45ed9bf195729379289f +run_name: Model_Analysis +source_name: '' +source_type: 4 +source_version: '' +start_time: 1763553648245 +status: 4 +tags: [] +user_id: PC diff --git a/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.runName b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.runName new file mode 100644 index 00000000..4c8c0443 --- /dev/null +++ b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.runName @@ -0,0 +1 @@ +Model_Analysis \ No newline at end of file diff --git a/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.git.commit b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.git.commit new file mode 100644 index 00000000..7baecb09 --- /dev/null +++ b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.git.commit @@ -0,0 +1 @@ +ee0487a54cbe7abb1d8287e7aad8209da0fb50ab \ No newline at end of file diff --git a/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.name b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.name new file mode 100644 index 00000000..edcd874b --- /dev/null +++ b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.name @@ -0,0 +1 @@ +c:\Users\PC\Desktop\sprint5\Churn-Prediction-avec-MLflow\venv\Lib\site-packages\ipykernel_launcher.py \ No newline at end of file diff --git a/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.type b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.type new file mode 100644 index 00000000..0c2c1fe9 --- /dev/null +++ b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.source.type @@ -0,0 +1 @@ +LOCAL \ No newline at end of file diff --git a/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.user b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.user new file mode 100644 index 00000000..d3a00fb1 --- /dev/null +++ b/mlruns/667014208243130233/11c997ed8bee45ed9bf195729379289f/tags/mlflow.user @@ -0,0 +1 @@ +PC \ No newline at end of file diff --git a/notebooks/1_data_preparation.ipynb b/notebooks/1_data_preparation.ipynb index a4faf3cf..65e0f2b1 100644 --- a/notebooks/1_data_preparation.ipynb +++ b/notebooks/1_data_preparation.ipynb @@ -29,7 +29,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "id": "b7bb38ee", "metadata": {}, "outputs": [], @@ -54,7 +54,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 2, "id": "e28261a1", "metadata": {}, "outputs": [], @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 3, "id": "8d1317c1", "metadata": {}, "outputs": [ @@ -93,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 4, "id": "f20ef61a", "metadata": {}, "outputs": [], @@ -109,7 +109,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 5, "id": "df0c3bad", "metadata": {}, "outputs": [ @@ -202,7 +202,7 @@ "type": "integer" } ], - "ref": "671c0634-f38e-44df-9001-023896228beb", + "ref": "6066bae9-4ee9-418e-9704-59be1dd7b3b1", "rows": [ [ "0", @@ -464,7 +464,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 6, "id": "0cb0b13f", "metadata": {}, "outputs": [], @@ -478,7 +478,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 7, "id": "3d2e82e1", "metadata": {}, "outputs": [ @@ -506,7 +506,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 8, "id": "8254ec85", "metadata": {}, "outputs": [ @@ -542,7 +542,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 9, "id": "1e8e39b1", "metadata": {}, "outputs": [ @@ -570,7 +570,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 10, "id": "6346e8be", "metadata": {}, "outputs": [ @@ -585,7 +585,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "C:\\Users\\PC\\AppData\\Local\\Temp\\ipykernel_17804\\2260265440.py:10: FutureWarning: \n", + "C:\\Users\\PC\\AppData\\Local\\Temp\\ipykernel_10940\\2260265440.py:10: FutureWarning: \n", "\n", "Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.\n", "\n", @@ -632,7 +632,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 11, "id": "cf988d59", "metadata": {}, "outputs": [], @@ -647,7 +647,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 12, "id": "a91d6aab", "metadata": {}, "outputs": [ @@ -679,7 +679,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 13, "id": "5c42d6fe", "metadata": {}, "outputs": [], @@ -693,7 +693,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 14, "id": "78a70fd5", "metadata": {}, "outputs": [ @@ -721,7 +721,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 15, "id": "5ebcc4c2", "metadata": {}, "outputs": [], @@ -739,7 +739,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 16, "id": "c7b37462", "metadata": {}, "outputs": [ @@ -767,7 +767,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 17, "id": "27f51f97", "metadata": {}, "outputs": [ @@ -804,7 +804,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 18, "id": "27fc5567", "metadata": {}, "outputs": [ @@ -838,7 +838,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 19, "id": "d2efb894", "metadata": {}, "outputs": [], @@ -854,7 +854,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 20, "id": "83b667f8", "metadata": {}, "outputs": [ diff --git a/notebooks/3_training_mlflow.ipynb b/notebooks/3_training_mlflow.ipynb index 1c8918d3..89826aaf 100644 --- a/notebooks/3_training_mlflow.ipynb +++ b/notebooks/3_training_mlflow.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 14, "id": "cdc36db3", "metadata": {}, "outputs": [], @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 15, "id": "7c0b9909", "metadata": {}, "outputs": [], @@ -55,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 16, "id": "3dfe9866", "metadata": {}, "outputs": [ @@ -65,7 +65,7 @@ "" ] }, - "execution_count": 96, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 17, "id": "7a71d137", "metadata": {}, "outputs": [ @@ -91,7 +91,7 @@ "" ] }, - "execution_count": 97, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -110,7 +110,7 @@ }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 18, "id": "3873ae40", "metadata": {}, "outputs": [], @@ -123,21 +123,21 @@ }, { "cell_type": "code", - "execution_count": 99, + "execution_count": 19, "id": "3660d6e9", "metadata": {}, "outputs": [], "source": [ "scripts = [\n", - " \"scripts/logistic_script.py\",\n", - " \"scripts/forest_script.py\",\n", - " \"scripts/xgboost_script.py\"\n", + " \"src/models/logistic.py\",\n", + " \"src/models/forest.py\",\n", + " \"src/models/xgboost.py\"\n", "]" ] }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 20, "id": "a2d7d584", "metadata": {}, "outputs": [ @@ -145,12 +145,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "⚙️ Entraînement avec scripts/logistic_script.py ...\n", - "✅ Terminé : scripts/logistic_script.py\n", - "⚙️ Entraînement avec scripts/forest_script.py ...\n", - "✅ Terminé : scripts/forest_script.py\n", - "⚙️ Entraînement avec scripts/xgboost_script.py ...\n", - "✅ Terminé : scripts/xgboost_script.py\n" + "⚙️ Entraînement avec src/models/logistic.py ...\n", + "✅ Terminé : src/models/logistic.py\n", + "⚙️ Entraînement avec src/models/forest.py ...\n", + "✅ Terminé : src/models/forest.py\n", + "⚙️ Entraînement avec src/models/xgboost.py ...\n", + "✅ Terminé : src/models/xgboost.py\n" ] } ], @@ -163,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 101, + "execution_count": 21, "id": "16b8b1b9", "metadata": {}, "outputs": [ @@ -171,7 +171,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "['run_id', 'experiment_id', 'status', 'artifact_uri', 'start_time', 'end_time']\n" + "['run_id', 'experiment_id', 'status', 'artifact_uri', 'start_time', 'end_time', 'metrics.accuracy', 'metrics.f1', 'params.note', 'tags.mlflow.runName', 'tags.mlflow.source.git.commit', 'tags.mlflow.source.type', 'tags.mlflow.user', 'tags.mlflow.source.name', 'tags.model_name', 'tags.imbalance_strategy']\n" ] } ], @@ -197,7 +197,7 @@ }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 22, "id": "9be2f5e6", "metadata": {}, "outputs": [ @@ -210,7 +210,7 @@ "" ] }, - "execution_count": 102, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -224,7 +224,7 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 23, "id": "47886e9f", "metadata": {}, "outputs": [ @@ -250,7 +250,7 @@ }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 24, "id": "14cb0429", "metadata": {}, "outputs": [ @@ -263,7 +263,7 @@ "" ] }, - "execution_count": 104, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -274,7 +274,7 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": 25, "id": "aabc40ea", "metadata": {}, "outputs": [], @@ -292,20 +292,46 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": 27, "id": "369da389", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'client' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[27]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m runs_info = \u001b[43mclient\u001b[49m.search_runs(experiment_ids=[experiment.experiment_id])\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33m✅ \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mlen\u001b[39m(runs_info)\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m runs trouvés\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 4\u001b[39m \u001b[38;5;66;03m# Créer le DataFrame\u001b[39;00m\n", + "\u001b[31mNameError\u001b[39m: name 'client' is not defined" + ] + } + ], "source": [ - "# Charger les runs MLflow\n", - "client = mlflow.tracking.MlflowClient()\n", - "experiment = client.get_experiment_by_name(\"Churn_Prediction_Models\")\n", - "runs = mlflow.search_runs(experiment_ids=[experiment.experiment_id])" + "runs_info = client.search_runs(experiment_ids=[experiment.experiment_id])\n", + "print(f\"✅ {len(runs_info)} runs trouvés\")\n", + "\n", + "# Créer le DataFrame\n", + "runs_data = []\n", + "for run in runs_info:\n", + " run_dict = {\n", + " 'run_id': run.info.run_id,\n", + " 'tags.model_name': run.data.tags.get('model_name', 'Unknown'),\n", + " 'tags.imbalance_strategy': run.data.tags.get('imbalance_strategy', 'Unknown'),\n", + " 'metrics.f1_score': run.data.metrics.get('f1_score', 0),\n", + " 'metrics.accuracy': run.data.metrics.get('accuracy', 0)\n", + " }\n", + " runs_data.append(run_dict)\n", + "runs = pd.DataFrame(runs_data)\n", + "\n", + "# Vérifier les colonnes disponibles\n", + "print(\"📋 Colonnes disponibles :\", runs.columns.tolist())\n" ] }, { "cell_type": "code", - "execution_count": 107, + "execution_count": null, "id": "2304da8b", "metadata": {}, "outputs": [ @@ -313,10 +339,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "📋 Colonnes disponibles : ['run_id', 'experiment_id', 'status', 'artifact_uri', 'start_time', 'end_time']\n", - "⚠️ Aucune métrique F1 trouvée dans les runs MLflow.\n", - "👉 Vérifiez que la métrique F1 a bien été loggée avec `mlflow.log_metric('f1', valeur)`.\n", - "🔎 Exemple de colonnes disponibles liées aux métriques : []\n" + "📋 Colonnes disponibles : ['run_id', 'experiment_id', 'status', 'artifact_uri', 'start_time', 'end_time', 'metrics.accuracy', 'metrics.f1', 'params.note', 'tags.mlflow.user', 'tags.mlflow.runName', 'tags.mlflow.source.name', 'tags.mlflow.source.type', 'tags.mlflow.source.git.commit', 'tags.model_name', 'tags.imbalance_strategy']\n" ] } ], @@ -325,7 +348,7 @@ "print(\"📋 Colonnes disponibles :\", runs.columns.tolist())\n", "\n", "# Rechercher la colonne correspondant à la métrique F1\n", - "f1_cols = [col for col in runs.columns if \"f1\" in col.lower() and col.startswith(\"metrics.\")]\n", + "f1_cols = [col for col in runs.columns if \"f1_score\" in col.lower() and col.startswith(\"metrics.\")]\n", "\n", "# Si aucune métrique F1 n'est trouvée, afficher un message explicatif au lieu de lever une erreur\n", "if not f1_cols:\n", @@ -347,7 +370,7 @@ }, { "cell_type": "code", - "execution_count": 171, + "execution_count": null, "id": "661c451b", "metadata": {}, "outputs": [ @@ -371,17 +394,22 @@ "type": "float" } ], - "ref": "723820ad-eff1-43d0-8403-e4115ac8b38a", + "ref": "1bfb0a45-4917-41ff-8bda-f7465ecc7239", "rows": [ [ "0", + null, + null + ], + [ + "1", "0.5", "0.5" ] ], "shape": { "columns": 2, - "rows": 1 + "rows": 2 } }, "text/html": [ @@ -410,6 +438,11 @@ " \n", " \n", " 0\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " 1\n", " 0.5\n", " 0.5\n", " \n", @@ -419,10 +452,11 @@ ], "text/plain": [ " metrics.accuracy metrics.f1\n", - "0 0.5 0.5" + "0 NaN NaN\n", + "1 0.5 0.5" ] }, - "execution_count": 171, + "execution_count": 72, "metadata": {}, "output_type": "execute_result" } @@ -433,7 +467,7 @@ }, { "cell_type": "code", - "execution_count": 172, + "execution_count": null, "id": "eaa49d1c", "metadata": {}, "outputs": [ @@ -446,13 +480,13 @@ "" ] }, - "execution_count": 172, + "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "best_run = runs.sort_values(\"metrics.f1\", ascending=False).iloc[0]\n", + "best_run = runs.sort_values(\"metrics.f1_score\", ascending=False).iloc[0]\n", "md(f\"**Meilleur modèle :** {best_run['tags.model_name']} (F1 = {best_run['metrics.f1']:.3f})\")\n" ] }, @@ -466,19 +500,24 @@ }, { "cell_type": "code", - "execution_count": 173, + "execution_count": null, "id": "3f546c09", "metadata": {}, "outputs": [], "source": [ "# Chargement et test du modèle\n", "model_uri = f\"runs:/{best_run['run_id']}/model\"\n", - "loaded_model = mlflow.sklearn.load_model(model_uri)" + "try:\n", + " loaded_model = mlflow.sklearn.load_model(model_uri)\n", + " print(\"Modèle chargé\")\n", + "except Exception as e:\n", + " print(f\"Erreur chargement modèle: {e}\")\n", + " loaded_model = None\n" ] }, { "cell_type": "code", - "execution_count": 174, + "execution_count": null, "id": "638439a2", "metadata": {}, "outputs": [], diff --git a/notebooks/4_model_analysis.ipynb b/notebooks/4_model_analysis.ipynb index 8c483d99..49055ff0 100644 --- a/notebooks/4_model_analysis.ipynb +++ b/notebooks/4_model_analysis.ipynb @@ -15,12 +15,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 63, "id": "3c944aae", "metadata": {}, "outputs": [], "source": [ - "import mlflow\n", + "import os\n", + "os.chdir(\"..\") if \"notebooks\" in os.getcwd() else None\n", + "from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, roc_curve, auc, accuracy_score, f1_score\n", "import mlflow.sklearn\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", @@ -40,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "id": "9b21c002", "metadata": {}, "outputs": [], @@ -53,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 65, "id": "732b4fa8", "metadata": {}, "outputs": [], @@ -64,13 +66,41 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 66, "id": "4a10075e", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ 2 runs trouvés pour l'expérience 'Churn_Prediction_Models'\n" + ] + } + ], "source": [ - "runs = mlflow.search_runs(experiment_ids=[experiment.experiment_id])\n", - "print(f\"✅ {len(runs)} runs trouvés pour l'expérience '{experiment_name}'\")" + "client = mlflow.tracking.MlflowClient()\n", + "mlflow.set_tracking_uri(\"file:./mlruns\")\n", + "experiment_name = \"Churn_Prediction_Models\"\n", + "client = mlflow.tracking.MlflowClient()\n", + "experiment = client.get_experiment_by_name(experiment_name)\n", + "if experiment is None:\n", + " raise ValueError(f\"⚠️ Aucun experiment MLflow trouvé avec le nom : {experiment_name}\")\n", + "runs_info = client.search_runs(experiment_ids=[experiment.experiment_id])\n", + "print(f\"✅ {len(runs_info)} runs trouvés pour l'expérience '{experiment_name}'\")\n", + "\n", + "# Créer le DataFrame à partir des objets Run\n", + "runs_data = []\n", + "for run in runs_info:\n", + " run_dict = {\n", + " 'run_id': run.info.run_id,\n", + " 'tags.model_name': run.data.tags.get('model_name', 'Unknown'),\n", + " 'tags.imbalance_strategy': run.data.tags.get('imbalance_strategy', 'Unknown'),\n", + " 'metrics.f1_score': run.data.metrics.get('f1_score', 0),\n", + " 'metrics.accuracy': run.data.metrics.get('accuracy', 0)\n", + " }\n", + " runs_data.append(run_dict)\n", + "runs = pd.DataFrame(runs_data)\n" ] }, { @@ -83,25 +113,257 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 67, "id": "c8455212", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.microsoft.datawrangler.viewer.v0+json": { + "columns": [ + { + "name": "index", + "rawType": "int64", + "type": "integer" + }, + { + "name": "Model", + "rawType": "object", + "type": "string" + }, + { + "name": "Strategy", + "rawType": "object", + "type": "string" + }, + { + "name": "f1", + "rawType": "int64", + "type": "integer" + }, + { + "name": "Accuracy", + "rawType": "float64", + "type": "float" + }, + { + "name": "Run_ID", + "rawType": "object", + "type": "string" + } + ], + "ref": "5a157108-f75b-49c9-a34a-0835d557bdb2", + "rows": [ + [ + "0", + "Unknown", + "Unknown", + "0", + "0.0", + "11c997ed8bee45ed9bf195729379289f" + ], + [ + "1", + "DummyModel", + "none", + "0", + "0.5", + "9ef1f5bd1b494066bbf7d0c26b56384f" + ] + ], + "shape": { + "columns": 5, + "rows": 2 + } + }, + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ModelStrategyf1AccuracyRun_ID
0UnknownUnknown00.011c997ed8bee45ed9bf195729379289f
1DummyModelnone00.59ef1f5bd1b494066bbf7d0c26b56384f
\n", + "
" + ], + "text/plain": [ + " Model Strategy f1 Accuracy Run_ID\n", + "0 Unknown Unknown 0 0.0 11c997ed8bee45ed9bf195729379289f\n", + "1 DummyModel none 0 0.5 9ef1f5bd1b494066bbf7d0c26b56384f" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "# ==========================================================\n", - "# 2️⃣ Synthèse des performances\n", - "# ==========================================================\n", - "metrics_summary = runs[[\"tags.model_name\", \"tags.imbalance_strategy\",\n", - " \"metrics.f1_score\", \"metrics.accuracy\", \"run_id\"]].sort_values(\"metrics.f1_score\", ascending=False)\n", - "metrics_summary.columns = [\"Model\", \"Strategy\", \"F1_score\", \"Accuracy\", \"Run_ID\"]" + "metrics_summary = runs[[\"tags.model_name\", \"tags.imbalance_strategy\", \"metrics.f1_score\", \"metrics.accuracy\", \"run_id\"]].copy()\n", + "metrics_summary.columns = [\"Model\", \"Strategy\", \"f1\", \"Accuracy\", \"Run_ID\"]\n", + "\n", + "metrics_summary.columns = [\"Model\", \"Strategy\", \"f1\", \"Accuracy\", \"Run_ID\"]\n", + "\n", + "display(metrics_summary.head(10))\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 68, "id": "655a04a6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.microsoft.datawrangler.viewer.v0+json": { + "columns": [ + { + "name": "index", + "rawType": "int64", + "type": "integer" + }, + { + "name": "Model", + "rawType": "object", + "type": "string" + }, + { + "name": "Strategy", + "rawType": "object", + "type": "string" + }, + { + "name": "f1", + "rawType": "int64", + "type": "integer" + }, + { + "name": "Accuracy", + "rawType": "float64", + "type": "float" + }, + { + "name": "Run_ID", + "rawType": "object", + "type": "string" + } + ], + "ref": "8711dce2-3c59-4626-bc9c-d747ad9d41b3", + "rows": [ + [ + "0", + "Unknown", + "Unknown", + "0", + "0.0", + "11c997ed8bee45ed9bf195729379289f" + ], + [ + "1", + "DummyModel", + "none", + "0", + "0.5", + "9ef1f5bd1b494066bbf7d0c26b56384f" + ] + ], + "shape": { + "columns": 5, + "rows": 2 + } + }, + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ModelStrategyf1AccuracyRun_ID
0UnknownUnknown00.011c997ed8bee45ed9bf195729379289f
1DummyModelnone00.59ef1f5bd1b494066bbf7d0c26b56384f
\n", + "
" + ], + "text/plain": [ + " Model Strategy f1 Accuracy Run_ID\n", + "0 Unknown Unknown 0 0.0 11c997ed8bee45ed9bf195729379289f\n", + "1 DummyModel none 0 0.5 9ef1f5bd1b494066bbf7d0c26b56384f" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "display(metrics_summary.head(10))" ] @@ -116,16 +378,35 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 69, "id": "51cedbca", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\IPython\\core\\pylabtools.py:170: UserWarning: Glyph 128202 (\\N{BAR CHART}) missing from font(s) DejaVu Sans.\n", + " fig.canvas.print_figure(bytes_io, **kw)\n" + ] + }, + { + "data": { + "image/png": "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yZMJxwAAADg7FStWdCUKP//8swuo6ginsogpU6ZYy5Ytk7TMBg0a2Oeff259+/a1119/PUH3UcnD9OnTXcc/tQZrXbRuCr2hFIpVuhFaW6z/h09LTZkCgUAgtVci2h08eNDV9ajmR7U/AAAgehw9etQ2b95sFSpUsJw5c6b26iCFXsuE5jXKKgAAAAAP4RgAAACI1nD8xhtvWPny5V1TuepqVPAdH9XcqDek5lehuIrM43Lfffe5mpnEFKADAAAg/YiqcKyi7p49e7qzs6gnpM6x3aJFizgHg16yZIk7zWDXrl3dMCE6r7guP/30U6x5/+///s++/fZbN8YeAAAAMqaoCscamuTuu++2Ll26uDHzRo4cablz57bRo0dHnP+1115zPTUff/xxN0zIwIED7YorrnDj64XasWOHdevWzQ0tEj7ANQAAADKOqAnHx48ft5UrV7qhQXyZM2d215cuXRrxPpoeOr+opTl0fp1l5fbbb3cBOtKpEiM5duyY6/EYegEAAED0i5pw/Oeff7ox8IoXLx5juq7v2rUr4n00/Uzzv/jii5Y1a1Y3eHZCDR482A0F4l9CzyMOAACA6BU14TglqCVapRdjx44Nnq87Ifr06ePGyPMvoadKBAAAQPSKmnBcpEgRy5Ili+3evTvGdF0vUaJExPtoenzzf/PNN64zX9myZV3rsS5bt251p1vUiBhxyZEjhxs8OvQCAACA6Bc14Th79uxWs2ZNmzt3box6YV2vV69exPtoeuj8MmfOnOD8qjXWeci///774EWjVaj+ePbs2Sn8jAAAAJDWZLUoomHcOnfubLVq1bLatWu78YgPHz7sRq+QTp06WenSpV1NsHTv3t2dw3vo0KHWqlUrmzRpkq1YscJGjRrlbi9cuLC7hNJoFWpZvvjii1PhGQIAgLRk27PVz+njle235pw+HqI8HLdv39727t1r/fr1c53qLrvsMps1a1aw0922bdvcCBa++vXr28SJE61v37725JNPWqVKlWzatGlWrVq1VHwWAAAASKuipqzC99BDD7m6YA2ntmzZMneWPN+CBQtc57pQt9xyi23YsMHNr5N/XH/99fEuf8uWLdajR48UW38AAIDk0rhxYzfiVq9evaxQoULu6PeAAQOCt6vhsHXr1pY3b17XR6pdu3Yx+mNpXjU2vv/++66/Vf78+e3WW2+1f/75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jRvd33Hjxrkvp7gO/w0ZMsR69+5tX375pTVt2jQ4XfdTy8iyZcvcPM8++6zNmTMnGHb1JbBv3z73xaHpmzZtsvbt2wfPIa86Ov9Lb82aNe5LZ/Xq1Xbo0CE3Tfdr1KhRjHV56qmn7LHHHnNfUhdddJF16NAhqludgIxMwVY/cvWjNzH0Q3zEiBG2ZMkSF0oVMtVHYuLEifb555+7fdXrr78e4z7aXxUpUsS+++47F5Tvv/9+u+WWW6x+/fq2atUqu/baa+322293oVr7ojvvvDNWi7CuX3311S44+xRkW7Ro4ZYvuv/kyZPd/UOdaZ8oH330kXtugwYNcg0HarwID74TJkywfv362fPPP2/r16938z799NPBx0c6FwCQaI0aNQp079491vQxY8YE8ufP7/7fuXPnQLly5QInT54M3n7LLbcE2rdvH7yu21999dVAr169AiVLlgz89NNPsR6nQYMGMaZdeeWVgSeeeML9/8svvwxkyZIlsG3btuDta9euDeij/d1337nrPXv2DLRq1cr9f9iwYe7xL7300sAXX3zhpl144YWBUaNGuf9v3rzZ3ffdd9+Ntbz169fzTgHSMO1zWrduHfE2fe6rVKkS/IyvXr06eNvff//tps2fP99d119d/+qrr4LzDB482E3buHFjcNq9994baNGiRZz7K+378uTJE7j99tuD0/744w+3nKVLl7rrO3bscPuwZcuWuevHjx8PFClSJDB27NhY+8lp06YFLrjggsDp06cD48aNC1x++eXudu1zte9N6D6xXr16gQceeCDG9qlTp47bL/r0OBMnTowxz8CBA919JdJ2RPpByzGQgtRZRGUNPrVQ6NBkqKFDh7pDj4sWLXLzh6tRo0aM66HLUIuGSiL8sgipWrWqK83QbaJWYS371KlTriVFhz51UWvyzp073aFLXY/rMfV4Er7eAKKHShjUUpsYofsBtdyqzKpixYoxpoXvF0Lvo32fysmqV68e4z7i369UqVLWqlUrVyIhn332mR07dsy1NofTfDri9fXXX7v5w1uNE7pP1N86derEuF+9evWC/1cZiI74qdxCpRn+5bnnnnPTkf4RjoEkUB2b6nnDqXZPpQw+9RgPpS+n8F7jDRs2dMFVh/oiScgy4qPDk//88487pKkvldBwrLCsL6dKlSrF+Zj+F2o093YHMjoFwgoVKljmzJmDYdkXVz+I8P1AQvZFkeY50/7krrvuciNR/Pvvv66kQiUQCuLhVFuskoz+/fu7MjPVG6cEv+RMjRYqLfMvP/30k+sEiPSPcAwkwcUXX+zCZjhNU41uYtSuXdt1UFFNW3jHlDNRZxHVAoZ2Ulm3bp0L6WotEbWYqDVHtYP6klLHEgVm1R3PmDEjVr0xgPRl3rx5rr/BTTfdZEWLFnXTNKKFL7XH6r3++utdv4q33nrLZs2aFbFF2Kfb9KNedcXq9JeUfaLmUbgOFRp61bqtRgPVKqvuOfSiHxhI/2J28QSQIOpkorCpkSTU6qEe4uqg8uGHH7rDgomlziozZ8606667zrWORBpDOZJmzZq5Q5ZqQVFHGXWae+CBB1zgrVWrVnA+tRSr48zNN9/srmvECn1BqEPLG2+8wasOpBMqSdDwZjoapREaFDYHDx7shnLr1KmTK3XQaDUarUFBT+UNffv2TdV11jppdJ8+ffq4o1ihJQ7htN/6888/I7YsJ3SfqKHt9Hi6ftVVV7nOd2vXro1RMvLMM8+4/buOBGp4PG1Xdd77+++/rWfPnimwFZCW0HIMJIF2oipR+Pnnn93OWPVrKouYMmWK25EmRYMGDVzA1hdVeA/wuOgQpYZpUguKWoO1Llo3hd5Q+mLQl2VobbH+Hz4NQHRTGFY/AZ04Q/sijZQzfPhwt5/w+z+oXlehsWbNmu6HuGppU5vqe48fP+6GfDsT1TFreLmk7hNVtqGRJzREprbB1q1bXYNHKDV6aCg3lXkobGsfqpGGaDnOGDKpV15qrwQAAMi4vvnmGzeEpcoh/E57QGohHAMAgFShcoW9e/da586d3clLVOIApDbKKgAAQKpQP41y5cq5DnM6yRGQFtByDAAAAHhoOQYAAAA8hGMAAADAQzgGAAAAPIRjAAAAwEM4BgAkyIIFC9xJFjSyQELpZBQ6UxkARAvCMQCkEzolrsLrfffdF+u2Bx980N2meQAAcSMcA0A6UqZMGZs0aZL9+++/wWlHjx61iRMnWtmyZVN13QAgGhCOASAdueKKK1xAnjp1anCa/q9gfPnll8c4M9nDDz9sxYoVs5w5c1qDBg1s+fLlMZY1c+ZMu+iiiyxXrlzWpEkT27JlS6zHW7RokTVs2NDNo8fVMg8fPpzCzxIAUg7hGADSmTvvvNPGjBkTvD569Gjr0qVLjHl69epln3zyiY0bN85WrVplF154obVo0cL27dvnbt++fbu1bdvW/vOf/9j3339vd911l/Xu3TvGMjZu3GgtW7a0m266yX788UebPHmyC8sPPfTQOXqmAJD8CMcAkM7cdtttLqRu3brVXRYvXuym+dSy+9Zbb9lLL71k1113nVWtWtXeeecd1/r73nvvuXl0+wUXXGBDhw61iy++2Dp27BirXnnw4MFueo8ePaxSpUpWv359Gz58uI0fP96VcgBANMqa2isAAEheRYsWtVatWtnYsWMtEAi4/xcpUiRGi++JEyfsqquuCk7Lli2b1a5d29avX++u62+dOnViLLdevXoxrv/www+uxXjChAnBaXq806dP2+bNm61KlSq8tACiDuEYANJpaYVf3vDGG2+kyGMcOnTI7r33XldnHI7OfwCiFeEYANIh1QIfP37cDd+mWuJQKpfInj27K7coV66cm6aWZHXIU4mEqNX3008/jXG/b7/9Nlbnv3Xr1rl6ZQBIL6g5BoB0KEuWLK40QuFV/w+VJ08eu//+++3xxx+3WbNmuXnuvvtuO3LkiHXt2tXNo7GSf/31VzfPhg0b3FBwKtMI9cQTT9iSJUtcC7U67Wn+6dOn0yEPQFQjHANAOpUvXz53ieSFF15wo0zcfvvtrgX4t99+s9mzZ1vBggWDZREazWLatGl26aWX2siRI23QoEExllGjRg1buHCh/fLLL244Nw0V169fPytVqtQ5eX4AkBIyBdR7AgAAAAAtxwAAAICPsgoAAADAQzgGAAAAPIRjAAAAwEM4BgAAADyEYwAAAMBDOAYAAAA8hGMAAADAQzgGAAAAPIRjAAAAwEM4BgAAADyEYwAAAMD+n/8P72hcd3Noo6MAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# ==========================================================\n", "# 3️⃣ Visualisation comparée (F1 & Accuracy)\n", "# ==========================================================\n", "plt.figure(figsize=(8,5))\n", - "sns.barplot(data=metrics_summary, x=\"Model\", y=\"F1_score\", hue=\"Strategy\")\n", + "sns.barplot(data=metrics_summary, x=\"Model\", y=\"f1\", hue=\"Strategy\")\n", "plt.title(\"📊 Comparaison du F1-score par modèle et stratégie\")\n", "plt.ylabel(\"F1-score\")\n", "plt.legend(title=\"Stratégie\")\n", @@ -134,10 +415,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 70, "id": "79e40869", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\IPython\\core\\pylabtools.py:170: UserWarning: Glyph 128200 (\\N{CHART WITH UPWARDS TREND}) missing from font(s) DejaVu Sans.\n", + " fig.canvas.print_figure(bytes_io, **kw)\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAArMAAAHXCAYAAACvatLKAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAASD5JREFUeJzt3QeYFFX29/EDQwbJmSUKEpQkYUAJBhQVBRQFWRREDGsAWdZVMICAMoigLMLKihIMCKIsuKgoIqAoihIESQoCg5JXyRKEfp/fff/V29PTk2Bmemrm+3meZujq6urbVdXVp0+deytXIBAIGAAAAOBDuaPdAAAAAOBsEcwCAADAtwhmAQAA4FsEswAAAPAtglkAAAD4FsEsAAAAfItgFgAAAL5FMAsAAADfIpgFACCdzJs3z5599ln7448/WKeZ6NSpUzZy5Ej7z3/+w3rPgQhmgWzgjjvusGrVqpmfPPXUU5YrV650W97UqVPd8rZt25ZuywSSsnjxYre/6W+oFi1a2KuvvmqPPfZYks9lX01/AwcOtFdeecWt/7N12WWXuRv8h2AWWdqhQ4ds6NCh1rBhQytSpIgVLFjQLrroInv00Udt586d0W4efBJwKHCO5J///Kd7PDY2NtPbhuypdOnS9uGHH9q0adOyXJbw2LFj7rMQHoCfiw8++CDJz1dmtXfu3Ln2xhtv2Pz5861MmTIZ0hZkbXmi3QBkT+vWrbPGjRtbvnz5Ij5+8uRJ27Bhg51//vlJLuOnn36ydu3aWXx8vN1yyy12zz33uOWtWbPGZT7+/e9/2w8//JCB78I/Jk2aZGfOnIl2M7KcgwcPur9JZa3ffPNN99jy5ctt8+bNVrNmzUxuIbIjHdcU0C5dutSyEgWHSg5IemUgFcxOmDAhQwLa1LZXZ2O0vs/18/vxxx+f0/MRPQSzyBCBQMCaN2+e5MFcp4I0T1JUb3bTTTfZnj173K/yVq1aJXj8mWeecXVp2ZUO4oUKFUr1/Hnz5s3Q9vjVZ5995oLVHj16JHps69at9uWXX9rs2bPt3nvvdYHtkCFDLCs6evSoFS5c2HKatH4OspKLL77Y3ZDwuK4f3UklOc7WQw89lC7LSe92IfNQZoAs6d1337XvvvvOHn/88USBrBQtWtQFtKFmzZplTZo0caUIOtV322232S+//JKotlTlCsr2Xn/99e7/lSpVcpkFWbt2rV1xxRUucKhatapNnz49Yq2bgiQFQKVKlXJt6dmzp/3222+JTn116NDBKlasaPnz53fZmuHDh9vp06cTzKeMg0onVqxYYW3atHFf3l69XWqXEalmdsaMGW59nHfeea6N9evXt3/84x+Jst/KepcsWdK9rn5kvP/++xFP1b/99ttunf/pT3+yAgUK2JVXXumymamhHzXNmjVzz9N7+Ne//pXkvDpd6G1HtevWW2+1HTt22NlYsmSJ24ciBfsKXkuUKOHW78033+zuR3LgwAH761//6tavtoHev7b3/v37g/McP37cZaYuuOAC9x4rVKjgfoxt2bIl2fpKZZQ0XftV+D6q51533XVu+3nB+Oeff+62V5UqVVxbKleu7Nr2+++/J2r3xo0brWvXru60q9Zl7dq13bqQRYsWudfV2Y1w2uf12LJly5Jcr5n9OYjkXD/Lqd3/5eeff7bOnTu7ZZUtW9at8xMnTkRs19dff23XXHONFStWzC1T70XbLTWUXWzdurV7HW13rTed5UoN7af9+/d3+4TWs7KU+sHvnbHRvuadgle2U9svuRIcr1OV5q1Vq5bbr7WddTxesGBBcBt469tbnlcH7+3bo0ePtrFjx7rtrnatX7/enZkbPHiw+5xrPen96n1rv/Skpr3ax/XZ1fZT+5o2bWrvvfdeovehs3lt27Z1nwN9fp9++mmbMmVKohr7SDWz2s76kav16X3mHnnkkSS3P6KDzCyyJO+AdPvtt6dqfn259u7d2wVMcXFxLqOrwO2LL76wVatWWfHixYPz6kv02muvdV8yo0aNckHMgw8+6A6o+rJX4KBAZOLEie7LuWXLlla9evUEr6f5tUwdWDdt2mQvvfSSbd++PRi0eG3SF+yAAQPc308//dQdwFUH/NxzzyVY3n//+1/XJgVuCsLLlSuX5mWE0pdN9+7dXcDpZbBV1qH14WUxtI4uueQSl/3q16+f+6JSnV/Hjh3tnXfesRtvvDHBMtVTOHfu3Pbwww+70/dad1pX+vJOjoKKq6++2n0xaX0pO6MvB+89hlKw/OSTT7og7K677rJ9+/bZiy++6LZV+HZMjW+//TbJx7TdtZ2VjdG60jb85ptv3D7kOXLkiPuS1bq78847XaZNQaz2TwU4+tGk/UnB1MKFC9320/o9fPiw2wbff/99sqU0SdE6at++vQscFAx42Un9YNP2uu+++9z2UnmE1o/aosdCv7zVbgXxKs9RIK7gWDWcWsf6wtaXstZB+HbWNLVZ+31KMutzkJRz+Syndv/XDwV9jhQ0az4F5a+//rp7H+E0Te1RiZX2cX1eFDTp+fphldw61TJ79erltrs+s2qX1qf2Ae37yXXw1LwK1vTjXT8u9GNHZx0GDRpku3btcsGkPn9anvYdvTetF2nQoEGSy9V21fFUn0WdadM202dq5cqVdtVVV7nXUt8F7etqfyR6//qxp/1QwaACTy1HnbX0ubv77rvd50WlY3rv2qcbNWqUYnsV5F966aXuB4w6f2mb6we3fnQoGeJtP62Tyy+/3O2PWh+aT6+ttqREPwS0P+jHuNpft25ddzx74YUXXInbnDlzUlwGMkkAyABr164NXHrppUk+HhsbG/jxxx+TfLxx48aBYsWKpeq1Tp48GShbtmzgoosuCvz+++/B6fPmzVMdQ2Dw4MHBab169XLTRowYEZz222+/BQoWLBjIlStXYMaMGcHpGzdudPMOGTIkOG3KlCluWpMmTdzrekaNGuWmz507Nzjt2LFjidp67733BgoVKhQ4fvx4cFrbtm3dcydOnJho/tQuQ++ratWqwfsPPfRQoGjRooE//vgjyfXWv39/97qff/55cNrhw4cD1atXD1SrVi1w+vRpN23RokVuvrp16wZOnDgRnPcf//iHm65tnZzOnTsHChQoENi+fXtw2vr16wMxMTHu+Z5t27a5ac8880yC52v5efLkSTQ9nLdttm7dGkjJt99+6+ZdsGCBu3/mzJnAn/70J7feQmnf0XyzZ89OtAw9RyZPnuzmef7555Ocx1uH+htKbdV0tT18Hx04cGCq9oe4uDi374au3zZt2gTOO++8BNNC2yODBg0K5M+fP3DgwIHgtL1797p1HbrPR5LZn4NIzvWznNr9f+zYsW6+t99+Ozjf0aNHAzVr1kywTbVua9WqFbjyyisTrGe9fy1P05PaV/W6xYsXD9x9990J3uPu3bvdcTB8erjhw4cHChcuHPjhhx8STNc+pM9UfHy8u79v375E6yE5DRs2DHTo0CHZeR544IEEn+PwfVvHIe1XoXRcCj2WeNuuXLlygTvvvDM4Lbn2an3Wr18/wT6k9X7JJZe47eDp27ev2x9WrVoVnPbf//43ULJkyUTHC+2Dunle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++67rXfv3lavXj0X1GpYrMmTJyf5HAWvCp68W7ly5cxvdEr+888/t2effdYuv/xyq1q1qjVv3twGDRpkHTt2dJlqufHGG9379e4/9dRT1qhRI3vllVesevXqwaz0/PnzrVWrVla8eHErVaqUXX/99bZly5bg62leady4sVveZZddFnxMy6pbt65bVp06deyf//xngrZ++eWX7jX1eNOmTV22ODTLG6nMYOnSpda6dWs3TJaGOuvXr58dPXo0Q9cpAADIeaIazCqruGLFCmvXrt3/GpQ7t7u/bNmyJJ935MgRF/wpSOrUqZOtW7cuyXlPnDhhhw4dSnDLCooUKeJuCgzVxnDffPON+ztlyhR3Ct+775UEqL519uzZwYBSgaIy3N9++63L7mo9KhDWuLnilW588sknbnl6rrz55ps2ePBge+aZZ1xmdsSIEfbkk0+6bLFofd1www1Wv359W7lypQ0fPtweffTRZN+bguhrrrnGZZ7XrFnjsu8Kbh988MF0W38AAABRLzPYv3+/nT59OlFmVfc3btwY8Tm1a9d2WdsGDRrYwYMHbfTo0a5mUwHtn/70p0Tzx8XF2dChQy2ryZMnj6v/VVZa2eiLL77Y2rZta7feeqt7b2XKlHHzKdMafgpfPwJee+214DyiwDGU1pEeX79+vV100UXBeZW1DV3ekCFDbMyYMXbTTTcFM7h6zr/+9S/r1auXTZ8+3WVdJ02a5DKzyp7/8ssvrt1J0Trv0aOH9e/f393XVbjGjRvn3t9LL73k2xpnAJHFD6vPqgGyqSqD11pWF/Uyg7Rq2bKl9ezZ0532VnCkDKMCNQVfkei0vYJe77Zjxw7LKhSA7ty509577z2XydTpegW1CnKTo6x0aCArP/74o3Xv3t3V3qqm2CtLiI+PT3I5yuYqi9qnT59gpli3p59+OliioNpkBdehAajKIZLz3XffufcQukzVQXuXCwYAAMgWmdnSpUtbTEyM6/gUSvdT26FIly1VHahOvUeiUQJ0y6oUJF511VXuptP7d911l8uW3nHHHUk+p3DhwommqRRAQa4yqBUrVnSBozKyyuImV64heo4634XSdjlbWu69997r6mTDaeQGAACAbJGZVS/4Jk2auBpPj4Iw3VcGNjVUprB27VqrUKGCZQc6je91lFKgrveXEo1+oAyqhta68sorXWeu3377LcE83ogHoctTOYcC359++smNZhB68zqMqaxD6ze0rje0fjcSZZdVqhC+TN3SY+QFAACALFNmoE5Lygyqw5E6IGncVQVzGt1AVFKgUgHPsGHD7OOPP3YBmDok3XbbbbZ9+3aX0fQTBaBXXHGFvfHGG66TlE6/z5o1y120QJ3aRKUCCux3796dKDgNpXFhVQv78ssvuwz1p59+6tZrKA1zppEFNOqBMt8quRDVE6vGVTWtP/zwgwtc1elMo0zIn//8Z/cD45577nHb56OPPnJ1yskNiaYOYhoBQR2+1EFNJRBz586lAxgAAMh+wWy3bt1ccKQe9aqDVfCjgMvrFKaaT/W+9yioU+cjZR+vu+4619tegZMymn6iOlKd2n/hhResTZs2riRAZQZ6b+PHj3fzqGPWggUL3KgNKqVIikYumDFjhhsZQsv561//as8991yiDmcKWFVbrGysFzDrR4CG5lIAqxELVIeselcvM6v62//85z9uu2j7PP74425bSVIduVRju2TJEhcca3gutV3P0esCAACkp1yBQCBgOYiCX12pSplJBWqhjh8/7jKkoeO3IjEN56XMudahsr1ZEdsSyDyMZgBkX1WiNJpBcvFalrsCGLI+DQOmURIqVarkRipQGUHXrl2zbCALAAByDoJZpEg1uyoT0F91tLvlllvcRRYAAACijWAWKXrkkUfcDQAAIKuJegcwAAAA4GwRzAIAAMC3CGYBAADgWwSzAAAA8C2CWQAAAPgWwSwAAAB8i2AWCVSrVs3Gjh3LWgEAAL7AOLOp1OTvr1lmWvFczzTNf9lll1mjRo0SBaJTp061/v3724EDB9K5hQAAANFHZhYAAAC+RTCbg9xxxx3WuXNnGz16tLssbalSpeyBBx6wU6dOJfmcV155xYoXL24LFy4MZoD79evnrghWsmRJK1++vD311FMJnhMfH2+dOnWyIkWKWNGiRa1r1662Z88e99jBgwctJibGvv32W3f/zJkzbjktWrQIPv+NN96wypUru/9v27bNcuXKZbNnz7bLL7/cChUqZA0bNrRly5ZlyDoCAAD+QjCbwyxatMi2bNni/k6bNs2VIegWyahRo2zgwIH28ccf25VXXhmcrucVLlzYvv76azfPsGHDbMGCBcHgVIHsr7/+akuWLHHTf/rpJ+vWrZt7vFixYq4cYvHixe7+2rVrXbC6atUq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9WB25syZNmDAABsyZIitXLnSGjZsaO3bt7e9e/dGnL9kyZL2+OOP27Jly2zNmjXWu3dvd/voo48yve0AAACIrlyBQCAQzQYoE9usWTMbP368u3/mzBmrXLmy9e3b1wYOHJiqZVx88cXWoUMHGz58eIrzHjp0yIoVK2YHDx60okWLnnP7ASCnix9WP9pNAJBBqgxea9GQlngtzZlZlQMMGzbM4uPj7VydPHnSVqxYYe3atftfg3LndveVeU2J4vCFCxfapk2brE2bNufcHgAAAPhLmoPZ/v37u7rVGjVq2FVXXWUzZsywEydOnNWL79+/306fPm3lypVLMF33d+/eneTzFKUXKVLE8uXL5zKyL774omtLJGqbovvQGwAAAHJwMLt69WrXSatu3bquHKBChQr24IMPuprXzHDeeee5NnzzzTf2zDPPuJrbxYsXR5w3Li7Opam9m0oYAAAAkMM7gKlOddy4cbZz507XeeuVV15xta8aXWDy5MmuBCAlpUuXtpiYGNuzZ0+C6bpfvnz5pBudO7fVrFnTvdbf/vY3u/nmm13QGsmgQYNcJte77dix4yzeLQAAALJVMHvq1Cl7++23rWPHji6g1HBZCmi7dOlijz32mPXo0SPFZahMoEmTJq7u1aMOYLrfsmXLVLdFz0mq1CF//vyucDj0BgAAgOwhT1qfoFKCKVOm2FtvveUypD179rQXXnjB6tSpE5znxhtvdFna1FCJQK9evVww3Lx5cxs7dqwdPXrUDbclWn6lSpWCmVf91bznn3++C2A/+OADN87sSy+9lNa3AgAAgJwWzCpIVWcrBY+dO3e2vHnzJpqnevXqduutt6Zqed26dbN9+/bZ4MGDXacvlQ7Mnz8/2ClMoyYoaPYo0L3//vvt559/toIFC7og+o033nDLAQAAQM6S5nFmt2/fblWrVjW/YpxZAEhfjDMLZF9VsuM4s7oy19dff51ouqZ9++23aV0cAAAAcNbSHMw+8MADEUcE+OWXX9xjAAAAQJYNZtevX++G5QrXuHFj9xgAAACQZYNZDXUVPi6s7Nq1y/LkSXN/MgAAACDzgtmrr746eCECz4EDB9zYskldUhYAAADICGlOpY4ePdratGnjRjRQaYHo0rIaSkvjvQIAAABZNpjVBQzWrFljb775pn333XdurFdd4KB79+4Rx5wFAAAAMspZFbkW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YTfddJPdcMMNtnr1arvrrrts4MCBCZaxZcsWu+aaa6xLly62Zs0amzlzpgtuH3zwwUx6pwCQ/ghmASDKbrvtNhdUbt++3d2++OILN82jzOlLL71kzz33nF177bVWr149mzRpksuuvvrqq24ePX7++efbmDFjrHbt2tajR49E9bZxcXFuev/+/a1WrVp2ySWX2Lhx4+y1115zpQ0A4Ed5ot0AAMjpypQpYx06dLCpU6daIBBw/y9dunSCjOqpU6fs0ksvDU7LmzevNW/e3DZs2ODu629sbGyC5bZs2TLB/e+++85lZN98883gNL3emTNnbOvWrVa3bt0MfJcAkDEIZgEgi5QaeKf7J0yYkCGvceTIEbv33ntdnWw4OpsB8CuCWQDIAlTLevLkSTccl2phQ6l8IF++fK78oGrVqm6aMrXqAKaSAVFW9b333kvwvK+++ipRZ7P169e7elsAyC6omQWALCAmJsaVCijY1P9DFS5c2O677z77+9//bvPnz3fz3H333Xbs2DHr06ePm0dj1f74449unk2bNrmhvVS2EOrRRx+1L7/80mWA1UlM88+dO5cOYAB8jWAWALKIokWLulskI0eOdKMQ3H777S7DunnzZvvoo4+sRIkSwTIBjXYwZ84ca9iwoU2cONFGjBiRYBkNGjSwJUuW2A8//OCG59LQX4MHD7aKFStmyvsDgIyQK6DqfwAAAMCHyMwCAADAtwhmAQAA4FsEswAAAPAtglkAAAD4FsEsAAAAfItgFgAAAL5FMAsAAADfIpgFAACAbxHMAgAAwLcIZgEAAOBbBLMAAADwLYJZAAAAmF/9P/WP7ai8sG2aAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "plt.figure(figsize=(8,5))\n", "sns.barplot(data=metrics_summary, x=\"Model\", y=\"Accuracy\", hue=\"Strategy\")\n", @@ -157,17 +457,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 71, "id": "0c4560e9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🏆 Meilleur modèle : Unknown (Unknown)\n", + "F1 = 0.000 | Accuracy = 0.000\n" + ] + } + ], "source": [ "# ==========================================================\n", "# 4️⃣ Sélection du meilleur modèle\n", "# ==========================================================\n", "best_run = metrics_summary.iloc[0]\n", "print(f\"🏆 Meilleur modèle : {best_run['Model']} ({best_run['Strategy']})\")\n", - "print(f\"F1 = {best_run['F1_score']:.3f} | Accuracy = {best_run['Accuracy']:.3f}\")" + "print(f\"F1 = {best_run['f1']:.3f} | Accuracy = {best_run['Accuracy']:.3f}\")" ] }, { @@ -180,14 +489,74 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 72, "id": "5a5650c0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Erreur lors du chargement du modèle: Failed to download artifacts from path 'model', please ensure that the path is correct.\n", + "Passage à la suite sans modèle\n" + ] + } + ], "source": [ "# Charger le modèle depuis MLflow\n", "model_uri = f\"runs:/{best_run['Run_ID']}/model\"\n", - "best_model = mlflow.sklearn.load_model(model_uri)" + "try:\n", + " best_model = mlflow.sklearn.load_model(model_uri)\n", + " print(\"Modèle chargé avec succès\")\n", + "except Exception as e:\n", + " print(f\"Erreur lors du chargement du modèle: {e}\")\n", + " print(\"Passage à la suite sans modèle\")\n", + " best_model = None\n" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "log_analysis", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Analyse du modèle ignorée\n" + ] + } + ], + "source": [ + "if best_model is not None:\n", + " # Logger les métriques et graphiques dans MLflow\n", + " with mlflow.start_run(run_name=\"Model_Analysis\", experiment_id=experiment.experiment_id):\n", + " mlflow.log_metric(\"test_accuracy\", accuracy_score(y_test, y_pred))\n", + " mlflow.log_metric(\"test_f1\", f1_score(y_test, y_pred, average=\"macro\"))\n", + " mlflow.log_metric(\"test_auc\", roc_auc)\n", + " \n", + " # Logger la matrice de confusion\n", + " cm_fig = plt.figure(figsize=(6,6))\n", + " ConfusionMatrixDisplay(cm).plot(cmap=\"Blues\")\n", + " plt.title(f\"Confusion Matrix - {best_run['Model']} ({best_run['Strategy']})\")\n", + " mlflow.log_figure(cm_fig, \"confusion_matrix.png\")\n", + " plt.close(cm_fig)\n", + " \n", + " # Logger la courbe ROC\n", + " roc_fig = plt.figure(figsize=(6,6))\n", + " plt.plot(fpr, tpr, label=f\"AUC = {roc_auc:.3f}\")\n", + " plt.plot([0,1], [0,1], linestyle=\"--\", color=\"gray\")\n", + " plt.title(f\"ROC Curve - {best_run['Model']} ({best_run['Strategy']})\")\n", + " plt.xlabel(\"False Positive Rate\")\n", + " plt.ylabel(\"True Positive Rate\")\n", + " plt.legend()\n", + " mlflow.log_figure(roc_fig, \"roc_curve.png\")\n", + " plt.close(roc_fig)\n", + " \n", + " print(\"✅ Métriques et graphiques loggés dans MLflow\")\n", + "else:\n", + " print(\"Analyse du modèle ignorée\")\n" ] }, { @@ -200,7 +569,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 74, "id": "5def0dc4", "metadata": {}, "outputs": [], @@ -220,16 +589,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 75, "id": "e336a62f", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Analyse du modèle ignorée\n" + ] + } + ], "source": [ - "# ==========================================================\n", - "# 5️⃣ Visualisations de performance du meilleur modèle\n", - "# ==========================================================\n", - "y_pred = best_model.predict(X_test)\n", - "y_proba = best_model.predict_proba(X_test)[:,1]" + "if best_model is not None:\n", + " # ==========================================================\n", + " # 5️⃣ Visualisations de performance du meilleur modèle\n", + " # ==========================================================\n", + " y_pred = best_model.predict(X_test)\n", + " y_proba = best_model.predict_proba(X_test)[:,1]\n", + "else:\n", + " print(\"Analyse du modèle ignorée\")\n" ] }, { @@ -242,10 +622,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 76, "id": "70a4c1bc", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'y_pred' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[76]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# Matrice de confusion\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m cm = confusion_matrix(y_test, \u001b[43my_pred\u001b[49m)\n\u001b[32m 3\u001b[39m ConfusionMatrixDisplay(cm).plot(cmap=\u001b[33m\"\u001b[39m\u001b[33mBlues\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 4\u001b[39m plt.title(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mConfusion Matrix - \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mbest_run[\u001b[33m'\u001b[39m\u001b[33mModel\u001b[39m\u001b[33m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mbest_run[\u001b[33m'\u001b[39m\u001b[33mStrategy\u001b[39m\u001b[33m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m)\u001b[39m\u001b[33m\"\u001b[39m)\n", + "\u001b[31mNameError\u001b[39m: name 'y_pred' is not defined" + ] + } + ], "source": [ "# Matrice de confusion\n", "cm = confusion_matrix(y_test, y_pred)\n", @@ -267,7 +659,18 @@ "execution_count": null, "id": "482c0a34", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhgAAAIjCAYAAABBOWJ+AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAZ51JREFUeJzt3QV4U1cfBvA3dYMixSnu7s5gDCiDMXTo0AJjwz6YIAMKQ7cxBkOGuzsMGAy34e4MirtLS/1+z/+wdG1pS1PSxt7f82Rrbu9NTk5C75tjV6dpmgYiIiIiI7Iz5oMRERERMWAQERFRkmALBhERERkdAwYREREZHQMGERERGR0DBhERERkdAwYREREZHQMGERERGR0DBhERERkdAwYRkRkZMmQIdDpdoo5t3749cuTIkaB9IyIiUKRIEYwYMQKW5PHjx3B3d8fGjRtNXRR6BwYMShZz5sxRfzT1NwcHB2TJkkX9Qbx9+3asx8gq9vPnz8cHH3yAVKlSwc3NDUWLFsUPP/yAgICAOJ9r9erV+Pjjj+Hl5QUnJydkzpwZzZo1w/bt2xNU1qCgIPz6668oX748PD094eLignz58qF79+64dOkSrJ28J1HfKw8PD+TKlQtNmzbFypUr1YnJFsiJWl5/zZo1Y/399OnTI+voyJEjsDSLFy/GzZs31efakqRNmxadOnXCoEGDTF0UegeHd+1AZEwSDnLmzKlO4gcOHFDBY+/evThz5ow6keuFh4ejVatWWLZsGapWraq+1UnA2LNnD4YOHYrly5dj69atyJAhQ7RA0rFjR/WYJUuWRJ8+fZAxY0bcvXtXhY6PPvoI+/btQ6VKleIs36NHj1CnTh0cPXoUn3zyiSqDnGAvXryIJUuWYNq0aQgJCbH6D4WzszNmzJihfn79+jWuX7+OP/74Q4WM6tWrY+3atUiZMiWsnXwmd+zYgXv37qnPUlQLFy5Uv5fPsiX6+eef0aJFCxWiLU3Xrl3x22+/qS8NNWrUMHVxKC5ysTOipDZ79my5qJ52+PDhaNv79u2rti9dujTa9pEjR6rt33zzzVuPtW7dOs3Ozk6rU6dOtO0///yzOuZ///ufFhER8dZx8+bN0w4ePBhvOevVq6cee8WKFW/9LigoSPv66681YwgNDdWCg4M1c9SuXTvN3d091t+NGjVK1XGzZs00a5c9e3bto48+0lKmTKmNGzcu2u9u3rypPidNmjSJ9XP9Pvz8/NRjJva9k3K/y7Fjx9RzbN26VbNURYoU0dq0aWPqYlA82EVCJiWtE+LKlSuR2+Qbs3y7km6JUaNGvXVM/fr10a5dO2zatEm1guiPkX0LFCiAMWPGxNqH3aZNG5QrVy7Oshw8eBAbNmyAr68vmjRpEuu3enlsPfkmL7d39YNfu3ZNlUeOHTduHHLnzq0e6/jx46qrSFpkYpIWEzlm4sSJkduePXuG//3vf/D29lbH58mTBz/++GOydln069cPtWvXVi1IUbuLpKzSyhST1IPUR8yuMmm16tmzJ9KlS6e6v7744gvVMiSvsW3btkidOrW6fffdd6plKra6nDRpkuq6kZYtKZM098u+w4YNQ9asWeHq6ooGDRrgyZMnkcfL50a6zkJDQ98qqzxG/vz5o22TForGjRtj0aJFb3UvSPl8fHxirSf5Zi2fbRkrIK9PynH+/Pm39pN6KFu2rHoe+VxMnTo1zrpfsGABSpcurV5XmjRpVOuDvObEWLNmjeo+lO7H2MZ/XL58Wb1vUnZp4ejQoQMCAwOj7RsWFqbqWv95lvd6wIABCA4OjrafbJfWQHmt8u9PXqu8b/PmzXurXIZ8xmvVqqVa1XhBcPPFgEEmJScMIX+s9eQP0dOnT1X3hJyAYyMnIbF+/frIY+REIsfY29snqizr1q2LDCJJYfbs2ZgwYQK6dOmCX375BZkyZUK1atVUN1BMS5cuVa/js88+U/flj7vsKycZee3SPFy5cmX0799fdQUlJ6kf+aO+ZcuWRD9Gjx498M8//6hw9emnn6quJ+lTl/Ao3WMjR45ElSpVVNCUcTgxSffE5MmT1eN8/fXX2LVrlxpnM3DgQBU8+/btq+pZTkDffPNNtLLLIMHNmzdHezzpApFQ8Pnnn7/1XPKZOnToULQQLIFDuoscHR3f2l+67iR4PHjwQJ2w5f35+++/1ful/7yL06dPq1Cj309O4n5+fqo7LyYZiCnve968eTF27Fh1Et62bZsKCHJSNpSURwZ4xlZ+IXX58uVLFdrlZwmGMYOwjIMYPHgwSpUqpcYsyedT9pfgE5MEFqkvCQXy2Zd/7xJgzp49G7mPoZ9xCVvy2qM+BpmZ+Jo3iIzdRSJNsg8fPlRNzNINkS5dOs3Z2Vnd15PmaNl39erVcT7ekydP1D6NGzdW98ePH//OY96lUaNG6jGePn2aoP2rVaumbu9qpr569ap6XGlqf/DgQbR9p06dqn53+vTpaNsLFSqk1ahRI/L+sGHDVLfFpUuXou3Xr18/zd7eXrtx44aWHF0k4vjx46rMvXv3jtwm96VpPyapB3m8mJ8DHx+faN1YFStW1HQ6nda1a9fIbWFhYVrWrFmj1bG+LuVz8+zZs8jt/fv3V9uLFy+uup/0WrZsqTk5OanuLREeHq4es3nz5tHKOXbsWPX8/v7+0couXWZSjowZM6r3QJw7d049165du2Lt+itRooSWPn167fHjx5HbTp48qbpU2rZtG7mtYcOGmouLi3b9+vXIbfLY8n5G/dN87do1tW3EiBHRyiyfGQcHh2jbE9pFInUg3Ttxdc907NjxrX8badOmjbx/4sQJtV+nTp2i7SddmrJ9+/bt0epRtu3evTtym/w7kH/3UbscDf2M//3337F2r5L5YAsGJSsZkS/N4tIEKt9opAlZWg6kSVtPvjmJFClSxPk4+t+9ePEi2v/jO+ZdjPEY8ZFuF3ntUUnzu7TSSIuFngx4PXfuHJo3bx65TbokpMldvvnJQFT9TepTvvHv3r0byUUGvUZ9nxJDuqGidmPJjB3JKbJdT1pwypQpA39//7eOl5adqIMT5XghLRBRW71ku3S96Gcq2dnZoXXr1uozF7X80iIig39lAHJMUg75Fi/dIvp95fOr796LSgYUnzhxQn07l24MvWLFiqlv7/qplfKeSStKw4YNkS1btsj9ChYs+Fa3y6pVq1QXgZQh6nsvg06lRUMGoRpKWnGithrGNogyKnmtcoz+34j+dcRsWZDWJCFdjVEVKlQoWn3JvwPpjor63hr6GdeXX/Yh88SAQclK+s2laX3FihWoW7eu+uMgfa1R6U/w8Z3AYoYQ/YyG9znpGeMx4hPbyUvGA8jslqjdJBI25CQp4UNPuhOk6V/+MEe96adQSjN7XJ4/f666APS3qGMSEuPVq1fvHcSinlSFPizIiTvmdukue5/jRdTHkOZ3GbOj74qQ8S4yayi+rjHpJpHQd/LkSdU9It0AsY3zkdk2IuZYDn14kM+7TLF++PChKoMEhJhiHivvvYQv2Tfm+y/jOuJ77+MT39iFmPWrP5nr61Fep4Q1GSMRlYQeGbehr4e4Hk//mFHfF0M/4/ryJ3bNEEp6nKZKyUoGecm3UiHf3qSfXf54yx95/Tdj+UMsTp06pfaJjfxO/81IyOBOfb92XMe8S9THiO3baUzyhy22P9LybSs2MjgvNnKykv53+eZbokQJFTYkdEj40JNvsPINWAY9xkYGxMalV69emDt3buR96efeuXMnEktaWETMk0ts4qqLuMbJxLY9tjo25PiYjyGfGem/1/f1y/9lwKO0EMRFWkJkMKOMfbh69ar6zCYXee/ls/bnn3/G+vr0/24MXUsituBmSD0acnJPyOMZ+hnXlz/qvxMyLwwYZDLyR0cGhX344YdqtoTMUBASOuRbkHxT/P7772P946QfgS6j0/XHyDciacaWkeyJGegpAwylPHLCSUjAkOeLrfk+5re3d5FAJLMo9N0kMjtDBrZFJSc3aTmIa9Gn+Mgf7KiDF+NrGk8IGXQpJxY5GUR9zJiDDaVrQroMzJEEC2nel/LJ56xevXrvrJeWLVti+PDhKgBLEIxN9uzZ1f8lMMd04cIFdTKUbkGZSSGBU761xxTzWHnv5UQsLWDxBUlDw7QEpcSS1ymBQMqv/0Ig7t+/rz4H+nowhKGfcX35oz4/mRd2kZBJyTRPadWQ6Zv6BYtk2qGM/Jc/tBIwYpL+XRnVLn3VFSpUiDxGZg5Ik7H8P7ZvvRIcZDZAXCpWrKgW2ZIFpmQaX0xywow6I0H+IMpJQ5q79aQJXRbzMoSEKXkt0nIhi3nJt+mYrTDy7Xr//v1vzX4Q8gddpgzGRb6xyx9t/U2+vSfW6NGj8ddff6nxIVGb96UuYvaRy8yQuFowTE3CgoQkad2RkBjb7JGYZNaEzPKQWRBxkZlBEj6kxShq4JJWH6k36RYUEoDlPZfP2Y0bNyL3k89vzPdYuspkf5nFEfNzLfdlbISh5LMuZYo5pTSh9K9D/t1GJTNchAQ2Qxn6GZduLekCK1y4sMHPRcmDLRhkct9++60atCehQT+4TFozZJ0ImQMvf3RkgKR845PpqBIU5FtL1GZ//ePIlDU5AcjANxlEKn3CMu5A/pBLuJDpefGRlhGZOih/1KVFQ7oq5BunfFOTk79849WvhSGrhsofVDlRyOBE6SOeMmWK+oOnHwyXUHLClpOcTL2Ux5PQEfO1ycBEabGRAYQSEqQvX7pzZDyLTH80ZlOx/DGXehYS/KRVRp5fuqakxUnCQ8yTr7x38j5Jy4YELTlRmGvztfTtS5iUgYVS1wk5Icq38tjW+ohJptbKUvVyEpfPhYy1kOnJcjKMerwEBhlzIK1lX331lapz2U8+P/ouQH14k5YTadWS91nCp4x/kW/wMo5EpuNGDb4JIetyyBoWMr1XPu+GKl68uFpTRD4HcvKXbjf59yX/JqV88hkxlKGfcRnLJf9GOQbDjJl6GgvZ9kqe+qmDuXPnVjeZEhh1uxxXuXJlNcVTpvQVLlxYGzp0qPbq1as4n0umv9auXVtLkyaNmsaXKVMmNS1x586dCSprYGCgNmbMGK1s2bKah4eHmuaYN29erUePHtrly5ej7btgwQItV65cah+Znrh58+Y4p6nKSqNxefHihebq6qr2k8eMzcuXL9V0zDx58qjn8/Ly0ipVqqTKGhISohmLlF/Kob+5ublpOXLkUNMapW7lfYlJtsmqrFIm2V+moUpdxTVNNebnQD89UqYwxzdlNq663LFjh9q+fPnyBH/uli1bpn7XpUuXWOtBP001PnE9vkzHls+tvKfy2a1fv76aghqTTHUtXbq0ej/lczRlypQ4V/JcuXKlVqVKFVUfcitQoIDWrVs37eLFiwZPUxXFihXTfH19E/Q+6F+n1L+eTAeWf4s5c+bUHB0dNW9vb/X51E8Jflc9xjbNO6Gf8fPnz1v8SqS2QCf/MXXIISJKbnI9Ffm2LV07CRlzY21kLE23bt1UF03MFjNzJ4Nt5X2TbhK2YJgvBgwisknSFC9jHmSVSVs8SckgTVmfQ8ajxDbWyVzJmBPprpIxS/qxIGSeOAaDiGyKjKWRMQ4yWHj8+PE2GS6ErGOhn3JsSWSKrX4tFjJvbMEgIpsigULWjpCBtTIoN67r3RDR++G/LCKyKRx2RpQ8uA4GERERGR0DBhERERmdgy2OnL5z545aqMZWB3cREREltotRLgiZOXNmNVA4PjYXMCRcxLziIhERESXczZs3kTVr1nj3sbmAob/EtFSO/vLcRERE9G5yGQT5kq4/l8bH5gKGvltEwgUDBhERkeESMsSAgzyJiIjI6BgwiIiIyOgYMIiIiMjobG4MRkKn4YSFhSE8PNzURSEz5ejoCHt7e1MXg4jIbDFgxBASEoK7d+8iMDDQNO8IWcwAJ5miJde0ICKitzFgxFiE6+rVq+qbqSwi4uTkxMW4KNYWrocPH+LWrVvImzcvWzKIiGLBgBGj9UJChszxdXNzi62+iJR06dLh2rVrCA0NZcAgIooFB3nGVinvWP6UiMvMExHFj2dSIiIiMjoGDCIiIjI6BgwiIiIyOgYMK7N//3416LBevXpv/W7nzp1q7MCzZ8/e+l2OHDkwbty4aNt27NiBunXrIm3atGrQa6FChfD111/j9u3bSVb+oKAgdOvWTT2nTAFt0qQJ7t+/H+8x7du3V68r6q1OnTrR9nny5Alat26trj+TKlUq+Pr64tWrV9H2OXXqFKpWrQoXFxc10Penn35KktdIRGQLGDCszMyZM9GjRw/s3r1bXZo+saZOnYqaNWsiY8aMWLlyJc6dO4cpU6bg+fPn+OWXX5BUevfujT/++APLly/Hrl271Gto3LjxO4+TQCHrl+hvixcvjvZ7CRdnz57Fli1bsH79elU/Xbp0iXaFwNq1ayN79uw4evQofv75ZwwZMgTTpk1LktdJRGTtOE01AWsevA41zYqero72Bs1WkG/kS5cuxZEjR3Dv3j3MmTMHAwYMMPh5ZX2Hnj17qtuvv/4arZXjgw8+iLUFxBgkvEhAWrRoEWrUqKG2zZ49GwULFsSBAwdQoUKFOI91dnZWYSg258+fx6ZNm3D48GGUKVNGbZswYYJqnRkzZoxa82ThwoVqmvKsWbPU+ieFCxfGiRMnMHbs2GhBhIiILCBgyLdI+aYo3xjlW+fq1avRsGHDeI+RZv4+ffqob6PSjD1w4EDVRJ5UJFwUGrwZpnDuBx+4OSX8LVq2bBkKFCiA/Pnz4/PPP8f//vc/9O/f3+ApldJ6ICfb7777LtbfSxdDXD7++GPs2bMnzt9LC4G8d7GRz4GsKyEtJ3ryerJly6a6fuILGPK5SJ8+PVKnTq3CyfDhw1U3i5Bjpcz6cCHkOWQ68sGDB9GoUSO1j4QnCRd6Pj4++PHHH/H06VP1uEREZCEBIyAgAMWLF0fHjh0T1Awuq2zK2IKuXbuqb5zbtm1Dp06dkClTJnUysHXy7V+Chb7LQFoEpJuhevXqBj3OP//8o8YqSL0aasaMGXj9+nW81/CIi7S6yAk+ZoDJkCGD+l1c5LXK5ydnzpy4cuWKarWRoKMfjyLHSviIysHBAWnSpIl8XPm/HB/zefW/Y8AgIrKggCEnAbkllIwBkJOAfgyANJ3v3btXNeMnVcCQbgppSTAFee6EunjxIg4dOqRagfQn0ObNm6vQYWjAkG6hxC4klSVLFiS3Fi1aRP5ctGhRFCtWDLlz51atGh999FGyl4eIyBycvfMcZ++8QLMy3iZ5fosagyHfSKM2nwsJFtIVEJfg4GB1izqYzxByojWkm8JUJEjIFWBlPEHUoCBjEyZOnAhPT0/VKiGkZSNmK4GMq5B9RL58+dQ+0m1laCvG+3SRyBgK6ZqRskQtn8wiiWt8RWxy5coFLy8vXL58WQUMOfbBgwfR9pG6kpkl+seV/8ecraK/b8hzExGZgzO3n6P1jIN4/joUKV0cUKeI4S3SNjWLRJqq9c3WenJfQkNczfKjRo1SJ079TcZtWBs5Wc6bN0+17MjARP3t5MmTKnDoZ1TIhblk3IGMdYjK399fBQoJFqJp06aqqyKuaZrxDfKULpKoZYh527hxY5zHli5dWnWhSNdX1JaZGzduoGLFigYNUn38+HFkOJJjpcxRX/f27dvVdWfKly8fuY+MCZIxIHoy40TGs7B7hIgsNVyUzJYKlfJ4maYgmpmQoqxevTreffLmzauNHDky2rYNGzaoYwMDA2M9JigoSHv+/Hnk7ebNm2p/+Tmm169fa+fOnVP/tyRSb05OTtqzZ8/e+t13332nlSlTJvJ+ly5dtBw5cmhr167V/P39tV27dmkVKlRQt4iIiMj9Jk2apOl0Oq1jx47azp07tWvXrml79+5Vx/fp0yfJXkvXrl21bNmyadu3b9eOHDmiVaxYUd2iyp8/v7Zq1Sr188uXL7VvvvlG279/v3b16lVt69atWqlSpdRnRd57vTp16mglS5bUDh48qF6H/L5ly5aRv5e6y5Ahg9amTRvtzJkz2pIlSzQ3Nzdt6tSpsZbTUj8rRGTddh2/qLX3m6Tl6LtOazRpr/bidYhRH1/OnXGdQ2OyqIBRtWpVrVevXtG2zZo1S0uZMqVRKsdSTxqffPKJVrdu3Vh/JydUeb0nT55U9+W1+fn5aQUKFNBcXV21nDlzqtDw8OHDt47dsmWL5uPjo6VOnVpzcXFRx8jJ/M6dO0n2WqR8X331lXpOOcE3atRIu3v3brR95PXMnj1b/SzBsnbt2lq6dOk0R0dHLXv27Frnzp21e/fuRTvm8ePHKlB4eHioz0uHDh1UOIlK6qhKlSqas7OzliVLFm306NHxltMSPytEZL12HjuvDfAbpg0ZMkT78qd5Rg8XhgYMnfwHZkDGOrxrmmrfvn1VE/vp06cjt7Vq1Ur1pcs6Bwkh3SnSVSJdAvoxCVFXkZSZKjKQVFZzJIoLPytEZE52HruALetWwEkXjgDHVOjXvRPSpHQ3+vPEdw41qzEYsjCUvm9eyMldfpY+dyFrOLRt2zZyf5meKuMFZH2GCxcuYPLkyWrtB1n9kYiIyBZtP3oeW5MhXBjKpAFDVpwsWbKkuglZQEt+Hjx4sLovsxj0YUNIy8KGDRvU4DtZP0MGNcqgQq6BQUREtmjbkXPY/sdKOP4bLvr36GwW4UKYdP6lrM8QXw+NLHUd2zHHjx9P4pIRERGZt0NXHmLL+jVwVeEiNfr36ITUKdxgLsx/gQciIiKK5uj1J+g47xg8QnOiSsonGNi9A1J5mE+4EAwYsTCTca9kxvgZISJTOeT/EB3mHEVASDiK5sqJH9p/ZpYLQppfiUxIf52MwMBAuLq6mro4ZMZkxVEh1zohIkoumw+ewdY/18MxNA8q5c6Kme3KwtXJPP8OMWBEIScLWaJav6y0m5tboq/JQdZLVgB9+PCh+nzINV+IiJLDpgOnsXfTGnjoIlAz9WMMa9fIbMOF4F/HGPTXnYh57QqiqGTJdbmMPAMoESWHP/efwr7Na+Goi0Cgc1r4dW9n1uFCMGDEICcMuYaFXN476nUpiKKSa7VIyCAiSmob95/C/ijhYmDPTkjhZv6LQTJgxNNdwv51IiIypfX7TuDglj/gIOHCxQsDe/haRLgQ/ApGRERkhvb98xDr/9oRGS4GWUjLhR5bMIiIiMzMvsuP4DvvCMJDc6N+huf4oWszeLg6w5IwYBAREZmRLSf80X3FRQSHRaBGgUwY9Xk9ODuY94DO2DBgEBERmYk1u47h6I71yIfMSF+gOCZ/Xsoiw4XgGAwiIiIzsHrXURzbsR4OOg2FU4ZiYqsSFhsuBFswiIiITGzVziM4sXMj7HUaXrtlgF9PX7g6vVld2lIxYBAREZnQyh2HcXLXn9HDhbNlhwvBgEFERGQiK7cfxsnd/4WLIb184WLhLRd6HINBRERkAtvO38ecHWdUuAhyz2hV4UKwBYOIiCiZbT13H18uPIrQ8PTI7Z0Bo9vXsqpwIRgwiIiIktGKncfgt+UWQsPtUa9oJvzcogQc7a2vQ4EBg4iIKJks3nIA5/f9hQ8dXKEr8AF+bVECDlYYLoR1vioiIiIzs2jzflzY95cac5HCMzV+aVHaasOFYAsGERFRElu0+W9c3L8VdjoNwSmyYGiP9nBytO5TsHW/OiIiIhNbsGkf/jmwLTJcDLGBcCGs/xUSERGZyIJN+/HPAWm5AEJSZlUtF44WvPy3Iay384eIiMiE1p+6g1/23EEQHBHi6a1aLmwlXAi2YBARERnZupN30HvpCYRHuCC8UA0Mb17WpsKFYMAgIiIyojnrd2PG/lsIj/DEZ6WzYnSTYrCXPhIbw4BBRERkJLP/2IVrR3fiQ0cdQgpWx6gmxWBng+FCMGAQEREZwax1O3H92C41oDMidTaMbFnFZsOFYMAgIiJ6TzPX7sDN47tVuAhLnQNDurWBvRUvopUQDBhERETvYcaaHbh1Yjd0OiA8TQ4M+YrhggGDiIjoPczZfChKuMgJv68+t/mWCz3bbr8hIiJKpGWHb+KHnQ9wNTwNItLmwpBuDBdRsYuEiIjIQEsP30C/VaehaTpkL10Nfp8WgZ0dv7NHxYBBRERkgCkrt2LPiYvQtOxoXykn/OoXgk76SCgaBgwiIqIE+n3FFjw4+zfyOQD58uTGYIaLODFgEBERJcDk5X/h4bn9b+6ky4tBbWqz5SIeDBhERETvMGnZZjw6f+DNnfR5MeiLFhxz8Q4MGERERPGYuHQTHl84qH7WZciHgV2aM1wkAIe8EhERxWHmtjN4cP7QmxNmxvwMFwZgCwYREVEs5uy7imFbriObXS7UyuGE7zs1ZcuFARgwiIiIYpix8xKGb/pH/VzvgzL4zic/B3QaiAGDiIgoinEL1+P2pdPw0OVHu+qF8E1thovEYMAgIiL6168L1+PF5aPwsANa57NnuHgPDBhEREQSLhasx4srR1VdOGUpjL7t6rNb5D0wYBARkc0bO38dXvofV/XglLUI+nVszHDxnhgwiIjIpo2Ztw4BV9+EC2dvCRdNTF0kq8B1MIiIyGZN2n4RN69cUD+7eBdluDAitmAQEZFNmrTjMn7+6zKckQ+dijjh28/rmrpIVoUBg4iIbM6vaw9i/P5H6ucetQuje428pi6S1WHAICIim/Lj7FUIunEa+eyzo0HNKuj2YR5TF8kqMWAQEZHNGD1rJYJvnlE/186fmuEiCTFgEBGRTRg1cyVCbr0JFx65SuLrNp+aukhWjQGDiIisWkREBH6cvToyXKTIXRJ9Pme4SGoMGEREZNXhQrpFQm+fU/dT5imN3q0/MXWxbALXwSAiIqukaRrG/HURh689Vfc9GS6SFVswiIjIKsPFz5svYvJOfwCZUbtCcXz5SXlTF8umMGAQEZHVdYuMmv8nZp0PB2APv/qF0aFyTlMXy+YwYBARkVWFixHTlyHi3kXUdEqBij4N0Z7hwiQ4BoOIiKwuXIiihQuhfeVcpi6WzWILBhERWUW4GD51KbQHl9T9tAUroHszH1MXy6YxYBARkcWHi2FTlwAP/lH3vQpVQLfPGC5MjQGDiIgserbIsOnLI8NF+kIV8eVntU1dLOIYDCIisuRwMfSPc1h3TYcgzR7pC1diuDAjbMEgIiKLDBdD1p3F3P3XodO5o2it5mhVmZdcNycMGEREZHFjLoZOWYqNN+2g03ngx8bF0Kyst6mLRTEwYBARkcUID4/A0N8XwP7xVdRytkex2i0YLswUAwYREVlOuJi8APZPrkLTgFwlKqNFpTymLhbFgQGDiIgsIlwMmTwfDk+uqXDhXfID+Db40NTFongwYBARkfmHi0nz4PD0OiI0IHupauj4aXVTF4vegQGDiIjMVkSEhsEz1sLp33CRo3R1dKhfzdTFogTgtUiIiMhsw0Xflaew5KoDboZ7ImcZhgtLwhYMIiIyO2HhEei38hRWHLsNO50d6jf+DA1KZDF1scgADBhERGRWQsPCMWTiXFx/FAJ7O2+Ma14S9YtnNnWxyNK6SCZNmoQcOXLAxcUF5cuXx6FDh+Ldf9y4ccifPz9cXV3h7e2N3r17IygoKNnKS0RESRwuJsyB0/ObKORwH6M/zs5wYaFMGjCWLl2KPn36wM/PD8eOHUPx4sXh4+ODBw8exLr/okWL0K9fP7X/+fPnMXPmTPUYAwYMSPayExGR8cOF32+z4fTilhrQmbdCTXxWtQir2UKZNGCMHTsWnTt3RocOHVCoUCFMmTIFbm5umDVrVqz7//3336hcuTJatWqlWj1q166Nli1bvrPVg4iIzFtIaJgKF84vbyNC0yFfhZr4vE5lUxeLLDFghISE4OjRo6hZs+Z/hbGzU/f3798f6zGVKlVSx+gDhb+/PzZu3Ii6devG+TzBwcF48eJFtBsREZlXuJBuEX24yF+xFlozXFg8kw3yfPToEcLDw5EhQ4Zo2+X+hQsXYj1GWi7kuCpVqqgr6YWFhaFr167xdpGMGjUKQ4cONXr5iYjIOLNF+s7dDs8XtxEBHQpUqoWWtSuyaq2AyQd5GmLnzp0YOXIkJk+erMZsrFq1Chs2bMCwYcPiPKZ///54/vx55O3mzZvJWmYiIoo7XPRaegKrL4fi7/CcKFi5NsOFFTFZC4aXlxfs7e1x//79aNvlfsaMGWM9ZtCgQWjTpg06deqk7hctWhQBAQHo0qULvv/+e9XFEpOzs7O6ERGR+QgKCcU3S45gw7kncLTX4buWPqhZKHqLNlk2k7VgODk5oXTp0ti2bVvktoiICHW/YsXYm8cCAwPfChESUoR0mRARkWWEi6G/zYLjld1IaR+GKZ+XZriwQiZdaEumqLZr1w5lypRBuXLl1BoX0iIhs0pE27ZtkSVLFjWOQtSvX1/NPClZsqRaM+Py5cuqVUO264MGERGZd7gYMn4WXAPvwVGng1+trPioIFsurJFJA0bz5s3x8OFDDB48GPfu3UOJEiWwadOmyIGfN27ciNZiMXDgQOh0OvX/27dvI126dCpcjBgxwoSvgoiIEuJ1sLRczIRr4H2EazoU/+BjNKlempVnpXSajfUtyDRVT09PNeAzZcqUpi4OEZFNhosS1euicfUypi4WJeE5lNciISKipA8X42fC9fWbcFHyw3poVI0tF9bOoqapEhGRZQkOC0evBQcRGvAMYZoOpRgubAZbMIiIKMnCxZcLjmH7P8+R2qEAhtbJgU+rlGBt2wgGDCIiMrpXr4Px7Zzt2H49Ai6OdpjYrgoq5/FiTdsQdpEQEZHRw8Ww32Yi/f1DyOv0DLPalWW4sEEMGEREZORwMQNuQQ8RATv08imMSmy5sEnsIiEiIqN4GRiE4RIugh8jTLNDhVqfol7l4qxdG8WAQURERg8XFX0aoG7FYqxZG8YuEiIiei8vA4Mjw0WoZodKDBfEgEFERO/jdUg4ui48husBdipcVP24IT5mywWxi4SIiBIrMCQMvnOOYL//E7g75UTXRj6oXjw3K5QUjsEgIiKDPXsViIFTV+HAQ094ODthbseyKJ09DWuSInEMBhERGRwuRv42A+leXUF1lxuY27EcwwW9hS0YRESUYE9fBmLUhBlwD32KUM0en3/yIUpnT80apLcwYBARkQHhYjrcQ5+pcFGjfhPUKF2QtUexYsAgIqJ3evIiAKMnSsvFM4Ro9qj5aVN8WKoAa47ixIBBRETxevE6BCMnzUaKf8NFrQafoXrJ/Kw1ihcHeRIRUZxeBoWi/ezD2PPSC4GaE2o3ZLighGELBhERxepFUCjazTqE4zeewdM1DVq1r4Xi2dOytihBGDCIiOgtD5+/xKhJ83D1ZQZ4uqbEwk7lUSSLJ2uKEoxdJEREFM39py/x88QZ8Ax9hJou/ljQsSzDBRmMLRhERBQtXPwyaQbcw18gGA5o3LgJinpznQsyHAMGEREp95+8wC+TJVy8VOHik8YtUKkory1CicOAQUREuP/4BX75/b9wUb9pS1QsnIs1Q4nGMRhERDbuWWAIfpi+NDJcNPisFcMFvTcGDCIiG/Y0IAStph/E5mcZcBdpVLgoXyinqYtFVoBdJERENurhswC0m3sM5+6+gJeHK/p0bo98GVKYulhkJRgwiIhs0O2HzzB+ykzYB3vCyyMHFncuj7wMF2RE7CIhIrIxtx48xfgpM+Ae8QpFHB9gbttiDBdkdGzBICKyITcfPMHEqbPgHhGAIDiiaYvWKJwtvamLRVaIAYOIyEbcePAEk6bOgtu/4eKzlp+jVL5spi4WWSkGDCIiG3D93hNMmj4T7hGBCIITmrdqjRJ5GS4o6XAMBhGRlXv4MhgD5m6JDBctWrdhuKAkxxYMIiIr9uBlkFrn4vJTD4R45MGgFtVQLE9WUxeLbAADBhGRlbp29xG+WHgclx+FIJOnC8Z0aYjsad1NXSyyEQwYRERW6OqdR5gyYxbyhuvwOmUxzO9SgeGCkhUDBhGRlfG/8xBTZ8yGm/YaOjtn/N6yKMMFJTsGDCIiK3Ll9kNMm/kmXLyGM9q2bYtCOTObulhkgxgwiIisxD+3HmDGLAkXQW/CRbt2KJQjk6mLRTaKAYOIyApcunkfM2fPeRMudM5o164dCmZnuCDT4ToYREQW7vaz1+ix8AgQEY5AnQvat2/PcEEmxxYMIiILDxctpu3HzWeALlVxjG9VBvmzZTB1sYgYMIiILNX563fRd9HfuPncBdnTumFW5wrInMrV1MUiUtiCQURkgc5du4t58+aieEQI7FIVwe9daiCTJ8MFmQ+OwSAissRwMXcuXLVghNi54Jc2VRkuyOywBYOIyIKcu3oH8+bNgyuCEahzRRffDsidJZ2pi0X0FgYMIiILcdb/DubP/y9cfNGpA3JlZrgg88SAQURkAc5fvx8tXHTt1BE5M3uZulhEceIYDCIiM3ftUQB8F57G3TB3BOrc0LUzwwWZP7ZgEBGZsauPAtBy2gHcexEMt3RF8EOb4siePo2pi0X0TgwYRERm6sQ/N/Drks24F5AJedOnwKLOFZAuhbOpi0WUIAwYRERm6NilG1i+eAFyIRQOqZzwY5da8PJguCDLwYBBRGRmjl68jhVLFsIFoQiwc4dfx/oMF2RxGDCIiMw4XPT8whdZ06c2dbGIDMaAQURkJo5evIYVSxZFhoteXTshS7pUpi4WUaIwYBARmYELt59i+ZLFcJVwYe+BXl19kcWL4YIsF9fBICIysUv3X6L1rCPYF5wNr+xT4n8MF2QF2IJBRGRCF+6+QOsZB/E4IAQZM2fDAN+mSO3O2SJk4wEjKCgILi4uxisNEZENOXD2CpauWI3goFwokiUdFviWRyo3J1MXi8g0XSQREREYNmwYsmTJAg8PD/j7+6vtgwYNwsyZM41TKiIiK7f/zBWsW7EEqRCAminuYaFvBYYLsu2AMXz4cMyZMwc//fQTnJz+S9pFihTBjBkzjF0+IiKr8/fpy/hj5RI4IwwB9inQ/8vP4enmaOpiEZk2YMybNw/Tpk1D69atYW9vH7m9ePHiuHDhgnFLR0RkZfae+gcbVi39N1ykxNfdOiND6pSmLhaR6cdg3L59G3ny5Im16yQ0NNRY5SIisjp7Tv6DTWuWwgnhCHBIiW+7d0I6zxSmLhaRebRgFCpUCHv27Hlr+4oVK1CyZEljlYuIyKqcvvUMS9esZ7ggm2FwC8bgwYPRrl071ZIhrRarVq3CxYsXVdfJ+vXrk6aUREQW7PSt52oqanBQTvikfojBXVvCy9PD1MUiMq8WjAYNGuCPP/7A1q1b4e7urgLH+fPn1bZatWolTSmJiCzU4ct30XrGAbwICkOR7Okxold7hguyCTpN0zTYkBcvXsDT0xPPnz9HypQcWEVESWfnsQvYsm4FDodmRcqs+TCnYzl4OHN9Q7KNc6jBLRi5cuXC48eP39r+7Nkz9TsiIgJ2HLuAretWwEkXjhLuzzGrfRmGC7IpBkfpa9euITw8/K3twcHBalwGEZGt2370PLb/sRKOunAEOKZC/x6dkdKVK3SSbUlwwFi3bl3kz5s3b1ZNJHoSOLZt24YcOXIYv4RERBZk6+Fz2Llh1b/hIjX69+iE1CncTF0sIvMNGA0bNlT/1+l0ahZJVI6Ojipc/PLLL8YvIRGRhdhy+Cx2bVj9Jlw4pcaAHp2QyoPhgmxTggOGTEkVOXPmxOHDh+Hl5ZWU5SIisihHrj3B1PUHUNROwkUaDOjhy3BBNs3gMRhXr15NmpIQEVmow9eeoP2sQwgIyQCvTKnwU6d6SOnOK02TbUvUfKmAgADs2rULN27cQEhISLTf9ezZ06DHmjRpEn7++Wfcu3dPXc9kwoQJKFeuXJz7y2yV77//Xi3w9eTJE2TPnh3jxo1D3bp1E/NSiIjey5YjF9Bn3RUEhACV83jh17Zl4er033WaiGyVwQHj+PHj6mQeGBiogkaaNGnw6NEjuLm5IX369AYFjKVLl6JPnz6YMmUKypcvr4KCj4+PWhlUHismCTOymJf8TpYml0vGX79+HalSpTL0ZRARvbc/95/Cvs1rURnuCMxdAdPalYWLI8MFUaLWwejduzfq16+Pp0+fwtXVFQcOHFAn+dKlS2PMmDEGPdbYsWPRuXNndOjQQV3jRIKGBJVZs2bFur9sl1aLNWvWoHLlympgabVq1VTLBxFRctq4/xT+3rwWjroIeLo5YVLrUgwXRO8TME6cOIGvv/4adnZ26nLtsv6Ft7c3fvrpJwwYMCDBjyOtEUePHkXNmjX/K4ydnbq/f//+OKfKVqxYEd26dUOGDBlQpEgRjBw5MtZ1OfSkfLLyWNQbEdH72LDvJPZvXgsHXQQCXbwwsGcnpHDjmAui9woYMiVVgoCQrgoZhyFkXYybN28m+HGkW0WCgQSFqOS+jMeIjb+/v+oakeM2btyIQYMGqamxw4cPj/N5Ro0apcqmv0kYIiJKrPV7T+DAlnWR4WIQwwWRccZgyCXZZZpq3rx5VfeEXOxMwsL8+fNVi0JSkqmyEmqmTZumWk+kW0ZWD5VBon5+frEe079/fzXOQ09aMBgyiCgx/th7Aoe2/vFvuEiHQT194eHqzMokMkYLhnRJZMqUSf08YsQIpE6dGl9++SUePnyIqVOnJvhxZB0NCQn379+Ptl3uZ8yYMdZj5Hnz5cunjtMrWLCgavGIOZtFz9nZWV2QJeqNiMhQe/95hBGbLiMcOgS6psPgXgwXREZtwShTpkzkz9KasGnTJiSGk5OTaoGQJcb1q4RKC4Xc7969e6zHyMDORYsWqf303TSXLl1SwUMej4goKez55yE6zT2C4DBXPM5eGWPbVIK7C1suiIzaghGXY8eO4ZNPPjHoGOm6mD59OubOnYvz58+rlhCZ+iqzSkTbtm1VF4ee/F5mkfTq1UsFiw0bNqgWFRn0SUSUFFbvOoq+83YgOCwCNQumx28dPmC4IDJ2C4Zc5GzLli2qtaBTp07q8uwXLlxAv3798Mcff6g1LAzRvHlz1bUi4zikm6NEiRKqRUQ/8FMGkOpbKoSMnZAyyFTZYsWKqXUwJGz07dvXoOclIkqIVTuP4MTOjfjQXocn2atgfOvScHIw2vcyIqum0zRNS8iOM2fOVGtWyMJasgZG2rRp1ToWPXr0UEFBTvQyHsLcySBPmU3y/Plzjscgojit3HEYJ3f9CXudhtduGeDX0xeuzo6sMbJpLww4hyY4io8fPx4//vijmjGybNky9f/Jkyfj9OnTaoEsSwgXREQJsXJ79HAxpBfDBVGStWC4u7vj7NmzavVMOURmZ+zYsUMNvLQkbMEgovgs33YIp/dsUuEiyD0j/Hp2hIsTWy6IDD2HJngMxuvXr9Uy3kKn06mAoZ+uSkRkDVbtPhklXGSCX88ODBdEyTHIc8aMGfDw8FA/h4WFYc6cOWo9i/e5mioRkTnYcu4++m++iQ/sU8DL0x1+PRguiJKli0S6RqTlIt4H0+nUct7mjF0kRBTTX2fvoduiYwgN1/BJkfQY27wknBwNXiaIyOq9SIoukmvXrhmjbEREZmXR5v1YvfcUQsOzoH7xLPi1WXE42HMqKtH7YkQnIpu1aPPfuLh/K4o4aMjhnRmjGC6IjIYBg4hs0sJN+3DpwFbY6YDgFFkwosPHbLkgMiIGDCKyOfP/3IfLB9+Ei5CUWTG0R3s4Ovx3EUUien8MGERkU+Zt3IMrh7a/CRee3hjSvR3DBVES4EgmIrIZK/dfwuVDOxguiMw1YFy5cgUDBw5Ey5Yt8eDBA7Xtzz//VCt9EhGZo7UnbuPbdf9gX2h2hKbKzpYLInMLGLt27ULRokVx8OBBrFq1Cq9evVLbT548CT8/v6QoIxHRe1lz7CZ6Lz2BCA0oXbIEfujBbhEiswsYcmn24cOHR162Xa9GjRo4cOCAsctHRPReZq3biZ1rF8FZC0WLst4Y3bgY7GQABhGZV8CQq6c2atTore3p06dXV1glIjIXM9fuwPVju5DaLghNsodgZKOiDBdE5howUqVKhbt37761/fjx48iSJYuxykVE9F5mrNmBm8d3qwGd4WlyYmiXpgwXROYcMFq0aIG+ffvi3r176tojERER2LdvH7755hu0bds2aUpJRGSA6au349aJ3dD9Gy78vvoc9lz+m8i8A8bIkSNRoEABeHt7qwGehQoVwgcffIBKlSqpmSVERKY0bfU23D655024SJsLQ7oxXBCZ9dVUY7px4wbOnDmjQkbJkiWRN29eWAJeTZXIei0+4I/Dfy6Dp10wIrxywe/L1rCz43I/RGZ9NVW9vXv3okqVKsiWLZu6ERGZgyWHbqD/mvNw1+XHZznD4depMcMFkQkZHO1lOmrOnDkxYMAAnDt3LmlKRURkgLk7zqLfqtPq588q5oNf5yYMF0SWFjDu3LmDr7/+Wi24VaRIEZQoUQI///wzbt26lTQlJCKKx+Tlf8F/10rksH+CDpVzwK9+ITUAnYgsLGB4eXmhe/fuauaILBn+2WefYe7cuciRI4dq3SAiSi6Tlm3Gw3P7YafT8KG3AwZ/wnBBZPGDPPXCw8PVdUgGDRqEU6dOqfvmjIM8iazDxKWb8PjCQfWzLkM+DOzSnN0iRGZ0Dk308Gppwfjqq6+QKVMmtGrVSnWXbNiwIbEPR0SUYBOW/BkZLuwy5me4IDJDBs8i6d+/P5YsWaLGYtSqVQvjx49HgwYN4ObmljQlJCKK4rfFG/H00mH1s12m/Pi+UzO2XBBZQ8DYvXs3vv32WzRr1kyNxyAiSi6z9l7F3+euoaADYJ+pIAZ0kuW/uc4FkVUEDOkaISJKbjP2+GP4hvMAsqF4ofzo2/xDhgsiSw8Y69atw8cffwxHR0f1c3w+/fRTY5WNiEiZsGoXfj30Qg0b6/5hXnxdOx+nohJZwywSaYKUi5vJJdnja46UueecRUJExvTrgvV4ceUoroenQuHKtdGndgGGCyJrWSpcrpga289ERElp7Px1eOl/XP2cN3tW9K6Vn+GCyEIYPDpq3rx5CA4Ofmt7SEiI+h0RkTGMmfdfuHD2LoL+vlz+m8iqF9qyt7fH3bt3VXdJVI8fP1bb2EVCRO9rzLy1CLh6Qv3s4l0UfTs2ZqUSWfvVVCWPxLbOv1yLRJ6UiOh9/DxvHQL14SJbUfTtwHBBZIkSHDBKliypgoXcPvroIzg4/HeotFpcvXoVderUSapyEpENmLDtH6y4EIhaTnZImaMIvmvfyNRFIqKkDhgNGzZU/z9x4gR8fHzg4eER+TsnJyd1sbMmTZokthxEZON+2/YPxm65BCAF0pf/FD0/Lm7qIhFRcgQMPz8/9X8JEs2bN4eLi8v7PC8RUaQf567F4guhAFzxXZ38+Kp6HtYOkYUzeAxGu3btkqYkRGSTRs1ciZBbZ1DH2QHZqjRiuCCypYCRJk0aXLp0SV17JHXq1PHOQ3/y5Ikxy0dEVkrW1Plx9moVLkT6PMXwVc1Cpi4WESVnwPj111+RIkWKyJ/jCxhERAkJF6NnrUTo7XPqfsrcpdH7809YcUS2vA6GLc3hJaKkDxeeeUrjf60ZLois7Rxq8Eqex44dw+nTpyPvr127Vs0wGTBggFrNk4goLvJ9ZvSCP/8LF3nLMFwQWSmDA8YXX3yhxmMIf39/NaPEzc0Ny5cvx3fffZcUZSQiKwkXP266iFnnwnE/3AOp8pXF/1rVM3WxiMhcAoaEixIlSqifJVRUq1YNixYtwpw5c7By5cqkKCMRWUO3yKYLmLLrCsJgj3K1G6FXy7qmLhYRJaFELRWuv6Lq1q1b8cknb/pOvb298ejRI+OXkIgsmvy9GDFtKQ7dCgCQCT80KIy2FXOYulhEZG4Bo0yZMhg+fDhq1qyJXbt24ffff1fbZanwDBkyJEUZiciCw8XwqUuhPbiEMo5Ag6olGS6IbITBXSTjxo1TAz27d++O77//HnnyvFlxb8WKFahUqVJSlJGILDRcDJu6RIUL4VWoAjr5lDZ1sYjI0qapBgUFqUu5Ozo6wpxxmipRMoWLKYuBh5fV/fSFK+HLprVY9UQWLkkv16539OhRnD9/Xv1cqFAhlCpVKrEPRURWFi5+mLIYOn24KFIJXzZhuCCyNQYHjAcPHqipqTL+IlWqVGrbs2fP8OGHH2LJkiVIly5dUpSTiCyANIgOXbQLdg8vQ9pGMxWrjC8a1zR1sYjIEsZg9OjRA69evcLZs2fVdUfkdubMGdVs0rNnz6QpJRFZRLgYvPYs5p4JxMFQb2QuVoXhgsiGGTwGQ/peZHpq2bJlo20/dOgQateurVozzBnHYBAZX3h4BPzWnMCCw3chlyr6sUkxNCvjzaomsjJJOgZD+ldjG8gp2/TrYxCRbYWLoZMX4Pmj+3DW5cOIpqXRtHRWUxeLiCyti6RGjRro1asX7ty5E7nt9u3b6N27Nz766CNjl4+IzDxcDJk0H/ZPriKtLhD9qngxXBBR4gLGxIkTVRNJjhw5kDt3bnXLmTOn2jZhwgRDH46ILDpczIPD02uI0IBspaqhQ73Kpi4WEZkJg7tIZElwWWhr27ZtkdNUCxYsqFb2JCIbChcT58Hh2XUVLnKUro4O9auZulhEZKkBY+nSpVi3bp26LLt0h8iMEiKywQGdE+fC8dkNFS5ylqmO9p8wXBBRIgOGXHOkW7duyJs3L1xdXbFq1SpcuXIFP//8c0IfgogsXHiEhn5LD8Hu6V3YA8hVtgba1atq6mIRkSWPwZCxF35+frh48SJOnDiBuXPnYvLkyUlbOiIyq3Dx3YpTWH7qMf4KzY/c5WsyXBDR+6+DIa0WMuZCBncKmZIq265du4ZMmTLBUnAdDCLDhYaFo//CvVhx/hXs7XT4rUVJ1CtmOf/uiciM18EIDg6Gu7t75H07Ozs4OTnh9evX71daIjL7cDFkwhy4Pr8Nb/u86N+iOuoWZbggIiMO8hw0aBDc3Nwi78tgzxEjRqg0ozd27FhDHpKIzFhIaJgKF84vbyMCOnStmo3hgoiMGzA++OADNf4iqkqVKsHf3z/yvk7WCCYi6wsXmg75K9ZEK59Kpi4WEVlbwNi5c2fSloSIzCxczIbzyzsqXBSoVAsta1c0dbGIyJoX2iIi6w8Xfr/NhsurOwjXdChUuTZa1Kpg6mIRkbUvFU5E1is0PAK9l57A7WdBKlwUruLDcEFEicIWDCKKDBc9Fx/Hn2fuw9k+NxrX8UbDykVZO0SUKAwYRISgkFAMmLYOm245w8neHr+3KYUaBTKwZogo0RgwiGzc6+BQDP1tJjwD76OyUzr4tmqKDwukN3WxiMgWx2Ds2bMHn3/+OSpWrIjbt2+rbfPnz8fevXuNXT4iSoZw4Rp4X425aPRhWYYLIjJNwFi5ciV8fHzUMuHHjx9XK3wKWTZ05MiRxikVESVPuBj/X7goUb0emnxYljVPRKYJGMOHD8eUKVMwffp0ODo6Rm6vXLkyjh07ZpxSEVGSCggKxtDxM+D6+j7CNB1KfVgPjauXZq0TkenGYMhqnrKqZ0yyXPizZ8+MVS4iSiLBYeEYOmEO3F8/UOGiTI1P0OCDUqxvIjJtC0bGjBlx+fLlt7bL+ItcuXIlqhCTJk1SV2l1cXFB+fLlcejQoQQdt2TJErU8ecOGDRP1vES2Jig0HF3nH8X+px4I0exR9qP6DBdEZB4Bo3PnzujVqxcOHjyoTu537tzBwoUL8c033+DLL780uABLly5Fnz594Ofnp7pYihcvrsZ4PHjwIN7j5DLx8pxVq1Y1+DmJbDZcLDiKHRcf4qF9GtRu1gGfVi1p6mIRkZXSaZqmGXKA7C6DOUeNGoXAwEC1zdnZWZ3shw0bZnABpMWibNmymDhxorofEREBb29v9OjRA/369Yv1mPDwcNVN07FjRzWjRbpm1qxZY/Rr2RNZi1evg+E3aQE2P06NMAdXzGpfFpVye5m6WERkYQw5hxrcgiGtFt9//z2ePHmCM2fO4MCBA3j48GGiwoVc7v3o0aOoWbPmfwWys1P39+/fH+dxP/zwA9KnTw9fX993PofMcpEKiXojsiUvA4MwbPx0pAy4hdrO/2BW2zIMF0RkvgttOTk5oVChQu/15I8ePVKtERkyRF8xUO5fuHAh1mNkrMfMmTNx4sSJBD2HtLQMHTr0vcpJZKkkXAz/bQbcgh8jVLNDTZ+PUSlvOlMXi4hsgMEB48MPP1StGHHZvn07ksrLly/Rpk0bNUXWyythzbv9+/dXYzz0pAVDumCIrN2LgCCMmPBfuKjs0xAfV+S1RYjITANGiRIlot0PDQ1VrQnSXdKuXTuDHktCgr29Pe7fvx9tu9yX2SoxXblyRQ3urF+/fuQ2GbMhHBwc1BTa3LlzRztGxofIjcjWwsXwCdPhHvxEhYsqdRqhToUipi4WEdkQgwPGr7/+Guv2IUOG4NWrVwZ3s5QuXRrbtm2LnGoqgUHud+/e/a39CxQogNOnT0fbNnDgQNWyMX78eLZMEAEIDAnD4MmLkPrfcFG1biP4lGO4ICILvdiZXJukXLlyGDNmjEHHSfeFtHyUKVNGHT9u3DgEBASgQ4cO6vdt27ZFlixZ1FgKWSejSJHofyhTpUql/h9zO5GthouOcw7j+OM0qOXyDA3q+aBW2cKmLhYR2SCjBQyZ9SEBwFDNmzdXs1AGDx6Me/fuqS6YTZs2RQ78vHHjhppZQkTxexUUAt+5R3Hw6hN4OLuiffv2KJMjDauNiCxjHYzGjRtHuy+H3717F0eOHMGgQYPUglnmjOtgkDV6+jIQoybMwMmAlLjjkAlzfcuhVLbUpi4WEVkZQ86hBrdgyANHJa0L+fPnV2tT1K5d2/DSEtF7efoiAKMmzoB76DOUcXyB+q1qM1wQkckZFDBkzQoZG1G0aFGkTs1vR0Sm9uRFAEb/Gy7k2iI1P22KCvkym7pYRESGreQpU0qllYJXTSUyvUfPX2H0xOmR4aLWp03xYakCpi4WEZFi8OhJma3h7+9v6GFEZORw8ZNquXiuwkXtBp+hOsMFEVlywBg+fLi6sNn69evV4E5e54Moeb0ICkXfGRvhHvYcIbCHT8NmqFYyP98GIrLMWSQyiPPrr79GihQp/js4ypLh8jByX8ZpmDPOIiFLDxdtZx7CiZtPUdb1IXo2rIKqxfOaulhEZCNeGDCLJMEBQ8ZfSIvF+fPn492vWrVqMGcMGGSpHjx7iS8WHMfxWy+Rys0RC3zLo0iW6LO6iIgsbpqqPoeYe4Agskb3n77EL5NmIEOIhrSuBTGvU3kUzsxwQURWMk01vquoElHSuP/kBX6ZPAPu4S/hYO+ASZ8VZLggIusKGPny5XtnyHjy5Mn7lomI/nX/8Qv88vubcBEMB9Rv0gIVCuVg/RCRdQWMoUOHvrWSJxEljXuPn2OsChevVLj4tGlLVCici9VNRNYXMFq0aIH06dMnXWmISLn7+Bl+/X1mZLho8FkrlC+Uk7VDRNa3DgbHXxAlj6cBIeg+dz8cwl4jGI5o1Izhgogsj8GzSIgo6TwJCEHrGQdx/kEEnrkXwY9NS6BMQY65ICIrDhgRERFJWxIiG3f74TP0nLsX5x/p4OXhjKldPkCe9P8tbEdEZEkMvlw7ERnfrQdP8dvUmSgQ/hovPIrg9y7VkCe9B6uaiGznWiREZFw3HjxR4cI9IgAROnv82Kw0wwURWTy2YBCZOFxMVOEiEEFwQvNWrVEibza+J0Rk8RgwiEzk+r0nmDT9v3DRonUbFM+Tle8HEVkFBgwiE7h+/wkmRwkXLVu3QTGGCyKyIhyDQZTMHrwIgu/8E3gS6oDXDBdEZKXYgkGUzOGixfQD8H/0GkEpi2BqqyIonCMT3wMisjoMGETJxP/OQwyd8yf8X6RBllRuWNS5ArKldWP9E5FVYsAgSgZXbj/EtJmzkUt7jXAPDaO61IB3GoYLIrJeDBhESeyfWw8wY9ZsuGlBeA1nDPi8NsMFEVk9BgyiJHTp5n3MnD3nTbjQOaNdu3YomJ1jLojI+nEWCVEyhItAnQvDBRHZFLZgECWBG49eYubsuZHhomP79sifLQPrmohsBlswiIzs1tNAtJ51GIeDMyJA5wrfDgwXRGR72IJBZEQ3nwSi5fQDuPX0NbKn9UbPjo2QNS0vuU5EtocBg8hIzl29g9/nr8DjQG/k9EqNxZ0rIKOnC+uXiGwSu0iIjODs1TuYN28evLSnqOlxm+GCiGweWzCI3tMZ/9tYMH8+XBGMQJ0rendszpYLIrJ5DBhE7+G0/20snD8PrghR4aJrp47ImdmLdUpENo8BgyiRTl2+hcUL5/8bLtzwZZcOyJGR4YKISHAMBlEiXH0UgBmLlsNFwoUdwwURUUwMGESJCBctpu3Httc58Ng+Lb7q7MuWCyKiGNhFQmSAi3efos2so3jwMhj5MqTB4M514eXhzDokIoqBAYMogY5duoFlixfCLSQr8mfIjoWdyzNcEBHFgV0kRAlw9OJ1LF+8QA3oLOvyAAt8yzJcEBHFgy0YRO9w9OI1rFiyCC4IRYCdO/7X1RfpUrqy3oiI4sGAQRSPI+evYdUyfbjwQK+uvsiSLhXrjIjoHRgwiOJw+PxVrF62GM4SLuw9VMtFZi+GCyKihOAYDKJYXLz3EuOWbYsMF32+7MRwQURkALZgEMVw4d4LtJp+EE9eZ4RrGhcM962PjGk9WU9ERAZgwCCK4tCFG/hy2Xk8CQxD0Syp8IuvDzzdHFlHREQGYsAg+tffp69g/aolKB7ugcdZSmJep/LwdGW4ICJKDI7BIAKw7/Q/2LBqCZwRBi+nCExvU5LhgojoPbAFg2ze3pP/4M81y+CEMAQ4pMS33TshnWcKm68XIqL3wYBBNm3PyX+wac1SOCEcAQ6e+La7L8MFEZERMGCQzdp94hI2S8uF7k24+K57J3h5epi6WEREVoFjMMgmnbr1DEPWnIQOGgIcGS6IiIyNLRhkc07efIbPZx7EyyA3ZMlcBuPbf4A0Kd1NXSwiIqvCgEE2ZcexCxi09hxeBjujbI7U+L1DOXg4858BEZGx8S8r2YxtR85hx/pVqKrT4WbW8pjaoRzcGS6IiJIEx2CQTdh6+E24cNSFI9wpBSa0q8RwQUSUhNiCQVZvy+Gz2LVhtQoXAU6pMaBHJ6TycDN1sYiIrBoDBlm1vw6dwe6NEi4iGC6IiJIRAwZZra1HL0QJF2kwsGdnpHR3MXWxiIhsAsdgkFU6dPUJ+qy9gicRbghwZrggIkpubMEgq3PQ/zE6zDmMwBDgZa4K+PHz0kjhxpYLIqLkxIBBVmXj/lOY/ucRBIZkQNW8XpjetgxcHO1NXSwiIpvDgEFWY8O+kziwZR1K2EcgY9a0+JXhgojIZBgwyCqs33sCB7f+AQddBAJdvPCzbx22XBARmRADBlm8P/Yex6Gt6/8NF+kwqKcvPFydTV0sIiKbxoBBFm3dnuM4vE1aLjQEuqbD4J6+cHdhuCAiMjVOUyWLtfXkVRzeJi0XGl4zXBARmRUGDLJIuy49xFfLL+BIaBa8dk2vukXYckFEZD7YRUIWZ8eF+/hiwTGEhEUga6FiGNqyJJw5FZWIyKwwYJBFWbnjMLbv3A2E5UHtQlkwsVUpODmwIY6IyNzwLzNZjJXbD+Pkrj+R3u4VPs30kuGCiMiMsQWDLMLy7Ydwevcm2Os0BLlnxPAvm7PlgojIjDFgkNlbtvUgzuzd/G+4yAS/nh3g4uRo6mIREZG5d5FMmjQJOXLkgIuLC8qXL49Dhw7Fue/06dNRtWpVpE6dWt1q1qwZ7/5k2ZZGDRceDBdERJbC5AFj6dKl6NOnD/z8/HDs2DEUL14cPj4+ePDgQaz779y5Ey1btsSOHTuwf/9+eHt7o3bt2rh9+3ayl52S1qZTt3Fk7/Z/w0VmDO3ZkS0XREQWQqdpmmbKAkiLRdmyZTFx4kR1PyIiQoWGHj16oF+/fu88Pjw8XLVkyPFt27Z95/4vXryAp6cnnj9/jpQpUxrlNZDxbTpzD90XHYOb9hp1Mwbgh69awcmRPXpERKZkyDnUpH+xQ0JCcPToUfTv3z9ym52dner2kNaJhAgMDERoaCjSpEkT6++Dg4PVLWrlkHn74+hV9F55HmERGqoXz4XhzYrDwd7kjW1ERGQAk/7VfvTokWqByJAhQ7Ttcv/evXsJeoy+ffsic+bMKpTEZtSoUSpt6W/SOkLma+GmfTj4xwKkxzM0LJEZYxkuiIgskkV/LRw9ejSWLFmC1atXqwGisZHWEWnK0d9u3ryZ7OWkhJn/5z5cOrAVjroIVE8fgl+alWDLBRGRhTJpF4mXlxfs7e1x//79aNvlfsaMGeM9dsyYMSpgbN26FcWKFYtzP2dnZ3Uj8zZv4x5cObQddjogJKU3hnZvA3u5Q0REFsmkLRhOTk4oXbo0tm3bFrlNBnnK/YoVK8Z53E8//YRhw4Zh06ZNKFOmTDKVlpLK3A1RwoWnN4b0aAdHB3tWOBGRBTP5sHyZotquXTsVFMqVK4dx48YhICAAHTp0UL+XmSFZsmRRYynEjz/+iMGDB2PRokVq7Qz9WA0PDw91I8syZ/1uXD2yQ4WL0FTZMKRbW4YLIiIrYPKA0bx5czx8+FCFBgkLJUqUUC0T+oGfN27cUDNL9H7//Xc1+6Rp06bRHkfW0RgyZEiyl58Sb+2J29h+6BRy278JF0O7t4M9Z4sQEVkFk6+Dkdy4DoZ5WHP8NvosOwH5+LXKHYEfOn7CcEFEZOYsZh0Msk3ztxzBkO33EKHp0LJcNgxrWBR2HNBJRGRVGDAoWc1YswO3TuxGRYe08C7xAUYwXBARWSWLXgeDLMv0NdtVuNDpgFzpU2J4wyJsuSAislJswaBkMW31Ntw5uVeFi/C0OTHkq8+jDd4lIiLrwoBBSW7aqm24c+pNuIjwyoUhX7ZmuCAisnIMGJSkpqzcivtn9qlwoXnlht+XrRguiIhsANuoKcksOngDC4/eR7img5YuDwYzXBAR2Qy2YFCSWHjwOr5ffQZAKtgXqolBTSuw5YKIyIYwYJDRTV65Db8feQbABb5VcmJgvYLQSR8JERHZDAYMMqqJSzfh8YWDqOPkBM+SdfA9wwURkU3iGAwyergQKTPnxIBPi7PlgojIRrEFg4zit8Ub8fTSYfWzXab8+L5TM465ICKyYQwY9N7GL96IZ/+GC/tMBTCg02cMF0RENo4Bg97Lb8u3RYYLh8wF0d+3KcMFERFxDAYl3ow9/ph09CWeRLjCMUshhgsiIorEFgxKlOm7/TFi43kAjshWoR56+xRkywUREUViwCCDjZ2/DpsvPAaQHj0/yoveNfNytggREUXDgEEG+WX+OrzyP45KTkDt4gXRp1Y+1iAREb2FAYMSbMy8tQi4ekL97OJdFF83rMDaIyKiWDFgUIL8PHcNAq+dVD+7ZCuGvh0aseaIiChODBj0Tj/NWY3X10+pn12zF8d37Ruy1oiIKF4MGBSvX1btiwwXbjmK49t2DBdERPRuvBYJxWnc1kuYcOgZjodmgnvOEgwXRESUYGzBoLdomoZf/7qA33b4q/t1an2ErtVys6aIiCjBGDAomoiICPw4exWuX78Be+TBdx8XxhcMF0REZCAGDIoWLkbPWonQ2+eQyR7oVcaD4YKIiBKFAYP+CxczVyL0zjl13zNPafRsWoO1Q0REicKAQSpcjJqxAmF35doigGfeMvhfq3qsGSIiSjQGDBsn4WLkjOUIv3tB3U+dryx6tqxr6mIREZGF4zRVG58tMvqP4wi884+6nzp/OYYLIiIyCrZg2HC4GPXnBUzbfw9pdPnRsZQnun9W29TFIiIiK8GAYaPdIiNWH8XMww/U/d6flkWbijlMXSwiIrIiDBg2GC6GTV2CkPtXkM4uH3p9WgGfV8hu6mIREZGVYcCwtXAxZTHw8DKcdECHUmkYLoiIKEkwYNhQuPhhymLoHl5W99MXqYQvm9QydbGIiMhKMWDYSrj4fSF0j95cWyRDkcro2qSmqYtFRERWjAHDBsLF0MkLYffYH5oGZC5WBV0af2TqYhERkZXjOhhWLCJCw+A1p3H7weM34aI4wwURESUPtmBYcbgYtPYMFh66BQddbgz8IB3af1zB1MUiIiIbwYBhhcLDIzB43mYsvBgOnU6HH5uWRJPSWU1dLCIisiEMGFYYLoZMmg+np9dQ1jEDWjX+BI1KMlwQEVHyYsCwtnAxcR4cnl1HhAbULVeQ4YKIiEyCAcOKwoXfxLlwfHZDhYucZaqj/SfVTF0sIiKyUQwYViA0LBxDJ86D4/M34SJX2RpoV6+qqYtFREQ2jNNULVx4hKa6RRguiIjInDBgWHi4+Hb5Sex/aI9wTYfc5dhyQURE5oFdJBYcLr5ZfhKrj9+GvZ0XenxcEY3K5zV1sYiIiBQGDAsUEhqGwVOWYtNtNzjYOWNCy5L4uGgmUxeLiIgoEgOGBYaLIRPmwPXlbfg4u8KnSWuGCyIiMjscg2GB4cL55W1EaDqUr1wVHxfLYupiERERvYUtGBYULvx+mw2XV3fUgM5ClWujRS1eW4SIiMwTA4YFCAoJxdAJEi7uqnBRuIoPmtcsb+piERERxYkBw8yFyoXLJi+G+7/homjVOvjso3KmLhYREVG8OAbDzMNFj0XHsf5eCjyLcEWxDxguiIjIMrAFw0wFh4aj55Lj2Hz2PpzsXVC/eVvUKJTR1MUiIiJKEAYMM/Q6OBRDf5uFS8/c4OTghWltSqN6/vSmLhYREVGCMWCYmcCgEPzw20y4vn6Ayo52qNa4GsMFERFZHAYMMxIQFIxhv81S4SJM06HMh3VRq1g2UxeLiIjIYAwYZhUupOXi4ZtwUeMTNPiglKmLRURElCgMGGbg1es34cIt6E24KPtRfXxataSpi0VERJRonKZqYkGh4eg//Y9/w4UdytVkuCAiIsvHgGHicPHF/KP4444LLkRkRPla9VG/ClsuiIjI8rGLxEReBgbhq0XHsefyE7g6OqBn26aomDutqYpDRERkVAwYJgoXw3+bAcfAcLg75sXMDmVRIRfDBRERWQ8GjGT2IiAIIybMgFvwY2S2s8P4+rkZLoiIyOowYCR7uJgOt+AnCNXsUKVOQ9QsnT85i0BERJQsGDCSyfNXr1XLhXvIm3BR9eNG8ClfJLmenoiIKFkxYCSDZ68CMVKFi6cI1exRrV4j1CpbODmemoiIyCQ4TTWJBYaEodecPXAKfq7CRfV6jRkuiIjI6rEFIwkFBIehw5zDOHQrDDmdC+D7+oVRs0yhpHxKIiIis8CAkUSevgxEj7l/49CtYKRwdsBY35oomS11Uj0dERGRWWHASAJPXgRg9MQZ8A55hSwuhTDJtzJKeKdKiqciIiIySxyDYWSPVbiYDvfQZ7CDhhGfFmS4ICIim2MWAWPSpEnIkSMHXFxcUL58eRw6dCje/ZcvX44CBQqo/YsWLYqNGzfCHDx6/go/TpBw8Rwhmj1qN/gM1UsVMHWxiIiIbC9gLF26FH369IGfnx+OHTuG4sWLw8fHBw8ePIh1/7///hstW7aEr68vjh8/joYNG6rbmTNnYEoPn7/ETxNnwD3sOUJgD5+GzVCtJBfRIiIi26TTNE0zZQGkxaJs2bKYOHGiuh8REQFvb2/06NED/fr1e2v/5s2bIyAgAOvXr4/cVqFCBZQoUQJTpkx55/O9ePECnp6eeP78OVKmTGm0cPGzChcvVLio07A5qhbPa5THJiIiMheGnENN2oIREhKCo0ePombNmv8VyM5O3d+/f3+sx8j2qPsLafGIa//g4GBVIVFvxiT5rMfCE3gVHIEQOOBjhgsiIiLTBoxHjx4hPDwcGTJkiLZd7t+7dy/WY2S7IfuPGjVKpS39TVpHjEmn06Fjtbw45lQYnzRtiSpsuSAiIjL9GIyk1r9/f9WUo7/dvHnT6M9Ru3BG7PiuFioWzmX0xyYiIrJEJl0Hw8vLC/b29rh//3607XI/Y8aMsR4j2w3Z39nZWd2SmquTfZI/BxERkaUwaQuGk5MTSpcujW3btkVuk0Gecr9ixYqxHiPbo+4vtmzZEuf+REREZIMrecoU1Xbt2qFMmTIoV64cxo0bp2aJdOjQQf2+bdu2yJIlixpLIXr16oVq1arhl19+Qb169bBkyRIcOXIE06ZNM/ErISIiIrMJGDLt9OHDhxg8eLAaqCnTTTdt2hQ5kPPGjRtqZolepUqVsGjRIgwcOBADBgxA3rx5sWbNGhQpUsSEr4KIiIjMah2M5JYU62AQERHZgheWsg4GERERWScGDCIiIjI6BgwiIiIyOgYMIiIiMjoGDCIiIjI6BgwiIiIyOgYMIiIiMjoGDCIiIjI6BgwiIiIyOgYMIiIiMjoGDCIiIjI6BgwiIiIyOgYMIiIisr7LtSc3/cVj5YpwRERElHD6c2dCLsRucwHj5cuX6v/e3t6mLgoREZHFnkvlsu3x0WkJiSFWJCIiAnfu3EGKFCmg0+mMlugksNy8eRMpU6Y0ymPaOtYp69Tc8TPKOrXFz6imaSpcZM6cGXZ28Y+ysLkWDKmQrFmzJsljyxvIgME6NXf8nLI+zR0/o+Zdn+9qudDjIE8iIiIyOgYMIiIiMjoGDCNwdnaGn5+f+j8ZB+vU+FinrE9zx8+oddWnzQ3yJCIioqTHFgwiIiIyOgYMIiIiMjoGDCIiIjI6BgwiIiIyOgaMBJo0aRJy5MgBFxcXlC9fHocOHYp3/+XLl6NAgQJq/6JFi2Ljxo3GeL9stk6nT5+OqlWrInXq1OpWs2bNd74HtsbQz6jekiVL1Kq2DRs2TPIyWnudPnv2DN26dUOmTJnUyP18+fLx3/571Oe4ceOQP39+uLq6qhUpe/fujaCgIOO8uVZg9+7dqF+/vlpVU/4Nr1mz5p3H7Ny5E6VKlVKfzzx58mDOnDlJV0CZRULxW7Jkiebk5KTNmjVLO3v2rNa5c2ctVapU2v3792Pdf9++fZq9vb32008/aefOndMGDhyoOTo6aqdPn2ZVJ7JOW7VqpU2aNEk7fvy4dv78ea19+/aap6enduvWLdZpIupT7+rVq1qWLFm0qlWrag0aNGBdvse/++DgYK1MmTJa3bp1tb1796q63blzp3bixAnWayLqc+HChZqzs7P6v9Tl5s2btUyZMmm9e/dmff5r48aN2vfff6+tWrVKZoNqq1ev1uLj7++vubm5aX369FHnpgkTJqhz1aZNm7SkwICRAOXKldO6desWeT88PFzLnDmzNmrUqFj3b9asmVavXr1o28qXL6998cUX7/t+2WydxhQWFqalSJFCmzt3bhKW0rrrU+qwUqVK2owZM7R27doxYLxnnf7+++9arly5tJCQkPd/Q62QofUp+9aoUSPaNjkxVq5cOcnLaomQgIDx3XffaYULF462rXnz5pqPj0+SlIldJO8QEhKCo0ePqib5qNczkfv79++P9RjZHnV/4ePjE+f+tiYxdRpTYGAgQkNDkSZNGti6xNbnDz/8gPTp08PX1zeZSmrddbpu3TpUrFhRdZFkyJABRYoUwciRIxEeHg5bl5j6rFSpkjpG343i7++vupvq1q2bbOW2NvuT+dxkcxc7M9SjR4/UHwj5gxGV3L9w4UKsx9y7dy/W/WU7Ja5OY+rbt6/qd4z5j8UWJaY+9+7di5kzZ+LEiRPJVErrr1M5AW7fvh2tW7dWJ8LLly/jq6++UkFYVlO0ZYmpz1atWqnjqlSpoq7gGRYWhq5du2LAgAHJVGrrcy+Oc5NcdfX169dqrIsxsQWDLM7o0aPVwMTVq1erwWJkGLnUcps2bdTAWS8vL1afkURERKgWoWnTpqF06dJo3rw5vv/+e0yZMoV1nAgyGFFagCZPnoxjx45h1apV2LBhA4YNG8b6tBBswXgH+QNsb2+P+/fvR9su9zNmzBjrMbLdkP1tTWLqVG/MmDEqYGzduhXFihVL4pJaZ31euXIF165dU6PPo54chYODAy5evIjcuXPDliXmMyozRxwdHdVxegULFlTfGqWLwMnJCbYqMfU5aNAgFYQ7deqk7stsvICAAHTp0kUFN+liIcPEdW6SS7kbu/VC8B16B/mjIN9Gtm3bFu2PsdyX/tbYyPao+4stW7bEub+tSUydip9++kl9e9m0aRPKlCmTTKW1vvqU6dOnT59W3SP626effooPP/xQ/SzTAW1dYj6jlStXVt0i+rAmLl26pIKHLYeLxNanjLOKGSL04Y2X0EqcZD83JcnQUSucXiXTpebMmaOm9nTp0kVNr7p37576fZs2bbR+/fpFm6bq4OCgjRkzRk2p9PPz4zTV96zT0aNHqyluK1as0O7evRt5e/nyZfJ8CKysPmPiLJL3r9MbN26omU3du3fXLl68qK1fv15Lnz69Nnz48CR4x62/PuXvptTn4sWL1fTKv/76S8udO7eapUdvyN8/mbovNzmdjx07Vv18/fp19XupT6nXmNNUv/32W3Vukqn/nKZqBmS+cLZs2dRJTqZbHThwIPJ31apVU3+go1q2bJmWL18+tb9MC9qwYYMJSm09dZo9e3b1DyjmTf4IkeH1GRMDxvt/RsXff/+tpqTLiVSmrI4YMUJNBybD6zM0NFQbMmSIChUuLi6at7e39tVXX2lPnz5ldf5rx44dsf5d1Nej/F/qNeYxJUqUUO+BfEZnz56tJRVerp2IiIiMjmMwiIiIyOgYMIiIiMjoGDCIiIjI6BgwiIiIyOgYMIiIiMjoGDCIiIjI6BgwiIiIyOgYMIiIiMjoGDCIrMycOXOQKlUqWCqdToc1a9bEu0/79u3RsGHDZCsTERmOAYPIDMkJVE60MW9yMS1zCDD68sjFqLJmzYoOHTrgwYMHRnn8u3fv4uOPP1Y/y1Vf5XnkImxRjR8/XpUjKQ0ZMiTydcpFtuQicHIlzydPnhj0OAxDZKt4uXYiM1WnTh3Mnj072rZ06dLBHMjlneWy7nJFzJMnT6qAcefOHWzevPm9Hzuuy3dH5enpieRQuHBhbN26FeHh4Th//jw6duyI58+fY+nSpcny/ESWjC0YRGbK2dlZnWyj3uSb9NixY1G0aFG4u7urb9VfffUVXr16FefjSACQS7GnSJFCBQO5bPaRI0cif793715UrVoVrq6u6vF69uyJgICAeMsm3+qlPJkzZ1atDXKMnIhfv36tQscPP/ygWjbkNZQoUQKbNm2KPDYkJATdu3dXlzF3cXFB9uzZMWrUqFi7SHLmzKn+X7JkSbW9evXqb7UKTJs2TZUj6mXSRYMGDVQg0Fu7di1KlSqlnjNXrlwYOnQowsLC4n2dDg4O6nVmyZIFNWvWxGeffaYub60nwcPX11eVU+ovf/78qnUlaivI3Llz1XPrW0N27typfnfz5k00a9ZMdWelSZNGlVdabIisBQMGkYWRbonffvsNZ8+eVSev7du347vvvotz/9atW6uT/eHDh3H06FH069cPjo6O6ndXrlxRLSVNmjTBqVOn1DdzCRwSAAwhJ1c5wcsJW06wv/zyC8aMGaMe08fHB59++in++ecfta+Ufd26dVi2bJlqBVm4cCFy5MgR6+MeOnRI/V/Ci3SdrFq16q195KT/+PFj7NixI3KbdGNIqJHXLvbs2YO2bduiV69eOHfuHKZOnaq6WEaMGJHg1ygnf2mhcXJyitwmr1nqdvny5epxBw8ejAEDBqjXJr755hsVIqSOpfxyq1SpEkJDQ1W9SOiTsu3btw8eHh5qPwlgRFYhya7TSkSJJpdZtre319zd3SNvTZs2jXXf5cuXa2nTpo28L5df9vT0jLyfIkUKbc6cObEe6+vrq3Xp0iXatj179mh2dnba69evYz0m5uNfunRJy5cvn1amTBl1P3PmzOoy5VGVLVtWXWpb9OjRQ6tRo4YWERER6+PLn6XVq1ern69evaruHz9+/K36adCgQeR9+bljx46R96dOnarKER4eru5/9NFH2siRI6M9xvz587VMmTJpcfHz81P1IHUvlwvXXwp77NixWny6deumNWnSJM6y6p87f/780eogODhYc3V11TZv3hzv4xNZCo7BIDJT0q3x+++/R96XLhH9t3npUrhw4QJevHihWg2CgoIQGBgINze3tx6nT58+6NSpE+bPnx/ZzJ87d+7I7hNpZZBWBD05x8s386tXr6JgwYKxlk3GIcg3btlPnrtKlSqYMWOGKo+MxahcuXK0/eW+PJe+e6NWrVqqO0G+sX/yySeoXbv2e9WVtFR07twZkydPVt0y8npatGihWnv0r1NaCaK2WEj3Rnz1JqSM0toi+y1YsEANNu3Ro0e0fSZNmoRZs2bhxo0bqotIWiCkWyg+Uh4ZsCstGFHJ80irEpE1YMAgMlMSKPLkyfNWM72ckL/88kt1spS+e+nSkHEAcmKL7UQp4wBatWqFDRs24M8//4Sfnx+WLFmCRo0aqbEbX3zxhRpDEVO2bNniLJucGI8dO6ZO4DKWQrpIhASMd5FxEBJepCwSlqQLQYLPihUrkFj169dXwUheY9myZVW3w6+//hr5e3mdMuaicePGbx0rYzLiIt0h+vdg9OjRqFevnnqcYcOGqW1Sj9INIl1CFStWVPXy888/4+DBg/GWV8ojY2GiBjtzG8hL9L4YMIgsiIyhkFYDOaHpv53r+/vjky9fPnXr3bs3WrZsqWanSMCQk72MHYgZZN5Fnju2Y2QQqQy4lNaCatWqRW6X++XKlYu2X/PmzdWtadOmqiVDxk1IYIpKP95BWhviIyFBwoOcsKVlQFoe5LXpyc8y3sPQ1xnTwIEDUaNGDRXw9K9TxlTIQFu9mC0Q8hpill/KI+Nd0qdPr+qCyBpxkCeRBZETpAwQnDBhAvz9/VW3x5QpU+LcX5rsZcCmzFy4fv26OiHKYE9910ffvn3x999/q32k+V8GYsqMB0MHeUb17bff4scff1QnUDmpy6BSeWwZYClkFszixYtVF8+lS5fUAEmZqRHb4mByApbWERmwef/+fdU1E183ibRgSHeFfnCnngy+nDdvnmp9kMGxMuVUWh8kMBhCWimKFSuGkSNHqvt58+ZVM3Jk8Ke8lkGDBqn6jUoGsEo3lNTFo0eP1Psn5fPy8lIzR6S1RVp05D2SlqRbt24ZVCYis2XqQSBE9LbYBgbqySBDGZwoAwJ9fHy0efPmqcGHT58+fWsQpgwcbNGihebt7a05OTmpgY/du3ePNoDz0KFDWq1atTQPDw81oLFYsWJvDdKMb5BnTDKwcsiQIVqWLFk0R0dHrXjx4tqff/4Z+ftp06ZpJUqUUM+VMmVKNQDz2LFjsQ7yFNOnT1fllwGX1apVi7N+5HmlXuT4K1euvFWuTZs2aZUqVVL1Js9brlw5VZb4BnlK2WNavHix5uzsrN24cUMLCgrS2rdvr+ojVapU2pdffqn169cv2nEPHjyIrF8p244dO9T2u3fvam3bttW8vLzU4+XKlUvr3Lmz9vz58zjLRGRJdPIfU4ccIiIisi7sIiEiIiKjY8AgIiIio2PAICIiIqNjwCAiIiKjY8AgIiIio2PAICIiIqNjwCAiIiKjY8AgIiIio2PAICIiIqNjwCAiIiKjY8AgIiIiGNv/AVPSXhcP8yvlAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Courbe ROC\n", "fpr, tpr, _ = roc_curve(y_test, y_proba)\n", @@ -295,12 +698,20 @@ "execution_count": null, "id": "891ff05c", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "💾 Résultats sauvegardés dans reports/model_comparison_results.csv\n" + ] + } + ], "source": [ "# ==========================================================\n", "# 6️⃣ Export de la synthèse\n", "# ==========================================================\n", - "metrics_summary.to_csv(\"reports/model_comparison_results.csv\", index=False)\n", + "metrics_summary.to_csv(\"outputs/reports/model_comparison_results.csv\", index=False)\n", "print(\"💾 Résultats sauvegardés dans reports/model_comparison_results.csv\")" ] }, @@ -322,7 +733,6 @@ "# ==========================================================\n", "# 7️⃣ Rapport rapide\n", "# ==========================================================\n", - "import markdown\n", "summary_text = f\"\"\"\n", "# 🧾 Rapport de comparaison des modèles\n", "\n", @@ -331,7 +741,7 @@ "**Nombre de runs :** {len(runs)}\n", "\n", "**Meilleur modèle :** {best_run['Model']} ({best_run['Strategy']})\n", - "- F1-score : {best_run['F1_score']:.3f}\n", + "- F1-score : {best_run['f1']:.3f}\n", "- Accuracy : {best_run['Accuracy']:.3f}\n", "\n", "Les figures ci-dessus montrent la comparaison entre les trois modèles et les différentes stratégies d'équilibrage.\n", @@ -346,7 +756,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open(\"reports/model_comparison.md\", \"w\", encoding=\"utf-8\") as f:\n", + "with open(\"outputs/reports/model_comparison.md\", \"w\", encoding=\"utf-8\") as f:\n", " f.write(summary_text)" ] }, @@ -355,7 +765,15 @@ "execution_count": null, "id": "bba8a1a3", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "📘 Rapport enregistré : reports/model_comparison.md\n" + ] + } + ], "source": [ "print(\"📘 Rapport enregistré : reports/model_comparison.md\")" ] @@ -367,8 +785,22 @@ "main_language": "python", "notebook_metadata_filter": "-all" }, + "kernelspec": { + "display_name": "venv (3.12.2)", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" } }, "nbformat": 4, diff --git a/notebooks/5_demo_pipeline.ipynb b/notebooks/5_demo_pipeline.ipynb index 233d4cde..e0771127 100644 --- a/notebooks/5_demo_pipeline.ipynb +++ b/notebooks/5_demo_pipeline.ipynb @@ -14,7 +14,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "d7e444d3", "metadata": {}, "outputs": [], @@ -37,15 +37,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "1a55ac11", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: 'data/dataset.csv'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mFileNotFoundError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 4\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m 2\u001b[39m \u001b[38;5;66;03m# 🔹 1. Charger le dataset\u001b[39;00m\n\u001b[32m 3\u001b[39m \u001b[38;5;66;03m# ------------------------------------------------------------\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m4\u001b[39m df = \u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_csv\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mdata/dataset.csv\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 5\u001b[39m df = df.drop(columns=[\u001b[33m\"\u001b[39m\u001b[33mRowNumber\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mCustomerId\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mSurname\u001b[39m\u001b[33m\"\u001b[39m], errors=\u001b[33m\"\u001b[39m\u001b[33mignore\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 6\u001b[39m df = df[df[\u001b[33m\"\u001b[39m\u001b[33mAge\u001b[39m\u001b[33m\"\u001b[39m] <= \u001b[32m80\u001b[39m]\n", + "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1026\u001b[39m, in \u001b[36mread_csv\u001b[39m\u001b[34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[39m\n\u001b[32m 1013\u001b[39m kwds_defaults = _refine_defaults_read(\n\u001b[32m 1014\u001b[39m dialect,\n\u001b[32m 1015\u001b[39m delimiter,\n\u001b[32m (...)\u001b[39m\u001b[32m 1022\u001b[39m dtype_backend=dtype_backend,\n\u001b[32m 1023\u001b[39m )\n\u001b[32m 1024\u001b[39m kwds.update(kwds_defaults)\n\u001b[32m-> \u001b[39m\u001b[32m1026\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_read\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilepath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwds\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:620\u001b[39m, in \u001b[36m_read\u001b[39m\u001b[34m(filepath_or_buffer, kwds)\u001b[39m\n\u001b[32m 617\u001b[39m _validate_names(kwds.get(\u001b[33m\"\u001b[39m\u001b[33mnames\u001b[39m\u001b[33m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m))\n\u001b[32m 619\u001b[39m \u001b[38;5;66;03m# Create the parser.\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m620\u001b[39m parser = \u001b[43mTextFileReader\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilepath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwds\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 622\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m chunksize \u001b[38;5;129;01mor\u001b[39;00m iterator:\n\u001b[32m 623\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m parser\n", + "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1620\u001b[39m, in \u001b[36mTextFileReader.__init__\u001b[39m\u001b[34m(self, f, engine, **kwds)\u001b[39m\n\u001b[32m 1617\u001b[39m \u001b[38;5;28mself\u001b[39m.options[\u001b[33m\"\u001b[39m\u001b[33mhas_index_names\u001b[39m\u001b[33m\"\u001b[39m] = kwds[\u001b[33m\"\u001b[39m\u001b[33mhas_index_names\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 1619\u001b[39m \u001b[38;5;28mself\u001b[39m.handles: IOHandles | \u001b[38;5;28;01mNone\u001b[39;00m = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m1620\u001b[39m \u001b[38;5;28mself\u001b[39m._engine = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_make_engine\u001b[49m\u001b[43m(\u001b[49m\u001b[43mf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mengine\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\pandas\\io\\parsers\\readers.py:1880\u001b[39m, in \u001b[36mTextFileReader._make_engine\u001b[39m\u001b[34m(self, f, engine)\u001b[39m\n\u001b[32m 1878\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mb\u001b[39m\u001b[33m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m mode:\n\u001b[32m 1879\u001b[39m mode += \u001b[33m\"\u001b[39m\u001b[33mb\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m-> \u001b[39m\u001b[32m1880\u001b[39m \u001b[38;5;28mself\u001b[39m.handles = \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 1881\u001b[39m \u001b[43m \u001b[49m\u001b[43mf\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1882\u001b[39m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1883\u001b[39m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43moptions\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mencoding\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1884\u001b[39m \u001b[43m \u001b[49m\u001b[43mcompression\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43moptions\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcompression\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1885\u001b[39m \u001b[43m \u001b[49m\u001b[43mmemory_map\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43moptions\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mmemory_map\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1886\u001b[39m \u001b[43m \u001b[49m\u001b[43mis_text\u001b[49m\u001b[43m=\u001b[49m\u001b[43mis_text\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1887\u001b[39m \u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43moptions\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mencoding_errors\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mstrict\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1888\u001b[39m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43moptions\u001b[49m\u001b[43m.\u001b[49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mstorage_options\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 1889\u001b[39m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1890\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mself\u001b[39m.handles \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 1891\u001b[39m f = \u001b[38;5;28mself\u001b[39m.handles.handle\n", + "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\PC\\Desktop\\sprint5\\Churn-Prediction-avec-MLflow\\venv\\Lib\\site-packages\\pandas\\io\\common.py:873\u001b[39m, in \u001b[36mget_handle\u001b[39m\u001b[34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[39m\n\u001b[32m 868\u001b[39m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(handle, \u001b[38;5;28mstr\u001b[39m):\n\u001b[32m 869\u001b[39m \u001b[38;5;66;03m# Check whether the filename is to be opened in binary mode.\u001b[39;00m\n\u001b[32m 870\u001b[39m \u001b[38;5;66;03m# Binary mode does not support 'encoding' and 'newline'.\u001b[39;00m\n\u001b[32m 871\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m ioargs.encoding \u001b[38;5;129;01mand\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mb\u001b[39m\u001b[33m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m ioargs.mode:\n\u001b[32m 872\u001b[39m \u001b[38;5;66;03m# Encoding\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m873\u001b[39m handle = \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[32m 874\u001b[39m \u001b[43m \u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 875\u001b[39m \u001b[43m \u001b[49m\u001b[43mioargs\u001b[49m\u001b[43m.\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 876\u001b[39m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[43m=\u001b[49m\u001b[43mioargs\u001b[49m\u001b[43m.\u001b[49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 877\u001b[39m \u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[43m=\u001b[49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 878\u001b[39m \u001b[43m \u001b[49m\u001b[43mnewline\u001b[49m\u001b[43m=\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 879\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 880\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 881\u001b[39m \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[32m 882\u001b[39m handle = \u001b[38;5;28mopen\u001b[39m(handle, ioargs.mode)\n", + "\u001b[31mFileNotFoundError\u001b[39m: [Errno 2] No such file or directory: 'data/dataset.csv'" + ] + } + ], "source": [ "# ------------------------------------------------------------\n", "# 🔹 1. Charger le dataset\n", "# ------------------------------------------------------------\n", - "df = pd.read_csv(\"dataset.csv\")\n", + "df = pd.read_csv(\"data/dataset.csv\")\n", "df = df.drop(columns=[\"RowNumber\", \"CustomerId\", \"Surname\"], errors=\"ignore\")\n", "df = df[df[\"Age\"] <= 80]" ] @@ -246,8 +263,22 @@ "main_language": "python", "notebook_metadata_filter": "-all" }, + "kernelspec": { + "display_name": "venv (3.12.2)", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" } }, "nbformat": 4, diff --git a/outputs/reports/model_comparison.md b/outputs/reports/model_comparison.md index e11bcfe7..331a805d 100644 --- a/outputs/reports/model_comparison.md +++ b/outputs/reports/model_comparison.md @@ -1,22 +1,13 @@ -# 🧾 Rapport de comparaison des modèles -**Expérience MLflow :** Churn_Prediction_Models -**Nombre de runs :** 9 +# 🧾 Rapport de comparaison des modèles -## 🏆 Meilleur modèle -**RandomForestClassifier (SMOTE)** -- **F1-score :** 0.842 -- **Accuracy :** 0.873 +**Expérience MLflow :** Churn_Prediction_Models -## 📊 Observations générales -- La stratégie **SMOTE** améliore nettement le rappel sur la classe minoritaire (clients churnés). -- La **Random Forest** offre le meilleur compromis biais-variance et gère bien la non-linéarité. -- La **Régression Logistique** reste un bon baseline mais sous-performe sur des données déséquilibrées. -- **XGBoost** atteint de bons résultats mais nécessite plus d’optimisation d’hyperparamètres. +**Nombre de runs :** 1 -## 📈 Visualisations -Les courbes ROC et matrices de confusion sont disponibles dans MLflow UI pour comparaison. +**Meilleur modèle :** DummyModel (none) +- F1-score : 0.500 +- Accuracy : 0.500 -## 💡 Recommandation -Utiliser le modèle **RandomForest avec SMOTE** pour le scoring de churn, puis affiner les hyperparamètres (n_estimators, max_depth). -Prochaine étape : déploiement du modèle via **MLflow Model Registry**. +Les figures ci-dessus montrent la comparaison entre les trois modèles et les différentes stratégies d'équilibrage. +Le meilleur compromis entre précision et rappel est obtenu avec **DummyModel** en mode **none**. diff --git a/outputs/reports/model_comparison_results.csv b/outputs/reports/model_comparison_results.csv new file mode 100644 index 00000000..70a79e5d --- /dev/null +++ b/outputs/reports/model_comparison_results.csv @@ -0,0 +1,2 @@ +Model,Strategy,f1,Accuracy,Run_ID +DummyModel,none,0.5,0.5,9ef1f5bd1b494066bbf7d0c26b56384f