{
"cells": [
{
"cell_type": "markdown",
"id": "ac01a6ea-bef6-4ace-89ff-1dc03a4215c2",
"metadata": {},
"source": [
"# Segmentation des clients par régression logistique"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "bca785be-39f7-4583-9bd8-67c1134ae275",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import os\n",
"import s3fs\n",
"import re\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.metrics import accuracy_score, confusion_matrix, classification_report\n",
"from sklearn.preprocessing import StandardScaler\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "3bf57816-b023-4e84-9450-095620bddebc",
"metadata": {},
"outputs": [],
"source": [
"# Create filesystem object\n",
"S3_ENDPOINT_URL = \"https://\" + os.environ[\"AWS_S3_ENDPOINT\"]\n",
"fs = s3fs.S3FileSystem(client_kwargs={'endpoint_url': S3_ENDPOINT_URL})"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "27002f2f-a78a-414c-8e4f-b15bf6dd9e40",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_543/1677066092.py:7: DtypeWarning: Columns (40) have mixed types. Specify dtype option on import or set low_memory=False.\n",
" dataset_train = pd.read_csv(file_in, sep=\",\")\n",
"/tmp/ipykernel_543/1677066092.py:12: DtypeWarning: Columns (40) have mixed types. Specify dtype option on import or set low_memory=False.\n",
" dataset_test = pd.read_csv(file_in, sep=\",\")\n"
]
}
],
"source": [
"# Importation des données\n",
"BUCKET = \"projet-bdc2324-team1/1_Output/Logistique Regression databases - First approach\"\n",
"\n",
"FILE_PATH_S3 = BUCKET + \"/\" + \"dataset_train.csv\"\n",
"\n",
"with fs.open(FILE_PATH_S3, mode=\"rb\") as file_in:\n",
" dataset_train = pd.read_csv(file_in, sep=\",\")\n",
"\n",
"FILE_PATH_S3 = BUCKET + \"/\" + \"dataset_test.csv\"\n",
"\n",
"with fs.open(FILE_PATH_S3, mode=\"rb\") as file_in:\n",
" dataset_test = pd.read_csv(file_in, sep=\",\")\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "c3928b55-8821-46da-b3b5-a036efd6d2cf",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" event_type_id | \n",
" name_event_types | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2.0 | \n",
" offre muséale individuel | \n",
"
\n",
" \n",
" 1 | \n",
" 4.0 | \n",
" spectacle vivant | \n",
"
\n",
" \n",
" 2 | \n",
" 5.0 | \n",
" offre muséale groupe | \n",
"
\n",
" \n",
" 3 | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" event_type_id name_event_types\n",
"0 2.0 offre muséale individuel\n",
"1 4.0 spectacle vivant\n",
"2 5.0 offre muséale groupe\n",
"3 NaN NaN"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_train[['event_type_id', 'name_event_types']].drop_duplicates()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "7e8a9d4d-7e55-4173-a7f4-8b8baa9610d2",
"metadata": {},
"outputs": [],
"source": [
"#Choose type of event \n",
"type_event_choosed = 5\n",
"\n",
"dataset_test = dataset_test[(dataset_test['event_type_id'] == type_event_choosed) | np.isnan(dataset_test['event_type_id'])]\n",
"dataset_test['y_has_purchased'] = dataset_test['y_has_purchased'].fillna(0)\n",
"dataset_train = dataset_train[(dataset_train['event_type_id'] == type_event_choosed) | np.isnan(dataset_train['event_type_id'])]\n",
"dataset_train['y_has_purchased'] = dataset_train['y_has_purchased'].fillna(0)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "e20ced8f-df1c-43bb-8d15-79f414c8225c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"customer_id 0.000000\n",
"event_type_id 0.950522\n",
"nb_tickets 0.000000\n",
"nb_purchases 0.000000\n",
"total_amount 0.000000\n",
"nb_suppliers 0.000000\n",
"vente_internet_max 0.000000\n",
"purchase_date_min 0.950522\n",
"purchase_date_max 0.950522\n",
"time_between_purchase 0.950522\n",
"nb_tickets_internet 0.000000\n",
"name_event_types 0.950522\n",
"avg_amount 0.950522\n",
"street_id 0.000000\n",
"is_partner 0.000000\n",
"gender 0.000000\n",
"is_email_true 0.000000\n",
"opt_in 0.000000\n",
"structure_id 0.863048\n",
"mcp_contact_id 0.297275\n",
"last_buying_date 0.611718\n",
"max_price 0.611718\n",
"ticket_sum 0.000000\n",
"average_price 0.102225\n",
"fidelity 0.000000\n",
"average_purchase_delay 0.611718\n",
"average_price_basket 0.611718\n",
"average_ticket_basket 0.611718\n",
"total_price 0.509493\n",
"purchase_count 0.000000\n",
"first_buying_date 0.611718\n",
"country 0.063488\n",
"tenant_id 0.000000\n",
"gender_label 0.000000\n",
"gender_female 0.000000\n",
"gender_male 0.000000\n",
"gender_other 0.000000\n",
"country_fr 0.063488\n",
"nb_campaigns 0.000000\n",
"nb_campaigns_opened 0.000000\n",
"time_to_open 0.543355\n",
"y_has_purchased 0.000000\n",
"dtype: float64"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_train.isna().sum()/len(dataset_train)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "05e29adb-7eef-416f-8f7b-248229eee0fe",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"nb_tickets 0\n",
"nb_purchases 0\n",
"total_amount 0\n",
"nb_suppliers 0\n",
"vente_internet_max 0\n",
"nb_tickets_internet 0\n",
"opt_in 0\n",
"fidelity 0\n",
"nb_campaigns 0\n",
"nb_campaigns_opened 0\n",
"dtype: int64"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_train[['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'vente_internet_max', 'nb_tickets_internet', 'opt_in', 'fidelity', 'nb_campaigns', 'nb_campaigns_opened']].isna().sum()\n",
"# pas de NaN, OK !"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "2ce94258-e2d1-472a-81fc-fc11e247b423",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"161.0"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_train['y_has_purchased'].sum()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "34bae3f7-d579-4f80-a38d-a83eb5ea8a7b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.9985491193310349\n",
"Confusion Matrix:\n",
" [[127988 49]\n",
" [ 137 24]]\n",
"Classification Report:\n",
" precision recall f1-score support\n",
"\n",
" 0.0 1.00 1.00 1.00 128037\n",
" 1.0 0.33 0.15 0.21 161\n",
"\n",
" accuracy 1.00 128198\n",
" macro avg 0.66 0.57 0.60 128198\n",
"weighted avg 1.00 1.00 1.00 128198\n",
"\n"
]
}
],
"source": [
"\n",
"reg_columns = ['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'vente_internet_max', 'nb_tickets_internet', 'opt_in', 'fidelity', 'nb_campaigns', 'nb_campaigns_opened']\n",
"\n",
"X_train = dataset_train[reg_columns]\n",
"y_train = dataset_train['y_has_purchased']\n",
"X_test = dataset_test[reg_columns]\n",
"y_test = dataset_test['y_has_purchased']\n",
"\n",
"# Fit and transform the scaler on the training data\n",
"scaler = StandardScaler()\n",
"\n",
"# Transform the test data using the same scaler\n",
"X_train_scaled = scaler.fit_transform(X_train)\n",
"X_test_scaled = scaler.fit_transform(X_test)\n",
"\n",
"# Create and fit the linear regression model\n",
"logit_model = LogisticRegression(penalty='l1', solver='liblinear', C=1.0)\n",
"logit_model.fit(X_train_scaled, y_train)\n",
"\n",
"y_pred = logit_model.predict(X_test_scaled)\n",
"\n",
"#Evaluation du modèle \n",
"accuracy = accuracy_score(y_test, y_pred)\n",
"conf_matrix = confusion_matrix(y_test, y_pred)\n",
"class_report = classification_report(y_test, y_pred)\n",
"\n",
"print(\"Accuracy:\", accuracy)\n",
"print(\"Confusion Matrix:\\n\", conf_matrix)\n",
"print(\"Classification Report:\\n\", class_report)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "ccc78c36-3287-46e6-89ac-7494c1a7106a",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjYAAAHFCAYAAADhWLMfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAABUp0lEQVR4nO3dfVyN9/8H8Nfp7qjo6EblkPvWJBsyCXMz5K7iu+2LZdFmMaE1uVkzt9vK3RcjcjM3m7G2ITM3LdPGGpFoijBETEducpBUO12/P/xc21FWca7rcLye38f1eDjX9T7X9T7HN733/nw+16UQBEEAERERkQkwM3YCRERERIbCwoaIiIhMBgsbIiIiMhksbIiIiMhksLAhIiIik8HChoiIiEwGCxsiIiIyGSxsiIiIyGSwsCEiIiKTwcKGTNrRo0fx1ltvoXHjxqhRowZq1qyJNm3aYM6cObh+/bqk1z5y5Ai6dOkClUoFhUKBhQsXGvwaCoUC06dPN/h5K7N27VooFAooFAr88ssv5Y4LgoBmzZpBoVCga9euj3SNpUuXYu3atdV6zy+//PLQnIjo2WBh7ASIpLJy5UqEhYXBw8MDEyZMgKenJ0pLS3Ho0CEsW7YM+/fvR0JCgmTXf/vtt1FYWIj4+HjY29ujUaNGBr/G/v37Ub9+fYOft6pq1aqFVatWlSte9uzZgzNnzqBWrVqPfO6lS5fCyckJISEhVX5PmzZtsH//fnh6ej7ydYno6cbChkzS/v37MWrUKPTs2RNbtmyBUqkUj/Xs2RORkZFITEyUNIesrCyEhoaiT58+kl2jffv2kp27KgYNGoT169djyZIlsLOzE/evWrUKvr6+uHnzpix5lJaWQqFQwM7OzujfCREZF4eiyCRFR0dDoVBgxYoVekXNfVZWVggMDBRfl5WVYc6cOXj++eehVCrh7OyMoUOH4uLFi3rv69q1K7y8vJCWloaXX34ZNjY2aNKkCWbNmoWysjIAfw/T/PXXX4iLixOHbABg+vTp4p//6f57zp07J+5LTk5G165d4ejoCGtrazRo0ACvvfYa7ty5I8ZUNBSVlZWF/v37w97eHjVq1ECrVq3wxRdf6MXcH7L5+uuvMXnyZKjVatjZ2aFHjx44efJk1b5kAG+88QYA4Ouvvxb3abVabNq0CW+//XaF75kxYwZ8fHzg4OAAOzs7tGnTBqtWrcI/n8fbqFEjHDt2DHv27BG/v/sdr/u5r1u3DpGRkahXrx6USiVOnz5dbijq6tWrcHNzQ4cOHVBaWiqe//jx47C1tUVwcHCVPysRPR1Y2JDJ0el0SE5Ohre3N9zc3Kr0nlGjRmHSpEno2bMntm7dio8//hiJiYno0KEDrl69qher0WgwZMgQvPnmm9i6dSv69OmDqKgofPXVVwCAfv36Yf/+/QCA119/Hfv37xdfV9W5c+fQr18/WFlZYfXq1UhMTMSsWbNga2uLkpKSh77v5MmT6NChA44dO4ZFixZh8+bN8PT0REhICObMmVMu/sMPP8T58+fx+eefY8WKFfjjjz8QEBAAnU5XpTzt7Ozw+uuvY/Xq1eK+r7/+GmZmZhg0aNBDP9vIkSPx7bffYvPmzXj11VcxduxYfPzxx2JMQkICmjRpgtatW4vf34PDhlFRUcjNzcWyZcvwww8/wNnZudy1nJycEB8fj7S0NEyaNAkAcOfOHfz3v/9FgwYNsGzZsip9TiJ6ighEJkaj0QgAhMGDB1cpPjs7WwAghIWF6e0/cOCAAED48MMPxX1dunQRAAgHDhzQi/X09BR69eqltw+AMHr0aL1906ZNEyr6sVuzZo0AQMjJyREEQRA2btwoABAyMjL+NXcAwrRp08TXgwcPFpRKpZCbm6sX16dPH8HGxka4ceOGIAiC8PPPPwsAhL59++rFffvttwIAYf/+/f963fv5pqWliefKysoSBEEQXnrpJSEkJEQQBEFo0aKF0KVLl4eeR6fTCaWlpcLMmTMFR0dHoaysTDz2sPfev17nzp0feuznn3/W2z979mwBgJCQkCAMGzZMsLa2Fo4ePfqvn5GInk7s2NAz7+effwaAcpNU27Vrh+bNm2P37t16+11dXdGuXTu9fS+88ALOnz9vsJxatWoFKysrjBgxAl988QXOnj1bpfclJyeje/fu5TpVISEhuHPnTrnO0T+H44B7nwNAtT5Lly5d0LRpU6xevRqZmZlIS0t76DDU/Rx79OgBlUoFc3NzWFpaYurUqbh27Rry8/OrfN3XXnutyrETJkxAv3798MYbb+CLL77A4sWL0bJlyyq/n4ieHixsyOQ4OTnBxsYGOTk5VYq/du0aAKBu3brljqnVavH4fY6OjuXilEolioqKHiHbijVt2hQ//fQTnJ2dMXr0aDRt2hRNmzbFZ5999q/vu3bt2kM/x/3j//TgZ7k/H6k6n0WhUOCtt97CV199hWXLluG5557Dyy+/XGHswYMH4efnB+DeqrXffvsNaWlpmDx5crWvW9Hn/LccQ0JCcPfuXbi6unJuDZEJY2FDJsfc3Bzdu3dHenp6ucm/Fbn/yz0vL6/csUuXLsHJyclgudWoUQMAUFxcrLf/wXk8APDyyy/jhx9+gFarRWpqKnx9fREREYH4+PiHnt/R0fGhnwOAQT/LP4WEhODq1atYtmwZ3nrrrYfGxcfHw9LSEtu2bcPAgQPRoUMHtG3b9pGuWdEk7IfJy8vD6NGj0apVK1y7dg3jx49/pGsS0ZOPhQ2ZpKioKAiCgNDQ0Aon25aWluKHH34AALzyyisAIE7+vS8tLQ3Z2dno3r27wfK6v7Ln6NGjevvv51IRc3Nz+Pj4YMmSJQCAw4cPPzS2e/fuSE5OFguZ+7788kvY2NhIthS6Xr16mDBhAgICAjBs2LCHxikUClhYWMDc3FzcV1RUhHXr1pWLNVQXTKfT4Y033oBCocDOnTsRExODxYsXY/PmzY99biJ68vA+NmSSfH19ERcXh7CwMHh7e2PUqFFo0aIFSktLceTIEaxYsQJeXl4ICAiAh4cHRowYgcWLF8PMzAx9+vTBuXPnMGXKFLi5ueH99983WF59+/aFg4MDhg8fjpkzZ8LCwgJr167FhQsX9OKWLVuG5ORk9OvXDw0aNMDdu3fFlUc9evR46PmnTZuGbdu2oVu3bpg6dSocHBywfv16bN++HXPmzIFKpTLYZ3nQrFmzKo3p168f5s+fj6CgIIwYMQLXrl3DvHnzKlyS37JlS8THx+Obb75BkyZNUKNGjUeaFzNt2jT8+uuvSEpKgqurKyIjI7Fnzx4MHz4crVu3RuPGjat9TiJ6crGwIZMVGhqKdu3aYcGCBZg9ezY0Gg0sLS3x3HPPISgoCGPGjBFj4+Li0LRpU6xatQpLliyBSqVC7969ERMTU+GcmkdlZ2eHxMRERERE4M0330Tt2rXxzjvvoE+fPnjnnXfEuFatWiEpKQnTpk2DRqNBzZo14eXlha1bt4pzVCri4eGBffv24cMPP8To0aNRVFSE5s2bY82aNdW6g69UXnnlFaxevRqzZ89GQEAA6tWrh9DQUDg7O2P48OF6sTNmzEBeXh5CQ0Nx69YtNGzYUO8+P1Wxa9cuxMTEYMqUKXqdt7Vr16J169YYNGgQUlJSYGVlZYiPR0RPAIUg/OOuWERERERPMc6xISIiIpPBwoaIiIhMBgsbIiIiMhksbIiIiMhksLAhIiIik8HChoiIiEwGCxsiIiIyGSZ5gz7r1mMqDyJ6BhWkxRo7BaInTg0ZfhMa6vdS0RH+DFeGHRsiIiIyGSbZsSEiInqiKNhHkAsLGyIiIqkpFMbO4JnBwoaIiEhq7NjIht80ERERmQx2bIiIiKTGoSjZsLAhIiKSGoeiZMNvmoiIiEwGOzZERERS41CUbFjYEBERSY1DUbLhN01EREQmgx0bIiIiqXEoSjYsbIiIiKTGoSjZ8JsmIiIik8GODRERkdQ4FCUbFjZERERS41CUbFjYEBERSY0dG9mwhCQiIiKTwcKGiIhIagozw2zVtHfvXgQEBECtVkOhUGDLli3isdLSUkyaNAktW7aEra0t1Go1hg4dikuXLumdo7i4GGPHjoWTkxNsbW0RGBiIixcv6sUUFBQgODgYKpUKKpUKwcHBuHHjhl5Mbm4uAgICYGtrCycnJ4SHh6OkpEQvJjMzE126dIG1tTXq1auHmTNnQhCEan1mFjZERERSM1JhU1hYiBdffBGxsbHljt25cweHDx/GlClTcPjwYWzevBmnTp1CYGCgXlxERAQSEhIQHx+PlJQU3L59G/7+/tDpdGJMUFAQMjIykJiYiMTERGRkZCA4OFg8rtPp0K9fPxQWFiIlJQXx8fHYtGkTIiMjxZibN2+iZ8+eUKvVSEtLw+LFizFv3jzMnz+/Wp9ZIVS3FHoKWLceY+wUiJ5IBWnl/3EjetbVkGG2qXWXmQY5T9GeqY/8XoVCgYSEBAwYMOChMWlpaWjXrh3Onz+PBg0aQKvVok6dOli3bh0GDRoEALh06RLc3NywY8cO9OrVC9nZ2fD09ERqaip8fHwAAKmpqfD19cWJEyfg4eGBnTt3wt/fHxcuXIBarQYAxMfHIyQkBPn5+bCzs0NcXByioqJw+fJlKJVKAMCsWbOwePFiXLx4EYoqzlNix4aIiEhqZgqDbMXFxbh586beVlxcbLA0tVotFAoFateuDQBIT09HaWkp/Pz8xBi1Wg0vLy/s27cPALB//36oVCqxqAGA9u3bQ6VS6cV4eXmJRQ0A9OrVC8XFxUhPTxdjunTpIhY192MuXbqEc+fOVfkzsLAhIiKSmoGGomJiYsR5LPe3mJgYg6R49+5dfPDBBwgKCoKdnR0AQKPRwMrKCvb29nqxLi4u0Gg0Yoyzs3O58zk7O+vFuLi46B23t7eHlZXVv8bcf30/piq43JuIiOgpERUVhXHjxunt+2eH41GVlpZi8ODBKCsrw9KlSyuNFwRBb2ioomEiQ8Tcny1T1WEogB0bIiIi6SkUBtmUSiXs7Oz0tsctbEpLSzFw4EDk5ORg165dYrcGAFxdXVFSUoKCggK99+Tn54vdFFdXV1y+fLncea9cuaIX82DXpaCgAKWlpf8ak5+fDwDlOjn/hoUNERGR1Iy0Kqoy94uaP/74Az/99BMcHR31jnt7e8PS0hK7du0S9+Xl5SErKwsdOnQAAPj6+kKr1eLgwYNizIEDB6DVavVisrKykJeXJ8YkJSVBqVTC29tbjNm7d6/eEvCkpCSo1Wo0atSoyp+JhQ0REZGJun37NjIyMpCRkQEAyMnJQUZGBnJzc/HXX3/h9ddfx6FDh7B+/XrodDpoNBpoNBqxuFCpVBg+fDgiIyOxe/duHDlyBG+++SZatmyJHj16AACaN2+O3r17IzQ0FKmpqUhNTUVoaCj8/f3h4eEBAPDz84OnpyeCg4Nx5MgR7N69G+PHj0doaKjYIQoKCoJSqURISAiysrKQkJCA6OhojBs3rlpDUVzuTfQM4XJvovJkWe7dc7ZBzlO0a1K14n/55Rd069at3P5hw4Zh+vTpaNy4cYXv+/nnn9G1a1cA9yYVT5gwARs2bEBRURG6d++OpUuXws3NTYy/fv06wsPDsXXrVgBAYGAgYmNjxdVVwL0b9IWFhSE5ORnW1tYICgrCvHnz9IbSMjMzMXr0aBw8eBD29vZ49913MXXqVBY2LGyIKsbChqg8WQobv7kGOU9R0gSDnMeUcVUUERGR1PgQTNlwjg0RERGZDHZsiIiIpCbBiiaqGAsbIiIiqXEoSjYsIYmIiMhksGNDREQkNQ5FyYaFDRERkdQ4FCUblpBERERkMtixISIikhqHomTDwoaIiEhqLGxkw2+aiIiITAY7NkRERFLj5GHZsLAhIiKSGoeiZMPChoiISGrs2MiGJSQRERGZDHZsiIiIpMahKNmwsCEiIpIah6JkwxKSiIiITAY7NkRERBJTsGMjGxY2REREEmNhIx8ORREREZHJYMeGiIhIamzYyIaFDRERkcQ4FCUfDkURERGRyWDHhoiISGLs2MiHhQ0REZHEWNjIh4UNERGRxFjYyIdzbIiIiMhksGNDREQkNTZsZMPChoiISGIcipIPh6KIiIjIZLBjQ0REJDF2bOTDwoaIiEhiLGzkw6EoIiIiMhns2BAREUmMHRv5sLAhIiKSGusa2XAoioiIiEwGOzZEREQS41CUfFjYEBERSYyFjXxY2BAREUmMhY18jFrYFBYWYsOGDdi3bx80Gg0UCgVcXFzQsWNHvPHGG7C1tTVmekRERPSUMdrk4ePHj+O5557DxIkTUVBQgAYNGqB+/fooKCjAhAkT4OHhgePHjxsrPSIiIsNRGGijShmtYzN69Gh07twZX3zxBaysrPSOlZSUICQkBKNHj8bPP/9spAyJiIgMg0NR8jFaYXPgwAEcOnSoXFEDAFZWVvjwww/Rrl07I2RGRERETyujDUXZ29vjjz/+eOjx06dPw97eXsaMiIiIpKFQKAyyUeWM1rEJDQ3FsGHD8NFHH6Fnz55wcXGBQqGARqPBrl27EB0djYiICGOlR0REZDAsSuRjtMJm+vTpsLa2xvz58zFx4kTxL10QBLi6uuKDDz7AxIkTjZUeERERPYWM+kiFSZMm4dKlSzhz5gxSUlKQkpKCM2fO4NKlSyxqiIjIZBhrKGrv3r0ICAiAWq2GQqHAli1b9I4LgoDp06dDrVbD2toaXbt2xbFjx/RiiouLMXbsWDg5OcHW1haBgYG4ePGiXkxBQQGCg4OhUqmgUqkQHByMGzdu6MXk5uYiICAAtra2cHJyQnh4OEpKSvRiMjMz0aVLF1hbW6NevXqYOXMmBEGo1md+Ip4V1bhxY/j6+sLX1xeNGzc2djpERESGZaTl3oWFhXjxxRcRGxtb4fE5c+Zg/vz5iI2NRVpaGlxdXdGzZ0/cunVLjImIiEBCQgLi4+ORkpKC27dvw9/fHzqdTowJCgpCRkYGEhMTkZiYiIyMDAQHB4vHdTod+vXrh8LCQqSkpCA+Ph6bNm1CZGSkGHPz5k307NkTarUaaWlpWLx4MebNm4f58+dX6zMrhOqWQk8B69ZjjJ0C0ROpIK3if9yInmU1ZJiUoX53s0HOc2nZq4/8XoVCgYSEBAwYMADAvW6NWq1GREQEJk2aBOBed8bFxQWzZ8/GyJEjodVqUadOHaxbtw6DBg26l8OlS3Bzc8OOHTvQq1cvZGdnw9PTE6mpqfDx8QEApKamwtfXFydOnICHhwd27twJf39/XLhwAWq1GgAQHx+PkJAQ5Ofnw87ODnFxcYiKisLly5ehVCoBALNmzcLixYtx8eLFKnesnoiODRERkSkz1FBUcXExbt68qbcVFxc/Uk45OTnQaDTw8/MT9ymVSnTp0gX79u0DAKSnp6O0tFQvRq1Ww8vLS4zZv38/VCqVWNQAQPv27aFSqfRivLy8xKIGAHr16oXi4mKkp6eLMV26dBGLmvsxly5dwrlz56r8uVjYEBERScxQhU1MTIw4j+X+FhMT80g5aTQaAICLi4vefhcXF/GYRqOBlZVVuduvPBjj7Oxc7vzOzs56MQ9ex97eHlZWVv8ac//1/Ziq4EMwiYiIJGao5d5RUVEYN26c3r5/djgexYO5CYJQab4PxlQUb4iY+7NlqvP9Gb1jk5iYiJSUFPH1kiVL0KpVKwQFBaGgoMCImRERET1ZlEol7Ozs9LZHLWxcXV0BlO+G5Ofni50SV1dXlJSUlPt9/GDM5cuXy53/ypUrejEPXqegoAClpaX/GpOfnw+gfFfp3xi9sJkwYQJu3rwJ4N4yr8jISPTt2xdnz54tV5USERE9lZ7Ah2A2btwYrq6u2LVrl7ivpKQEe/bsQYcOHQAA3t7esLS01IvJy8tDVlaWGOPr6wutVouDBw+KMQcOHIBWq9WLycrKQl5enhiTlJQEpVIJb29vMWbv3r16S8CTkpKgVqvRqFGjKn8uow9F5eTkwNPTEwCwadMm+Pv7Izo6GocPH0bfvn2NnB0REdHjM9adh2/fvo3Tp0+Lr3NycpCRkQEHBwc0aNAAERERiI6Ohru7O9zd3REdHQ0bGxsEBQUBAFQqFYYPH47IyEg4OjrCwcEB48ePR8uWLdGjRw8AQPPmzdG7d2+EhoZi+fLlAIARI0bA398fHh4eAAA/Pz94enoiODgYc+fOxfXr1zF+/HiEhobCzs4OwL0l4zNmzEBISAg+/PBD/PHHH4iOjsbUqVOr9f0ZvbCxsrLCnTt3AAA//fQThg4dCgBwcHAQOzlERERUfYcOHUK3bt3E1/dHQoYNG4a1a9di4sSJKCoqQlhYGAoKCuDj44OkpCTUqlVLfM+CBQtgYWGBgQMHoqioCN27d8fatWthbm4uxqxfvx7h4eHi6qnAwEC9e+eYm5tj+/btCAsLQ8eOHWFtbY2goCDMmzdPjFGpVNi1axdGjx6Ntm3bwt7eHuPGjav26I3R72MTGBiIkpISdOzYER9//DFycnJQr149JCUlYcyYMTh16lS1z8n72FRNxzZN8f7QHmjj2QB166gw8P0V+OGXowAACwszTA8LQK9OLdC4viNu3r6L5AMnMGXRVuRd0QIAGtR1wMkdMys895AJq7D5pyMAgFbP18cn7w2Ad4sG0OkEbNmdgUn/24TCor/bjd6eDfBxeH+09nSDIADpx85j8sItOHrqTzGmh29zTHm3L5o3rYu7JaX47fAZfDA/AecvXZPqKzI5vI+N8axauRyLFs7HkDeHYmLUZADAtatXsXD+POzfl4Jbt26hjXdbfDB5Cho2bGTcZJ8xctzHpmH4DwY5z/lFAQY5jykz+hyb2NhYWFhYYOPGjYiLi0O9evUAADt37kTv3r2NnJ1ps7VWIvPUn3h/1rfljtnUsEKr5m6YtXInfN+YjcGRK+HewBnfLRwpxly8XIBGPaL0tplx23D7TjF+/O3eLbnr1lFh+7KxOHPhCjoHz0P/0Uvg2dQVK2f+fUfKmjZKbF06Ghc0BegcPA/d35qPW4V3sXXpaFhY3Pu/aKN6jvhuwQj8knYKPoNnITBsCRxr2yL+f+9I/C0RPb6szKPY+N03eO45D3GfIAiICB+NixcvYOHipfhmYwLqquth5PC3xC42mQ4+3Vs+Rh+KatCgAbZt21Zu/4IFC4yQzbMl6bfjSPrteIXHbt6+C/9R+v91P272d0hZPxFurva4oClAWZmAy9du6cUEdnsRG5PSxW5Mn5e9UPqXDhEx34rL9iJivsWBb6LQxM0JZy9cxXONXOCgssXHcdtw8fINAMCny3fi0Hcfws3VATkXr6J1czeYm5lh+pJt4nkWfrkb3y0YAQsLM/z1V5khvxoig7lTWIioSRMwbcYnWLk8Ttx//vw5HP09A5u+34ZmzdwBAJOnTEO3lzsgccd2vPr6f42VMtFTzegdm8OHDyMzM1N8/f3332PAgAH48MMPyz0ci4zLrpY1ysrKcONWUYXHWzd3Q6vn3fDFlv3iPqWVBUpLdXoPMSsqLgUAdGjVFABw6txlXCm4hWEDOsDSwhw1lJYIGeCLY6cvITfvOgAg/VgudGVlGNq/PczMFLCrWQNB/drhp/0nWNTQEy36k5no3LkL2vt20Ntf+v//vimt/l6qa25uDktLSxw5nC5rjiQ9dmzkY/TCZuTIkeI8mrNnz2Lw4MGwsbHBd999xyd8P0GUVhb4OLw/vtl5CLcK71YYM2yAL7LP5iH19xxx3y8HT8LF0Q7vD+0OSwtz1K5ljZljAwEArnVUAIDbd4rR653P8Ebfl1CQugBXf/sfevg2x3/GxkGnu1e05OZdh39YLGaMCYD2wEJc/nUe6rnUxtAP1kj8yYke3c4d25GdfRzh70eWO9aocROo1fWwaOH/cFOrRWlJCVatXIGrV6/gypUrRsiWJPUELvc2VUYvbE6dOoVWrVoBAL777jt07twZGzZswNq1a7Fp06ZK31/RczOEMl2l76Oqs7Aww7pZb8FMocB7MeXn4wBADaUlBvVpq9etAYDssxqETl2H8ODuuL5/Ps79FI2ci1ehuXoTZf9ftNRQWmL59Dex//ez6DJ0Hl55az6yz+YhYfEo1FBaAgBcHGshbuoQrP/hADq9ORc9hi9ASakOG+YNl/bDEz0iTV4e5sz6FNGz5lZ4AzVLS0v8b+EinD93Di93aAeftq1wKO0AOr3cGebmRv+nmeipZfQ5NoIgoKzs3i+4n376Cf7+/gAANzc3XL16tdL3x8TEYMaMGXr7zF1egmXddoZP9hlkYWGG9bOHo2E9R/QZsfih3Zr/9GgFmxpWWL/tYLlj3yQewjeJh+DsUAuFRcUQBCD8zVdw7s97q5kG9WmLBmoHdBn2P3HIaljUWuTtnYOAri/gux/TMXJQZ9wsvIvJn30vnvftyV/g9I+foF3LRjiYec7wH57oMRw/fgzXr13DGwP/fhqzTqdD+qE0xH+9HmlHMuHZwgvfbv4et27dQmlpKRwcHDBk8H/RooWXETMnKXAYST5GL2zatm2LTz75BD169MCePXsQF3dvcl1OTk6VbqFc0XMznF+eJEmuz5r7RU3TBnXQe8QiXNcWPjQ2ZEAHbN+TiasFtx8ak3/93kTjof3b425JKXanngBwbwVWWZmgNw+nTBAgCIDZ//9jYFPDSuzw3Kf7/4LYzIz/YNCTx6d9e2zcor/Ed9rkKDRq0gRvDQ/VuwfI/XuGnD9/DsePZWH02PdkzZWkx8JGPkYvbBYuXIghQ4Zgy5YtmDx5Mpo1awYA2Lhxo3gr5n+jVCrLtXkVZuYPiaZ/srW2QlO3OuLrRvUc8cJz9VBw8w4uXdFiw9x30Pp5N7z63jKYmyng4njvH9/r2jso/evv4b4mbk7o1KYpBoyNK3cNAHh3UGek/n4Wt++UoHv75xEdMQBTFn8P7e17k5B3p55AdMQALIwaiLj4PTBTKDD+LT/8pdNhz6F78692/noMY4d0Q9SI3vg2MR21bJSYMSYQ5y9dQ8aJi1J9RUSPzNa2Jtzdn9PbZ21jg9qq2uL+pB93wt7eAXXrqvHHHycxJyYa3V7pgQ4dOxkjZZIQ6xr5GL2weeGFF/RWRd03d+5cvf+iIcNr49kQSZ///V+Gc8a/BgBYtzUVnyzbgYCuLwAADn4Tpfc+v3c+w6/pf4ivh/X3xaV8LX7af6LC67T1aoiP3u2HmjZWOHnuMsZ8+jW+3p4mHj917jJee285Jo/sg1++iERZmYDfT1xE/9FLobl67+7Te9JOIeTDL/D+sB4YN6wn7twtwYGjOQgcvRR3/3+VFdHT5sqVK5g3ZxauXb2GOnXqwD+wP0a+G2bstIieaka/87AUeOdhoorxzsNE5clx52H3CYkGOc8fc3nj2soYvWOj0+mwYMECfPvtt8jNzS1375rr168bKTMiIiLD4FCUfIy+pnDGjBmYP38+Bg4cCK1Wi3HjxuHVV1+FmZkZpk+fbuz0iIiI6Cli9MJm/fr1WLlyJcaPHw8LCwu88cYb+PzzzzF16lSkpqYaOz0iIqLHxjsPy8fohY1Go0HLli0BADVr1oRWe+/J0f7+/ti+fbsxUyMiIjIIhcIwG1XO6IVN/fr1kZeXBwBo1qwZkpKSAABpaWkV3q2TiIiI6GGMXtj85z//we7duwEA7733HqZMmQJ3d3cMHToUb7/9tpGzIyIienxmZgqDbFQ5o6+KmjVrlvjn119/HfXr18e+ffvQrFkzBAYGGjEzIiIiw+AwknyMXtg8qH379mjfvr2x0yAiIqKnkFEKm61bt1Y5ll0bIiJ62nFFk3yMUtgMGDCgSnEKhQI6na7yQCIioicY6xr5GKWwKSsrqzyIiIjIRLBjIx+jr4oiIiIiMhSjFTbJycnw9PTEzZs3yx3TarVo0aIF9u7da4TMiIiIDIt3HpaP0QqbhQsXIjQ0FHZ2duWOqVQqjBw5EgsWLDBCZkRERIbFOw/Lx2iFze+//47evR/++HU/Pz+kp6fLmBERERE97Yx2H5vLly/D0tLyocctLCxw5coVGTMiIiKSBoeR5GO0jk29evWQmZn50ONHjx5F3bp1ZcyIiIhIGhyKko/RCpu+ffti6tSpuHv3brljRUVFmDZtGvz9/Y2QGRERET2tjDYU9dFHH2Hz5s147rnnMGbMGHh4eEChUCA7OxtLliyBTqfD5MmTjZUeERGRwXAoSj5GK2xcXFywb98+jBo1ClFRURAEAcC9v/xevXph6dKlcHFxMVZ6REREBsO6Rj5GfQhmw4YNsWPHDhQUFOD06dMQBAHu7u6wt7c3ZlpERET0lHoinu5tb2+Pl156ydhpEBERSYJDUfJ5IgobIiIiU8a6Rj4sbIiIiCTGjo18+BBMIiIiMhns2BAREUmMDRv5sLAhIiKSGIei5MOhKCIiIjIZ7NgQERFJjA0b+bCwISIikhiHouTDoSgiIiIyGezYEBERSYwNG/mwsCEiIpIYh6Lkw6EoIiIiMhns2BAREUmMHRv5sLAhIiKSGOsa+XAoioiISGIKhcIgW3X89ddf+Oijj9C4cWNYW1ujSZMmmDlzJsrKysQYQRAwffp0qNVqWFtbo2vXrjh27JjeeYqLizF27Fg4OTnB1tYWgYGBuHjxol5MQUEBgoODoVKpoFKpEBwcjBs3bujF5ObmIiAgALa2tnByckJ4eDhKSkqq90VWAQsbIiIiEzR79mwsW7YMsbGxyM7Oxpw5czB37lwsXrxYjJkzZw7mz5+P2NhYpKWlwdXVFT179sStW7fEmIiICCQkJCA+Ph4pKSm4ffs2/P39odPpxJigoCBkZGQgMTERiYmJyMjIQHBwsHhcp9OhX79+KCwsREpKCuLj47Fp0yZERkYa/HMrBEEQDH5WI7NuPcbYKRA9kQrSYo2dAtETp4YMkzK6fbbPIOf5+b0OVY719/eHi4sLVq1aJe577bXXYGNjg3Xr1kEQBKjVakRERGDSpEkA7nVnXFxcMHv2bIwcORJarRZ16tTBunXrMGjQIADApUuX4Obmhh07dqBXr17Izs6Gp6cnUlNT4ePjAwBITU2Fr68vTpw4AQ8PD+zcuRP+/v64cOEC1Go1ACA+Ph4hISHIz8+HnZ2dQb4fgB0bIiIiyRljKKpTp07YvXs3Tp06BQD4/fffkZKSgr59+wIAcnJyoNFo4OfnJ75HqVSiS5cu2LfvXiGWnp6O0tJSvRi1Wg0vLy8xZv/+/VCpVGJRAwDt27eHSqXSi/Hy8hKLGgDo1asXiouLkZ6eXq3PVRlOHiYiInpKFBcXo7i4WG+fUqmEUqksFztp0iRotVo8//zzMDc3h06nw6effoo33ngDAKDRaAAALi4ueu9zcXHB+fPnxRgrKyvY29uXi7n/fo1GA2dn53LXd3Z21ot58Dr29vawsrISYwyFHRsiIiKJKRSG2WJiYsQJuve3mJiYCq/5zTff4KuvvsKGDRtw+PBhfPHFF5g3bx6++OKLB3LT7wQJglBpd+jBmIriHyXGENixISIikpiZgX55R0VFYdy4cXr7KurWAMCECRPwwQcfYPDgwQCAli1b4vz584iJicGwYcPg6uoK4F43pW7duuL78vPzxe6Kq6srSkpKUFBQoNe1yc/PR4cOHcSYy5cvl7v+lStX9M5z4MABveMFBQUoLS0t18l5XOzYEBERPSWUSiXs7Oz0tocVNnfu3IGZmf6veXNzc3G5d+PGjeHq6opdu3aJx0tKSrBnzx6xaPH29oalpaVeTF5eHrKyssQYX19faLVaHDx4UIw5cOAAtFqtXkxWVhby8vLEmKSkJCiVSnh7ez/OV1IOOzZEREQSM8YN+gICAvDpp5+iQYMGaNGiBY4cOYL58+fj7bff/v+cFIiIiEB0dDTc3d3h7u6O6Oho2NjYICgoCACgUqkwfPhwREZGwtHREQ4ODhg/fjxatmyJHj16AACaN2+O3r17IzQ0FMuXLwcAjBgxAv7+/vDw8AAA+Pn5wdPTE8HBwZg7dy6uX7+O8ePHIzQ01KArogAWNkRERJIzxiMVFi9ejClTpiAsLAz5+flQq9UYOXIkpk6dKsZMnDgRRUVFCAsLQ0FBAXx8fJCUlIRatWqJMQsWLICFhQUGDhyIoqIidO/eHWvXroW5ubkYs379eoSHh4urpwIDAxEb+/ftJczNzbF9+3aEhYWhY8eOsLa2RlBQEObNm2fwz8372BA9Q3gfG6Ly5LiPTZ+4A5UHVcHOUT6VBz3jOMeGiIiITAaHooiIiCTGp3vLh4UNERGRxFjXyIdDUURERGQy2LEhIiKSmAJs2ciFhQ0REZHEzFjXyIZDUURERGQy2LEhIiKSGFdFyYeFDRERkcRY18iHQ1FERERkMtixISIikpgZWzayYWFDREQkMdY18mFhQ0REJDFOHpYP59gQERGRyWDHhoiISGJs2MiHhQ0REZHEOHlYPhyKIiIiIpPBjg0REZHE2K+RDwsbIiIiiXFVlHw4FEVEREQmgx0bIiIiiZmxYSObKhU2W7durfIJAwMDHzkZIiIiU8ShKPlUqbAZMGBAlU6mUCig0+keJx8iIiKiR1alwqasrEzqPIiIiEwWGzby4RwbIiIiiXEoSj6PVNgUFhZiz549yM3NRUlJid6x8PBwgyRGRERkKjh5WD7VLmyOHDmCvn374s6dOygsLISDgwOuXr0KGxsbODs7s7AhIiIio6n2fWzef/99BAQE4Pr167C2tkZqairOnz8Pb29vzJs3T4ociYiInmoKhcIgG1Wu2oVNRkYGIiMjYW5uDnNzcxQXF8PNzQ1z5szBhx9+KEWORERETzWFgTaqXLULG0tLS7FqdHFxQW5uLgBApVKJfyYiIiIyhmrPsWndujUOHTqE5557Dt26dcPUqVNx9epVrFu3Di1btpQiRyIioqeaGYeRZFPtjk10dDTq1q0LAPj444/h6OiIUaNGIT8/HytWrDB4gkRERE87hcIwG1Wu2h2btm3bin+uU6cOduzYYdCEiIiIiB4Vb9BHREQkMa5okk+1C5vGjRv/61/Q2bNnHyshIiIiU8O6Rj7VLmwiIiL0XpeWluLIkSNITEzEhAkTDJUXERERUbVVu7B57733Kty/ZMkSHDp06LETIiIiMjVcFSWfaq+Kepg+ffpg06ZNhjodERGRyeCqKPkYbPLwxo0b4eDgYKjTERERmQxOHpbPI92g759/QYIgQKPR4MqVK1i6dKlBkyMiIiKqjmoXNv3799crbMzMzFCnTh107doVzz//vEGTe1QFabHGToGIiEhksHkfVKlqFzbTp0+XIA0iIiLTxaEo+VS7iDQ3N0d+fn65/deuXYO5ublBkiIiIiJ6FNXu2AiCUOH+4uJiWFlZPXZCREREpsaMDRvZVLmwWbRoEYB77bTPP/8cNWvWFI/pdDrs3bv3iZljQ0RE9CRhYSOfKhc2CxYsAHCvY7Ns2TK9YScrKys0atQIy5YtM3yGRERERFVU5cImJycHANCtWzds3rwZ9vb2kiVFRERkSjh5WD7Vnjz8888/s6ghIiKqBjOFYbbq+vPPP/Hmm2/C0dERNjY2aNWqFdLT08XjgiBg+vTpUKvVsLa2RteuXXHs2DG9cxQXF2Ps2LFwcnKCra0tAgMDcfHiRb2YgoICBAcHQ6VSQaVSITg4GDdu3NCLyc3NRUBAAGxtbeHk5ITw8HCUlJRU/0NVotqFzeuvv45Zs2aV2z937lz897//NUhSRERE9HgKCgrQsWNHWFpaYufOnTh+/Dj+97//oXbt2mLMnDlzMH/+fMTGxiItLQ2urq7o2bMnbt26JcZEREQgISEB8fHxSElJwe3bt+Hv7w+dTifGBAUFISMjA4mJiUhMTERGRgaCg4PF4zqdDv369UNhYSFSUlIQHx+PTZs2ITIy0uCfWyE8bJnTQ9SpUwfJyclo2bKl3v7MzEz06NEDly9fNmiCj+LuX8bOgIiInhY1DPZwoYebuP2kQc4zp59HlWM/+OAD/Pbbb/j1118rPC4IAtRqNSIiIjBp0iQA97ozLi4umD17NkaOHAmtVos6depg3bp1GDRoEADg0qVLcHNzw44dO9CrVy9kZ2fD09MTqamp8PHxAQCkpqbC19cXJ06cgIeHB3bu3Al/f39cuHABarUaABAfH4+QkBDk5+fDzs7ucb4WPdXu2Ny+fbvCZd2Wlpa4efOmQZIiIiIyJWYKhUG24uJi3Lx5U28rLi6u8Jpbt25F27Zt8d///hfOzs5o3bo1Vq5cKR7PycmBRqOBn5+fuE+pVKJLly7Yt28fACA9PR2lpaV6MWq1Gl5eXmLM/v37oVKpxKIGANq3bw+VSqUX4+XlJRY1ANCrVy8UFxfrDY0ZQrULGy8vL3zzzTfl9sfHx8PT09MgSREREZkSMwNtMTEx4jyW+1tMTEyF1zx79izi4uLg7u6OH3/8Ee+++y7Cw8Px5ZdfAgA0Gg0AwMXFRe99Li4u4jGNRgMrK6tyc2sfjHF2di53fWdnZ72YB69jb28PKysrMcZQqt2AmzJlCl577TWcOXMGr7zyCgBg9+7d2LBhAzZu3GjQ5IiIiOhvUVFRGDdunN4+pVJZYWxZWRnatm2L6OhoAPceYn3s2DHExcVh6NChYtyDK7YEQah0FdeDMRXFP0qMIVS7YxMYGIgtW7bg9OnTCAsLQ2RkJP78808kJyejUaNGBk2OiIjIFCgUhtmUSiXs7Oz0tocVNnXr1i03ktK8eXPk5uYCAFxdXQGgXMckPz9f7K64urqipKQEBQUF/xpT0fzaK1eu6MU8eJ2CggKUlpaW6+Q8rkd64Gi/fv3w22+/obCwEKdPn8arr76KiIgIeHt7GzQ5IiIiU2CoOTbV0bFjR5w8qT9p+dSpU2jYsCEAoHHjxnB1dcWuXbvE4yUlJdizZw86dOgAAPD29oalpaVeTF5eHrKyssQYX19faLVaHDx4UIw5cOAAtFqtXkxWVhby8vLEmKSkJCiVSoPXDo88Fzw5ORmrV6/G5s2b0bBhQ7z22mtYtWqVIXMjIiKiR/T++++jQ4cOiI6OxsCBA3Hw4EGsWLECK1asAHBvaCgiIgLR0dFwd3eHu7s7oqOjYWNjg6CgIACASqXC8OHDERkZCUdHRzg4OGD8+PFo2bIlevToAeBeF6h3794IDQ3F8uXLAQAjRoyAv78/PDzureLy8/ODp6cngoODMXfuXFy/fh3jx49HaGioQVdEAdUsbC5evIi1a9di9erVKCwsxMCBA1FaWopNmzZx4jAREdFDGOPGwy+99BISEhIQFRWFmTNnonHjxli4cCGGDBkixkycOBFFRUUICwtDQUEBfHx8kJSUhFq1aokxCxYsgIWFBQYOHIiioiJ0794da9eu1Xu00vr16xEeHi6ungoMDERsbKx43NzcHNu3b0dYWBg6duwIa2trBAUFYd68eQb/3FW+j03fvn2RkpICf39/DBkyBL1794a5uTksLS3x+++/P1GFDe9jQ0REVSXHfWymJ/1hmPP4uRvkPKasyn+dSUlJCA8Px6hRo+Duzi+WiIiInjxVnjz866+/4tatW2jbti18fHwQGxuLK1euSJkbERGRSTDG5OFnVZULG19fX6xcuRJ5eXkYOXIk4uPjUa9ePZSVlWHXrl16z5UgIiKivxlquTdVrtrLvW1sbPD2228jJSUFmZmZiIyMxKxZs+Ds7IzAwEApciQiIiKqkke6j819Hh4emDNnDi5evIivv/7aUDkRERGZFDOFYTaqXLWf7v004KooIiKqKjlWRUXvPmOQ83zYvalBzmPKZPjrJCIierax2yKfxxqKIiIiInqSsGNDREQkMXZs5MPChoiISGIKrtWWDYeiiIiIyGSwY0NERCQxDkXJh4UNERGRxDgSJR8ORREREZHJYMeGiIhIYnyApXxY2BAREUmMc2zkw6EoIiIiMhns2BAREUmMI1HyYWFDREQkMTOwspELCxsiIiKJsWMjH86xISIiIpPBjg0REZHEuCpKPixsiIiIJMb72MiHQ1FERERkMtixISIikhgbNvJhYUNERCQxDkXJh0NRREREZDLYsSEiIpIYGzbyYWFDREQkMQ6PyIffNREREZkMdmyIiIgkpuBYlGxY2BAREUmMZY18WNgQERFJjMu95cM5NkRERGQy2LEhIiKSGPs18mFhQ0REJDGORMmHQ1FERERkMtixISIikhiXe8uHhQ0REZHEODwiH37XREREZDLYsSEiIpIYh6Lkw8KGiIhIYixr5MOhKCIiIjIZ7NgQERFJjENR8mFhQ0REJDEOj8iHhQ0REZHE2LGRD4tIIiIiMhksbIiIiCSmMND2OGJiYqBQKBARESHuEwQB06dPh1qthrW1Nbp27Ypjx47pva+4uBhjx46Fk5MTbG1tERgYiIsXL+rFFBQUIDg4GCqVCiqVCsHBwbhx44ZeTG5uLgICAmBrawsnJyeEh4ejpKTkMT9VeSxsiIiIJKZQGGZ7VGlpaVixYgVeeOEFvf1z5szB/PnzERsbi7S0NLi6uqJnz564deuWGBMREYGEhATEx8cjJSUFt2/fhr+/P3Q6nRgTFBSEjIwMJCYmIjExERkZGQgODhaP63Q69OvXD4WFhUhJSUF8fDw2bdqEyMjIR/9QD6EQBEEw+FmN7O5fxs6AiIieFjVkmG36fabGIOfp39K12u+5ffs22rRpg6VLl+KTTz5Bq1atsHDhQgiCALVajYiICEyaNAnAve6Mi4sLZs+ejZEjR0Kr1aJOnTpYt24dBg0aBAC4dOkS3NzcsGPHDvTq1QvZ2dnw9PREamoqfHx8AACpqanw9fXFiRMn4OHhgZ07d8Lf3x8XLlyAWq0GAMTHxyMkJAT5+fmws7MzyPcDsGNDREQkOTMoDLIVFxfj5s2beltxcfG/Xnv06NHo168fevToobc/JycHGo0Gfn5+4j6lUokuXbpg3759AID09HSUlpbqxajVanh5eYkx+/fvh0qlEosaAGjfvj1UKpVejJeXl1jUAECvXr1QXFyM9PT0R/xWK/bEFjaXL1/GzJkzjZ0GERHRYzPUUFRMTIw4j+X+FhMT89DrxsfH4/DhwxXGaDT3ukguLi56+11cXMRjGo0GVlZWsLe3/9cYZ2fncud3dnbWi3nwOvb29rCyshJjDOWJLWw0Gg1mzJhh7DSIiIieGFFRUdBqtXpbVFRUhbEXLlzAe++9h6+++go1atR46DkfXIouCEKly9MfjKko/lFiDMFo97E5evTovx4/efKkTJkQERFJS2Ggp0UplUoolcoqxaanpyM/Px/e3t7iPp1Oh7179yI2Nlb8PavRaFC3bl0xJj8/X+yuuLq6oqSkBAUFBXpdm/z8fHTo0EGMuXz5crnrX7lyRe88Bw4c0DteUFCA0tLScp2cx2W0wqZVq1ZQKBSoaO7y/f28oREREZkCY/w66969OzIzM/X2vfXWW3j++ecxadIkNGnSBK6urti1axdat24NACgpKcGePXswe/ZsAIC3tzcsLS2xa9cuDBw4EACQl5eHrKwszJkzBwDg6+sLrVaLgwcPol27dgCAAwcOQKvVisWPr68vPv30U+Tl5YlFVFJSEpRKpV7hZQhGK2wcHR0xe/ZsdO/evcLjx44dQ0BAgMxZERERmYZatWrBy8tLb5+trS0cHR3F/REREYiOjoa7uzvc3d0RHR0NGxsbBAUFAQBUKhWGDx+OyMhIODo6wsHBAePHj0fLli3FycjNmzdH7969ERoaiuXLlwMARowYAX9/f3h4eAAA/Pz84OnpieDgYMydOxfXr1/H+PHjERoaatAVUYARCxtvb29cunQJDRs2rPD4jRs3KuzmEBERPW3MDDQUZWgTJ05EUVERwsLCUFBQAB8fHyQlJaFWrVpizIIFC2BhYYGBAweiqKgI3bt3x9q1a2Fubi7GrF+/HuHh4eLqqcDAQMTGxorHzc3NsX37doSFhaFjx46wtrZGUFAQ5s2bZ/DPZLT72CQkJKCwsBBvvvlmhccLCgqwdetWDBs2rNrn5n1siIioquS4j82Px68Y5Dy9POsY5DymjDfoIyKiZ5ochU1StmEKG7/mLGwq88Qu9yYiIiKqLqPNsSEiInpWGGq5N1WOhQ0REZHEzFjXyIZDUURERGQy2LEhIiKSGIei5GP0jk1iYiJSUlLE10uWLEGrVq0QFBSEgoICI2ZGRERkGIZ6CCZVzuiFzYQJE3Dz5k0AQGZmJiIjI9G3b1+cPXsW48aNM3J2RERE9DQx+lBUTk4OPD09AQCbNm2Cv78/oqOjcfjwYfTt29fI2RERET0+DkXJx+gdGysrK9y5cwcA8NNPP4m3Y3ZwcBA7OURERE8zM4VhNqqc0Ts2nTp1wrhx49CxY0ccPHgQ33zzDQDg1KlTqF+/vpGzIyIioqeJ0Ts2sbGxsLCwwMaNGxEXF4d69eoBAHbu3InevXsbOTuqSPqhNIwNexc9unbCiy08kLz7J73jcUsWo79/b/i0bYVOvi9hxPAQHD36u3j8zz8v4sUWHhVuST/ulPvjEEli1crlCBr4Gnxfao2uL/siYmwYzuWcfWj8zOlT8WILD3z15Vr5kiTZKAz0P6qc0Ts2DRo0wLZt28rtX7BggRGyoaooKroDDw8P9P/Pq4iMGFvueMOGjRA1eSrq13fD3eK7+OrLtRgV+jZ+2LkLDg4OcHWti92/pOi9Z+N332Dt6lXo1KmzXB+DSFKH0g5i0BtD0KJlS+j+0mHxogV4N3Q4Nm/dDhsbG73Y5N0/Ievo76jj7GykbElqXNEkH6MXNocPH4alpSVatmwJAPj++++xZs0aeHp6Yvr06bCysjJyhvSgTi93QaeXuzz0eF//AL3X4ydGIWHTRvxx6iR82vvC3NwcTnX0H+SWvPsn9OrTBza2tpLkTCS3uBWr9F7P/CQG3V72RfbxY/Bu+5K4//Lly4j5dCbiVqzC2FEj5U6TZMK6Rj5GH4oaOXIkTp06BQA4e/YsBg8eDBsbG3z33XeYOHGikbOjx1VaUoJN332DWrVq4TkPjwpjjh/LwskT2fjPq6/LnB2RfG7fugUAsFOpxH1lZWWY/MEEhLw1HM2auRsrNSKTYvSOzalTp9CqVSsAwHfffYfOnTtjw4YN+O233zB48GAsXLjwX99fXFyM4uJivX2CuRJKpVKijKkq9vzyMyaNH4e7d4vgVKcOlq1cDXt7hwpjEzZtRJMmTdGqdRuZsySShyAImDcnBq3beMPd/Tlx/5pVK2FuYYGgN4caMTuSgxnHomRj9I6NIAgoKysDcG+59/1717i5ueHq1auVvj8mJgYqlUpvmzs7RtKcqXIvtfPBt5u24Mv18ejY6WVMiIzAtWvXysXdvXsXO3dsw4DX2K0h0xXzyUz8ceoUZs+dL+47fiwL69d9iY8/jYGCv/RMnsJAG1XO6B2btm3b4pNPPkGPHj2wZ88exMXFAbh34z4XF5dK3x8VFVXuDsWCObs1xmZjY4MGDRuiQcOGeOHFVgjo44ctmzdieKj+HIJdSYkoKrqLgMABxkmUSGIxn36MX35JxuovvoKLq6u4/3D6IVy/fg29e3QT9+l0Ovxv7mysX/cldu5KNka6RE89oxc2CxcuxJAhQ7BlyxZMnjwZzZo1AwBs3LgRHTp0qPT9SmX5Yae7f0mSKj0GQRBQUlJSbv+WzZvQtdsrcHCoeJiK6GklCAJiPv0Yybt3YdXadahf303vuH9gf/j46v8bN2rEcPgH9MeA/7wqZ6okB7ZbZGP0wuaFF15AZmZmuf1z586Fubm5ETKiytwpLERubq74+s+LF3EiO/veUGDt2vh8xTJ07fYKnOrUgfbGDXwTvwGXL2vQs5f+fYlyz59H+qE0LIlbIfdHIJJc9MczsHPHNixcvBS2Nra4euUKAKBmrVqoUaMGate2R+3a9nrvsbSwhJOTExo1bmKMlElCvAeNfIxe2DxMjRo1jJ0CPcSxY1l4562/JzvOm3NvTlNg///go2kzkJNzFlu/T8CNggLUrl0bLbxaYs2X68ut+tiSsAnOLi7w7dhJ1vyJ5PDtN18DAIaHBOvtn/lJDPqzI0MkGYUgCIIxE9DpdFiwYAG+/fZb5ObmlhuuuH79erXPyaEoIiKqqhoy/Cf+wbNag5ynXRNV5UHPOKOvipoxYwbmz5+PgQMHQqvVYty4cXj11VdhZmaG6dOnGzs9IiKix8ZVUfIxesemadOmWLRoEfr164datWohIyND3JeamooNGzZU+5zs2BARUVXJ0bFJM1DH5iV2bCpl9I6NRqMRH6dQs2ZNaLX3/vL9/f2xfft2Y6ZGRERkGGzZyMbohU39+vWRl5cHAGjWrBmSkpIAAGlpabx7MBERmQQ+3Vs+Ri9s/vOf/2D37t0AgPfeew9TpkyBu7s7hg4dirffftvI2RERET0+hcIwG1XO6HNsHpSamop9+/ahWbNmCAwMfKRzcI4NERFVlRxzbNLP3TTIebwb2RnkPKbsiStsDIGFDRERVZUchc1hAxU2bVjYVMooN+jbunVrlWMftWtDRET0xOAwkmyM0rExM6va1B6FQgGdTlft87NjQ0REVSVLx+a8gTo2DdmxqYxROjZlZWXGuCwREZFRcEWTfJ7YZ0URERGZCq5oko/RlnsnJyfD09MTN2+Wb89ptVq0aNECe/fuNUJmRERE9LQyWmGzcOFChIaGws6u/HihSqXCyJEjsWDBAiNkRkREZFi88bB8jFbY/P777+jdu/dDj/v5+SE9PV3GjIiIiCTCykY2RitsLl++DEtLy4cet7CwwJUrV2TMiIiIiJ52Rits6tWrh8zMzIceP3r0KOrWrStjRkRERNLgs6LkY7TCpm/fvpg6dSru3r1b7lhRURGmTZsGf39/I2RGRERkWHxWlHyM9kiFy5cvo02bNjA3N8eYMWPg4eEBhUKB7OxsLFmyBDqdDocPH4aLi0u1z80b9BERUVXJcYO+rIu3DXIer/o1DXIeU2bUZ0WdP38eo0aNwo8//oj7aSgUCvTq1QtLly5Fo0aNHum8LGyIiKiqWNiYlifiIZgFBQU4ffo0BEGAu7s77O3tH+t8LGyIiKiqZCls/jRQYVOPhU1lnojCxtBY2BARUVXJUdgc+7PQIOdpUc/WIOcxZUabPExERERkaHxWFBERkcS4okk+LGyIiIgkxrpGPhyKIiIiIpPBwoaIiEhqRnhWVExMDF566SXUqlULzs7OGDBgAE6ePKkXIwgCpk+fDrVaDWtra3Tt2hXHjh3TiykuLsbYsWPh5OQEW1tbBAYG4uLFi3oxBQUFCA4OhkqlgkqlQnBwMG7cuKEXk5ubi4CAANja2sLJyQnh4eEoKSmp3oeqAhY2REREEjPGIxX27NmD0aNHIzU1Fbt27cJff/0FPz8/FBb+vUJrzpw5mD9/PmJjY5GWlgZXV1f07NkTt27dEmMiIiKQkJCA+Ph4pKSk4Pbt2/D394dOpxNjgoKCkJGRgcTERCQmJiIjIwPBwcHicZ1Oh379+qGwsBApKSmIj4/Hpk2bEBkZ+RjfasW43JuIiJ5pciz3PpF3xyDneb6uzSO/98qVK3B2dsaePXvQuXNnCIIAtVqNiIgITJo0CcC97oyLiwtmz56NkSNHQqvVok6dOli3bh0GDRoEALh06RLc3NywY8cO9OrVC9nZ2fD09ERqaip8fHwAAKmpqfD19cWJEyfg4eGBnTt3wt/fHxcuXIBarQYAxMfHIyQkBPn5+bCzs3vMb+Zv7NgQERFJzFDPiiouLsbNmzf1tuLi4irloNVqAQAODg4AgJycHGg0Gvj5+YkxSqUSXbp0wb59+wAA6enpKC0t1YtRq9Xw8vISY/bv3w+VSiUWNQDQvn17qFQqvRgvLy+xqAGAXr16obi4GOnp6Y/ylT4UCxsiIiKJGWqKTUxMjDiP5f4WExNT6fUFQcC4cePQqVMneHl5AQA0Gg0AlHsmo4uLi3hMo9HAysqq3BMBHoxxdnYud01nZ2e9mAevY29vDysrKzHGULjcm4iISGoGWu8dFRWFcePG6e1TKpWVvm/MmDE4evQoUlJSyqf2wE12BEEot+9BD8ZUFP8oMYbAjg0REdFTQqlUws7OTm+rrLAZO3Ystm7dip9//hn169cX97u6ugJAuY5Jfn6+2F1xdXVFSUkJCgoK/jXm8uXL5a575coVvZgHr1NQUIDS0tJynZzHxcKGiIhIYsZYFSUIAsaMGYPNmzcjOTkZjRs31jveuHFjuLq6YteuXeK+kpIS7NmzBx06dAAAeHt7w9LSUi8mLy8PWVlZYoyvry+0Wi0OHjwoxhw4cABarVYvJisrC3l5eWJMUlISlEolvL29q/W5KsNVUURE9EyTY1XU6fwig5ynmbN1lWPDwsKwYcMGfP/99/Dw8BD3q1QqWFvfO8/s2bMRExODNWvWwN3dHdHR0fjll19w8uRJ1KpVCwAwatQobNu2DWvXroWDgwPGjx+Pa9euIT09Hebm5gCAPn364NKlS1i+fDkAYMSIEWjYsCF++OEHAPeWe7dq1QouLi6YO3curl+/jpCQEAwYMACLFy82yHdzHwsbIiJ6pplqYfOwuStr1qxBSEgIgHtdnRkzZmD58uUoKCiAj48PlixZIk4wBoC7d+9iwoQJ2LBhA4qKitC9e3csXboUbm5uYsz169cRHh6OrVu3AgACAwMRGxuL2rVrizG5ubkICwtDcnIyrK2tERQUhHnz5lVpjlB1sLAhIqJnmhyFzRkDFTZNq1HYPKu4KoqIiEhqfAqmbDh5mIiIiEwGOzZEREQSq+6KJnp0LGyIiIgkZuB70NG/4FAUERERmQx2bIiIiCTGho18WNgQERFJjZWNbFjYEBERSYyTh+XDOTZERERkMtixISIikhhXRcmHhQ0REZHEWNfIh0NRREREZDLYsSEiIpIYh6Lkw8KGiIhIcqxs5MKhKCIiIjIZ7NgQERFJjENR8mFhQ0REJDHWNfLhUBQRERGZDHZsiIiIJMahKPmwsCEiIpIYnxUlHxY2REREUmNdIxvOsSEiIiKTwY4NERGRxNiwkQ8LGyIiIolx8rB8OBRFREREJoMdGyIiIolxVZR8WNgQERFJjXWNbDgURURERCaDHRsiIiKJsWEjHxY2REREEuOqKPlwKIqIiIhMBjs2REREEuOqKPmwsCEiIpIYh6Lkw6EoIiIiMhksbIiIiMhkcCiKiIhIYhyKkg8LGyIiIolx8rB8OBRFREREJoMdGyIiIolxKEo+LGyIiIgkxrpGPhyKIiIiIpPBjg0REZHU2LKRDQsbIiIiiXFVlHw4FEVEREQmgx0bIiIiiXFVlHxY2BAREUmMdY18WNgQERFJjZWNbDjHhoiIiEwGOzZEREQS46oo+bCwISIikhgnD8uHQ1FERERkMhSCIAjGToJMU3FxMWJiYhAVFQWlUmnsdIieGPzZIJIOCxuSzM2bN6FSqaDVamFnZ2fsdIieGPzZIJIOh6KIiIjIZLCwISIiIpPBwoaIiIhMBgsbkoxSqcS0adM4OZLoAfzZIJIOJw8TERGRyWDHhoiIiEwGCxsiIiIyGSxsiIiIyGSwsKEqUygU2LJli7HTIHqi8OeC6MnCwoYAABqNBmPHjkWTJk2gVCrh5uaGgIAA7N6929ipAQAEQcD06dOhVqthbW2Nrl274tixY8ZOi0zck/5zsXnzZvTq1QtOTk5QKBTIyMgwdkpERsfChnDu3Dl4e3sjOTkZc+bMQWZmJhITE9GtWzeMHj3a2OkBAObMmYP58+cjNjYWaWlpcHV1Rc+ePXHr1i1jp0Ym6mn4uSgsLETHjh0xa9YsY6dC9OQQ6JnXp08foV69esLt27fLHSsoKBD/DEBISEgQX0+cOFFwd3cXrK2thcaNGwsfffSRUFJSIh7PyMgQunbtKtSsWVOoVauW0KZNGyEtLU0QBEE4d+6c4O/vL9SuXVuwsbERPD09he3bt1eYX1lZmeDq6irMmjVL3Hf37l1BpVIJy5Yte8xPT1SxJ/3n4p9ycnIEAMKRI0ce+fMSmQoLI9dVZGTXr19HYmIiPv30U9ja2pY7Xrt27Ye+t1atWli7di3UajUyMzMRGhqKWrVqYeLEiQCAIUOGoHXr1oiLi4O5uTkyMjJgaWkJABg9ejRKSkqwd+9e2Nra4vjx46hZs2aF18nJyYFGo4Gfn5+4T6lUokuXLti3bx9Gjhz5GN8AUXlPw88FEVWMhc0z7vTp0xAEAc8//3y13/vRRx+Jf27UqBEiIyPxzTffiP+A5+bmYsKECeK53d3dxfjc3Fy89tpraNmyJQCgSZMmD72ORqMBALi4uOjtd3Fxwfnz56udN1FlnoafCyKqGOfYPOOE/7/xtEKhqPZ7N27ciE6dOsHV1RU1a9bElClTkJubKx4fN24c3nnnHfTo0QOzZs3CmTNnxGPh4eH45JNP0LFjR0ybNg1Hjx6t9HoP5igIwiPlTVSZp+nngoj0sbB5xrm7u0OhUCA7O7ta70tNTcXgwYPRp08fbNu2DUeOHMHkyZNRUlIixkyfPh3Hjh1Dv379kJycDE9PTyQkJAAA3nnnHZw9exbBwcHIzMxE27ZtsXjx4gqv5erqCuDvzs19+fn55bo4RIbwNPxcENFDGHWGDz0RevfuXe1JkvPmzROaNGmiFzt8+HBBpVI99DqDBw8WAgICKjz2wQcfCC1btqzw2P3Jw7Nnzxb3FRcXc/IwSepJ/7n4J04eJvobOzaEpUuXQqfToV27dti0aRP++OMPZGdnY9GiRfD19a3wPc2aNUNubi7i4+Nx5swZLFq0SPyvTgAoKirCmDFj8Msvv+D8+fP47bffkJaWhubNmwMAIiIi8OOPPyInJweHDx9GcnKyeOxBCoUCERERiI6ORkJCArKyshASEgIbGxsEBQUZ/gshwpP/cwHcm+SckZGB48ePAwBOnjyJjIyMct1NomeKsSsrejJcunRJGD16tNCwYUPByspKqFevnhAYGCj8/PPPYgweWNY6YcIEwdHRUahZs6YwaNAgYcGCBeJ/mRYXFwuDBw8W3NzcBCsrK0GtVgtjxowRioqKBEEQhDFjxghNmzYVlEqlUKdOHSE4OFi4evXqQ/MrKysTpk2bJri6ugpKpVLo3LmzkJmZKcVXQSR60n8u1qxZIwAot02bNk2Cb4Po6aAQhP+fJUdERET0lONQFBEREZkMFjZERERkMljYEBERkclgYUNEREQmg4UNERERmQwWNkRERGQyWNgQERGRyWBhQ2SCpk+fjlatWomvQ0JCMGDAANnzOHfuHBQKBTIyMmS/NhE9m1jYEMkoJCQECoUCCoUClpaWaNKkCcaPH4/CwkJJr/vZZ59h7dq1VYplMUJETzMLYydA9Kzp3bs31qxZg9LSUvz666945513UFhYiLi4OL240tJSWFpaGuSaKpXKIOchInrSsWNDJDOlUglXV1e4ubkhKCgIQ4YMwZYtW8Tho9WrV6NJkyZQKpUQBAFarRYjRoyAs7Mz7Ozs8Morr+D333/XO+esWbPg4uKCWrVqYfjw4bh7967e8QeHosrKyjB79mw0a9YMSqUSDRo0wKeffgoAaNy4MQCgdevWUCgU6Nq1q/i+NWvWoHnz5qhRowaef/55LF26VO86Bw8eROvWrVGjRg20bdsWR44cMeA3R0RUOXZsiIzM2toapaWlAIDTp0/j22+/xaZNm2Bubg4A6NevHxwcHLBjxw6oVCosX74c3bt3x6lTp+Dg4IBvv/0W06ZNw5IlS/Dyyy9j3bp1WLRoEZo0afLQa0ZFRWHlypVYsGABOnXqhLy8PJw4cQLAveKkXbt2+Omnn9CiRQtYWVkBAFauXIlp06YhNjYWrVu3xpEjRxAaGgpbW1sMGzYMhYWF8Pf3xyuvvIKvvvoKOTk5eO+99yT+9oiIHmDkh3ASPVOGDRsm9O/fX3x94MABwdHRURg4cKAwbdo0wdLSUsjPzxeP7969W7CzsxPu3r2rd56mTZsKy5cvFwRBEHx9fYV3331X77iPj4/w4osvVnjdmzdvCkqlUli5cmWFOebk5AgAhCNHjujtd3NzEzZs2KC37+OPPxZ8fX0FQRCE5cuXCw4ODkJhYaF4PC4ursJzERFJhUNRRDLbtm0batasiRo1asDX1xedO3fG4sWLAQANGzZEnTp1xNj09HTcvn0bjo6OqFmzprjl5OTgzJkzAIDs7Gz4+vrqXePB1/+UnZ2N4uJidO/evco5X7lyBRcuXMDw4cP18vjkk0/08njxxRdhY2NTpTyIiKTAoSgimXXr1g1xcXGwtLSEWq3WmyBsa2urF1tWVoa6devil19+KXee2rVrP9L1ra2tq/2esrIyAPeGo3x8fPSO3R8yEwThkfIhIjIkFjZEMrO1tUWzZs2qFNumTRtoNBpYWFigUaNGFcY0b94cqampGDp0qLgvNTX1oed0d3eHtbU1du/ejXfeeafc8ftzanQ6nbjPxcUF9erVw9mzZzFkyJAKz+vp6Yl169ahqKhILJ7+LQ8iIilwKIroCdajRw/4+vpiwIAB+PHHH3Hu3Dns27cPH330EQ4dOgQAeO+997B69WqsXr0ap06dwrRp03Ds2LGHnrNGjRqYNGkSJk6ciC+//BJnzpxBamoqVq1aBQBwdnaGtbU1EhMTcfnyZWi1WgD3bvoXExODzz77DKdOnUJmZibWrFmD+fPnAwCCgoJgZmaG4cOH4/jx49ixYwfmzZsn8TdERKSPhQ3RE0yhUGDHjh3o3Lkz3n77bTz33HMYPHgwzp07BxcXFwDAoEGDMHXqVEyaNAne3t44f/48Ro0a9a/nnTJlCiIjIzF16lQ0b94cgwYNQn5+PgDAwsICixYtwvLly6FWq9G/f38AwDvvvIPPP/8ca9euRcuWLdGlSxesXbtWXB5es2ZN/PDDDzh+/Dhat26NyZMnY/bs2RJ+O0RE5SkEDowTERGRiWDHhoiIiEwGCxsiIiIyGSxsiIiIyGSwsCEiIiKTwcKGiIiITAYLGyIiIjIZLGyIiIjIZLCwISIiIpPBwoaIiIhMBgsbIiIiMhksbIiIiMhksLAhIiIik/F/5TIxve7GojgAAAAASUVORK5CYII=",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=['Class 0', 'Class 1'], yticklabels=['Class 0', 'Class 1'])\n",
"plt.xlabel('Predicted')\n",
"plt.ylabel('Actual')\n",
"plt.title('Confusion Matrix')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "fe6e14d2-001d-4585-9344-f240b84ce4af",
"metadata": {},
"source": [
"## Ajout TP : test d'une nouvelle pipeline"
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "9d19f8c0-ed31-46cd-8879-47810fa099d6",
"metadata": {},
"outputs": [],
"source": [
"# definition des variables utilisées\n",
"\n",
"numeric_features = ['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'nb_tickets_internet', 'fidelity', 'nb_campaigns', 'nb_campaigns_opened']\n",
"# categorical_features = [\"opt_in\"]\n",
"encoded_features = [\"opt_in\", \"vente_internet_max\"]\n",
"features = numeric_features + encoded_features\n",
"X_train = dataset_train[features]\n",
"y_train = dataset_train['y_has_purchased']\n",
"X_test = dataset_test[features]\n",
"y_test = dataset_test['y_has_purchased']"
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "412ddfad-3d20-4fa0-afaa-79ec87b3122d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 128198.000000\n",
"mean 2.924687\n",
"std 923.990506\n",
"min 0.000000\n",
"25% 0.000000\n",
"50% 0.000000\n",
"75% 1.000000\n",
"max 330831.000000\n",
"Name: fidelity, dtype: float64"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"### variable fidelity\n",
"\n",
"X_train[\"fidelity\"].describe() # sûrement un problème d'outlier pour fidelity\n",
"# X_train[\"total_amount\"].describe()"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "97e1cd25-0961-45dd-af7f-78ab1d8088ee",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" nb_tickets | \n",
" nb_purchases | \n",
" total_amount | \n",
" nb_suppliers | \n",
" nb_tickets_internet | \n",
" fidelity | \n",
" nb_campaigns | \n",
" nb_campaigns_opened | \n",
" opt_in | \n",
" vente_internet_max | \n",
"
\n",
" \n",
" \n",
" \n",
" 2 | \n",
" 122983.0 | \n",
" 65082.0 | \n",
" 878762.5 | \n",
" 5.0 | \n",
" 9.0 | \n",
" 330831 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 3 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 173 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 15 | \n",
" 2773.0 | \n",
" 81.0 | \n",
" 32338.0 | \n",
" 2.0 | \n",
" 2.0 | \n",
" 94 | \n",
" 126.0 | \n",
" 50.0 | \n",
" 1 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 24 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 224 | \n",
" 21.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 28 | \n",
" 282.0 | \n",
" 15.0 | \n",
" 0.0 | \n",
" 2.0 | \n",
" 53.0 | \n",
" 34 | \n",
" 32.0 | \n",
" 13.0 | \n",
" 1 | \n",
" 1.0 | \n",
"
\n",
" \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
"
\n",
" \n",
" 144905 | \n",
" 14.0 | \n",
" 8.0 | \n",
" 136.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 9 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 144906 | \n",
" 190.0 | \n",
" 120.0 | \n",
" 1757.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 120 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 144950 | \n",
" 761.0 | \n",
" 418.0 | \n",
" 5406.5 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 907 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 144959 | \n",
" 11.0 | \n",
" 8.0 | \n",
" 103.0 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 8 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 150686 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 6 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
287 rows × 10 columns
\n",
"
"
],
"text/plain": [
" nb_tickets nb_purchases total_amount nb_suppliers \\\n",
"2 122983.0 65082.0 878762.5 5.0 \n",
"3 0.0 0.0 0.0 0.0 \n",
"15 2773.0 81.0 32338.0 2.0 \n",
"24 0.0 0.0 0.0 0.0 \n",
"28 282.0 15.0 0.0 2.0 \n",
"... ... ... ... ... \n",
"144905 14.0 8.0 136.0 2.0 \n",
"144906 190.0 120.0 1757.0 2.0 \n",
"144950 761.0 418.0 5406.5 2.0 \n",
"144959 11.0 8.0 103.0 1.0 \n",
"150686 0.0 0.0 0.0 0.0 \n",
"\n",
" nb_tickets_internet fidelity nb_campaigns nb_campaigns_opened \\\n",
"2 9.0 330831 0.0 0.0 \n",
"3 0.0 173 2.0 0.0 \n",
"15 2.0 94 126.0 50.0 \n",
"24 0.0 224 21.0 0.0 \n",
"28 53.0 34 32.0 13.0 \n",
"... ... ... ... ... \n",
"144905 0.0 9 1.0 0.0 \n",
"144906 0.0 120 1.0 0.0 \n",
"144950 0.0 907 1.0 0.0 \n",
"144959 0.0 8 1.0 0.0 \n",
"150686 0.0 6 0.0 0.0 \n",
"\n",
" opt_in vente_internet_max \n",
"2 0 1.0 \n",
"3 1 0.0 \n",
"15 1 1.0 \n",
"24 1 0.0 \n",
"28 1 1.0 \n",
"... ... ... \n",
"144905 1 0.0 \n",
"144906 1 0.0 \n",
"144950 1 0.0 \n",
"144959 1 0.0 \n",
"150686 1 0.0 \n",
"\n",
"[287 rows x 10 columns]"
]
},
"execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_train[X_train[\"fidelity\"]>5]"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "fc17957e-b684-41cd-880f-049a4ffcc7dc",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" customer_id | \n",
" event_type_id | \n",
" nb_tickets | \n",
" nb_purchases | \n",
" total_amount | \n",
" nb_suppliers | \n",
" vente_internet_max | \n",
" purchase_date_min | \n",
" purchase_date_max | \n",
" time_between_purchase | \n",
" ... | \n",
" tenant_id | \n",
" gender_label | \n",
" gender_female | \n",
" gender_male | \n",
" gender_other | \n",
" country_fr | \n",
" nb_campaigns | \n",
" nb_campaigns_opened | \n",
" time_to_open | \n",
" y_has_purchased | \n",
"
\n",
" \n",
" \n",
" \n",
" 2 | \n",
" 1 | \n",
" 5.0 | \n",
" 122983.0 | \n",
" 65082.0 | \n",
" 878762.5 | \n",
" 5.0 | \n",
" 1.0 | \n",
" 267.437789 | \n",
" 0.23066 | \n",
" 267.20713 | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 1.0 | \n",
"
\n",
" \n",
" 3 | \n",
" 2 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" male | \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 1.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 6 | \n",
" 5 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" male | \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 1.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 7 | \n",
" 6 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" male | \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 1.0 | \n",
" 12.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 8 | \n",
" 7 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" female | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" 1.0 | \n",
" 24.0 | \n",
" 10.0 | \n",
" 5 days 11:58:52 | \n",
" 0.0 | \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",
" 152645 | \n",
" 1256102 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" female | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152646 | \n",
" 1256103 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152647 | \n",
" 1256104 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152648 | \n",
" 1256105 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152649 | \n",
" 1256106 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
128198 rows × 42 columns
\n",
"
"
],
"text/plain": [
" customer_id event_type_id nb_tickets nb_purchases total_amount \\\n",
"2 1 5.0 122983.0 65082.0 878762.5 \n",
"3 2 NaN 0.0 0.0 0.0 \n",
"6 5 NaN 0.0 0.0 0.0 \n",
"7 6 NaN 0.0 0.0 0.0 \n",
"8 7 NaN 0.0 0.0 0.0 \n",
"... ... ... ... ... ... \n",
"152645 1256102 NaN 0.0 0.0 0.0 \n",
"152646 1256103 NaN 0.0 0.0 0.0 \n",
"152647 1256104 NaN 0.0 0.0 0.0 \n",
"152648 1256105 NaN 0.0 0.0 0.0 \n",
"152649 1256106 NaN 0.0 0.0 0.0 \n",
"\n",
" nb_suppliers vente_internet_max purchase_date_min \\\n",
"2 5.0 1.0 267.437789 \n",
"3 0.0 0.0 NaN \n",
"6 0.0 0.0 NaN \n",
"7 0.0 0.0 NaN \n",
"8 0.0 0.0 NaN \n",
"... ... ... ... \n",
"152645 0.0 0.0 NaN \n",
"152646 0.0 0.0 NaN \n",
"152647 0.0 0.0 NaN \n",
"152648 0.0 0.0 NaN \n",
"152649 0.0 0.0 NaN \n",
"\n",
" purchase_date_max time_between_purchase ... tenant_id gender_label \\\n",
"2 0.23066 267.20713 ... 1311 other \n",
"3 NaN NaN ... 1311 male \n",
"6 NaN NaN ... 1311 male \n",
"7 NaN NaN ... 1311 male \n",
"8 NaN NaN ... 1311 female \n",
"... ... ... ... ... ... \n",
"152645 NaN NaN ... 1311 female \n",
"152646 NaN NaN ... 1311 other \n",
"152647 NaN NaN ... 1311 other \n",
"152648 NaN NaN ... 1311 other \n",
"152649 NaN NaN ... 1311 other \n",
"\n",
" gender_female gender_male gender_other country_fr nb_campaigns \\\n",
"2 0 0 1 1.0 0.0 \n",
"3 0 1 0 1.0 2.0 \n",
"6 0 1 0 1.0 2.0 \n",
"7 0 1 0 1.0 12.0 \n",
"8 1 0 0 1.0 24.0 \n",
"... ... ... ... ... ... \n",
"152645 1 0 0 1.0 0.0 \n",
"152646 0 0 1 NaN 0.0 \n",
"152647 0 0 1 NaN 0.0 \n",
"152648 0 0 1 NaN 0.0 \n",
"152649 0 0 1 NaN 0.0 \n",
"\n",
" nb_campaigns_opened time_to_open y_has_purchased \n",
"2 0.0 NaN 1.0 \n",
"3 0.0 NaN 0.0 \n",
"6 0.0 NaN 0.0 \n",
"7 0.0 NaN 0.0 \n",
"8 10.0 5 days 11:58:52 0.0 \n",
"... ... ... ... \n",
"152645 0.0 NaN 0.0 \n",
"152646 0.0 NaN 0.0 \n",
"152647 0.0 NaN 0.0 \n",
"152648 0.0 NaN 0.0 \n",
"152649 0.0 NaN 0.0 \n",
"\n",
"[128198 rows x 42 columns]"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# on transforme opt_in en indicatrice\n",
"\n",
"dataset_train[\"opt_in\"] = dataset_train[\"opt_in\"].astype(int)\n",
"dataset_train"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "8ad69b5d-e2e2-4d70-b8f0-ea0d37f7fe0c",
"metadata": {},
"outputs": [],
"source": [
"# definition des variables utilisées\n",
"\n",
"numeric_features = ['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'nb_tickets_internet', 'fidelity', 'nb_campaigns', 'nb_campaigns_opened']\n",
"# categorical_features = [\"opt_in\"]\n",
"encoded_features = [\"opt_in\", \"vente_internet_max\"]\n",
"features = numeric_features + encoded_features\n",
"X_train = dataset_train[features]\n",
"y_train = dataset_train['y_has_purchased']\n",
"X_test = dataset_test[features]\n",
"y_test = dataset_test['y_has_purchased']"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "f4772d69-4f92-434a-a617-b7df4dcd106e",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" nb_tickets | \n",
" nb_purchases | \n",
" total_amount | \n",
" nb_suppliers | \n",
" nb_tickets_internet | \n",
" fidelity | \n",
" nb_campaigns | \n",
" nb_campaigns_opened | \n",
" opt_in | \n",
" vente_internet_max | \n",
"
\n",
" \n",
" \n",
" \n",
" 2 | \n",
" 122983.0 | \n",
" 65082.0 | \n",
" 878762.5 | \n",
" 5.0 | \n",
" 9.0 | \n",
" 330831 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 3 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 173 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 6 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 7 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 12.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 8 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 24.0 | \n",
" 10.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
"
\n",
" \n",
" 152645 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152646 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152647 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152648 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152649 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
128198 rows × 10 columns
\n",
"
"
],
"text/plain": [
" nb_tickets nb_purchases total_amount nb_suppliers \\\n",
"2 122983.0 65082.0 878762.5 5.0 \n",
"3 0.0 0.0 0.0 0.0 \n",
"6 0.0 0.0 0.0 0.0 \n",
"7 0.0 0.0 0.0 0.0 \n",
"8 0.0 0.0 0.0 0.0 \n",
"... ... ... ... ... \n",
"152645 0.0 0.0 0.0 0.0 \n",
"152646 0.0 0.0 0.0 0.0 \n",
"152647 0.0 0.0 0.0 0.0 \n",
"152648 0.0 0.0 0.0 0.0 \n",
"152649 0.0 0.0 0.0 0.0 \n",
"\n",
" nb_tickets_internet fidelity nb_campaigns nb_campaigns_opened \\\n",
"2 9.0 330831 0.0 0.0 \n",
"3 0.0 173 2.0 0.0 \n",
"6 0.0 1 2.0 0.0 \n",
"7 0.0 1 12.0 0.0 \n",
"8 0.0 1 24.0 10.0 \n",
"... ... ... ... ... \n",
"152645 0.0 0 0.0 0.0 \n",
"152646 0.0 0 0.0 0.0 \n",
"152647 0.0 0 0.0 0.0 \n",
"152648 0.0 0 0.0 0.0 \n",
"152649 0.0 0 0.0 0.0 \n",
"\n",
" opt_in vente_internet_max \n",
"2 0 1.0 \n",
"3 1 0.0 \n",
"6 1 0.0 \n",
"7 1 0.0 \n",
"8 1 0.0 \n",
"... ... ... \n",
"152645 0 0.0 \n",
"152646 0 0.0 \n",
"152647 0 0.0 \n",
"152648 0 0.0 \n",
"152649 0 0.0 \n",
"\n",
"[128198 rows x 10 columns]"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_train[\"vente_internet_max\"].unique() # indicatrice ?\n",
"X_train"
]
},
{
"cell_type": "markdown",
"id": "3ed647a6-db9a-4737-b819-57cb81691ea2",
"metadata": {},
"source": [
"### Autre ajout : travail de preprocessing des données - étude des outliers"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "3771eeb1-5221-44e5-a5cd-15475fbe4858",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"count 128198.000000\n",
"mean 0.582536\n",
"std 181.774597\n",
"min 0.000000\n",
"25% 0.000000\n",
"50% 0.000000\n",
"75% 0.000000\n",
"max 65082.000000\n",
"Name: nb_purchases, dtype: float64"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 1. number of purchases\n",
"\n",
"X_train[\"nb_purchases\"].describe()"
]
},
{
"cell_type": "code",
"execution_count": 84,
"id": "63c44b80-88cd-4339-91b9-3764e2690316",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" nb_tickets | \n",
" nb_purchases | \n",
" total_amount | \n",
" nb_suppliers | \n",
" nb_tickets_internet | \n",
" fidelity | \n",
" nb_campaigns | \n",
" nb_campaigns_opened | \n",
" opt_in | \n",
" vente_internet_max | \n",
"
\n",
" \n",
" \n",
" \n",
" 2 | \n",
" 122983.0 | \n",
" 65082.0 | \n",
" 878762.5 | \n",
" 5.0 | \n",
" 9.0 | \n",
" 330831 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 15 | \n",
" 2773.0 | \n",
" 81.0 | \n",
" 32338.0 | \n",
" 2.0 | \n",
" 2.0 | \n",
" 94 | \n",
" 126.0 | \n",
" 50.0 | \n",
" 1 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 28 | \n",
" 282.0 | \n",
" 15.0 | \n",
" 0.0 | \n",
" 2.0 | \n",
" 53.0 | \n",
" 34 | \n",
" 32.0 | \n",
" 13.0 | \n",
" 1 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 29 | \n",
" 40.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 4 | \n",
" 24.0 | \n",
" 17.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 31 | \n",
" 52.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 5 | \n",
" 22.0 | \n",
" 6.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
"
\n",
" \n",
" 147155 | \n",
" 4.0 | \n",
" 2.0 | \n",
" 44.0 | \n",
" 1.0 | \n",
" 4.0 | \n",
" 2 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 147242 | \n",
" 3.0 | \n",
" 2.0 | \n",
" 40.0 | \n",
" 1.0 | \n",
" 3.0 | \n",
" 2 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 147414 | \n",
" 12.0 | \n",
" 2.0 | \n",
" 132.0 | \n",
" 1.0 | \n",
" 12.0 | \n",
" 2 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 147636 | \n",
" 15.0 | \n",
" 2.0 | \n",
" 165.0 | \n",
" 1.0 | \n",
" 15.0 | \n",
" 2 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 147950 | \n",
" 2.0 | \n",
" 2.0 | \n",
" 29.0 | \n",
" 1.0 | \n",
" 2.0 | \n",
" 2 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0 | \n",
" 1.0 | \n",
"
\n",
" \n",
"
\n",
"
747 rows × 10 columns
\n",
"
"
],
"text/plain": [
" nb_tickets nb_purchases total_amount nb_suppliers \\\n",
"2 122983.0 65082.0 878762.5 5.0 \n",
"15 2773.0 81.0 32338.0 2.0 \n",
"28 282.0 15.0 0.0 2.0 \n",
"29 40.0 2.0 0.0 1.0 \n",
"31 52.0 2.0 0.0 1.0 \n",
"... ... ... ... ... \n",
"147155 4.0 2.0 44.0 1.0 \n",
"147242 3.0 2.0 40.0 1.0 \n",
"147414 12.0 2.0 132.0 1.0 \n",
"147636 15.0 2.0 165.0 1.0 \n",
"147950 2.0 2.0 29.0 1.0 \n",
"\n",
" nb_tickets_internet fidelity nb_campaigns nb_campaigns_opened \\\n",
"2 9.0 330831 0.0 0.0 \n",
"15 2.0 94 126.0 50.0 \n",
"28 53.0 34 32.0 13.0 \n",
"29 0.0 4 24.0 17.0 \n",
"31 0.0 5 22.0 6.0 \n",
"... ... ... ... ... \n",
"147155 4.0 2 0.0 0.0 \n",
"147242 3.0 2 0.0 0.0 \n",
"147414 12.0 2 0.0 0.0 \n",
"147636 15.0 2 0.0 0.0 \n",
"147950 2.0 2 0.0 0.0 \n",
"\n",
" opt_in vente_internet_max \n",
"2 0 1.0 \n",
"15 1 1.0 \n",
"28 1 1.0 \n",
"29 1 0.0 \n",
"31 1 0.0 \n",
"... ... ... \n",
"147155 0 1.0 \n",
"147242 0 1.0 \n",
"147414 0 1.0 \n",
"147636 0 1.0 \n",
"147950 0 1.0 \n",
"\n",
"[747 rows x 10 columns]"
]
},
"execution_count": 84,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_train[X_train[\"nb_purchases\"]>1]"
]
},
{
"cell_type": "code",
"execution_count": 65,
"id": "032fbc5a-9044-41bd-b992-78077a6c8432",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.quantile(X_train[\"nb_purchases\"], 0.99)"
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "cad9f7cb-8b71-49a6-874b-e15cb9d7a204",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"count 128198.000000\n",
"mean 1.946941\n",
"std 343.940117\n",
"min 0.000000\n",
"25% 0.000000\n",
"50% 0.000000\n",
"75% 0.000000\n",
"max 122983.000000\n",
"Name: nb_tickets, dtype: float64\n"
]
},
{
"data": {
"text/plain": [
"23.0"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"### 2. nb tickets\n",
"\n",
"print(X_train[\"nb_tickets\"].describe())\n",
"np.quantile(X_train[\"nb_tickets\"], 0.99)"
]
},
{
"cell_type": "code",
"execution_count": 73,
"id": "6bb0c86d-eb61-473d-a29b-c59e7e5af489",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"count 128198.000000\n",
"mean 10.496193\n",
"std 2457.094272\n",
"min 0.000000\n",
"25% 0.000000\n",
"50% 0.000000\n",
"75% 0.000000\n",
"max 878762.500000\n",
"Name: total_amount, dtype: float64\n"
]
},
{
"data": {
"text/plain": [
"44.0"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 3. total amount\n",
"\n",
"print(X_train[\"total_amount\"].describe())\n",
"np.quantile(X_train[\"total_amount\"], 0.99)"
]
},
{
"cell_type": "code",
"execution_count": 76,
"id": "ab6fded3-d8a5-4bb4-8f2d-472ea0e5e755",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"count 128198.000000\n",
"mean 2.924687\n",
"std 923.990506\n",
"min 0.000000\n",
"25% 0.000000\n",
"50% 0.000000\n",
"75% 1.000000\n",
"max 330831.000000\n",
"Name: fidelity, dtype: float64\n"
]
},
{
"data": {
"text/plain": [
"2.0"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 4. fidelity\n",
"\n",
"print(X_train[\"fidelity\"].describe())\n",
"np.quantile(X_train[\"fidelity\"], 0.99)"
]
},
{
"cell_type": "code",
"execution_count": 79,
"id": "c1f0ac75-71a4-43fb-844b-e006acf5927b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"count 128198.000000\n",
"mean 24.276463\n",
"std 37.899868\n",
"min 0.000000\n",
"25% 1.000000\n",
"50% 4.000000\n",
"75% 28.000000\n",
"max 299.000000\n",
"Name: nb_campaigns, dtype: float64\n"
]
},
{
"data": {
"text/plain": [
"133.0"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 5. nb campaigns - semble pas aberrant meme si forte variance\n",
"\n",
"print(X_train[\"nb_campaigns\"].describe())\n",
"np.quantile(X_train[\"nb_campaigns\"], 0.99)"
]
},
{
"cell_type": "code",
"execution_count": 80,
"id": "8bb01064-1c23-4100-ace8-56f155e0b4ab",
"metadata": {},
"outputs": [],
"source": [
"### on retire les outliers - variables : nb purchases, nb tickets, total amount, fidelity\n",
"\n",
"p99_nb_purchases = np.quantile(X_train[\"nb_purchases\"], 0.99)\n",
"p99_nb_tickets = np.quantile(X_train[\"nb_tickets\"], 0.99)\n",
"p99_total_amount = np.quantile(X_train[\"total_amount\"], 0.99)\n",
"p99_fidelity = np.quantile(X_train[\"fidelity\"], 0.99)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 98,
"id": "b2b43ab6-16aa-41bc-9a62-47ab769c5bf2",
"metadata": {},
"outputs": [],
"source": [
"# filtre - on enlève les valeurs aberrantes sur les variables problématiques (retire 2% des valeurs en tt)\n",
"\n",
"X_train = X_train.loc[(X_train[\"nb_purchases\"] <= p99_nb_purchases) &\n",
"(X_train[\"nb_tickets\"] <= p99_nb_tickets) &\n",
"(X_train[\"total_amount\"] <= p99_total_amount) &\n",
"(X_train[\"fidelity\"] <= p99_fidelity)]"
]
},
{
"cell_type": "code",
"execution_count": 99,
"id": "b254a671-9e57-4123-ae65-55c852eb64cd",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" nb_tickets | \n",
" nb_purchases | \n",
" total_amount | \n",
" nb_suppliers | \n",
" nb_tickets_internet | \n",
" fidelity | \n",
" nb_campaigns | \n",
" nb_campaigns_opened | \n",
" opt_in | \n",
" vente_internet_max | \n",
"
\n",
" \n",
" \n",
" \n",
" 6 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 2.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 7 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 12.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 8 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 24.0 | \n",
" 10.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 9 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 14.0 | \n",
" 7.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 10 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1 | \n",
" 23.0 | \n",
" 11.0 | \n",
" 1 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" nb_tickets nb_purchases total_amount nb_suppliers nb_tickets_internet \\\n",
"6 0.0 0.0 0.0 0.0 0.0 \n",
"7 0.0 0.0 0.0 0.0 0.0 \n",
"8 0.0 0.0 0.0 0.0 0.0 \n",
"9 0.0 0.0 0.0 0.0 0.0 \n",
"10 0.0 0.0 0.0 0.0 0.0 \n",
"\n",
" fidelity nb_campaigns nb_campaigns_opened opt_in vente_internet_max \n",
"6 1 2.0 0.0 1 0.0 \n",
"7 1 12.0 0.0 1 0.0 \n",
"8 1 24.0 10.0 1 0.0 \n",
"9 1 14.0 7.0 1 0.0 \n",
"10 1 23.0 11.0 1 0.0 "
]
},
"execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_train.head()"
]
},
{
"cell_type": "code",
"execution_count": 101,
"id": "86d90380-6ad2-4c6b-a103-53e4c1fa59e0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" customer_id | \n",
" event_type_id | \n",
" nb_tickets | \n",
" nb_purchases | \n",
" total_amount | \n",
" nb_suppliers | \n",
" vente_internet_max | \n",
" purchase_date_min | \n",
" purchase_date_max | \n",
" time_between_purchase | \n",
" ... | \n",
" tenant_id | \n",
" gender_label | \n",
" gender_female | \n",
" gender_male | \n",
" gender_other | \n",
" country_fr | \n",
" nb_campaigns | \n",
" nb_campaigns_opened | \n",
" time_to_open | \n",
" y_has_purchased | \n",
"
\n",
" \n",
" \n",
" \n",
" 6 | \n",
" 5 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" male | \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 1.0 | \n",
" 2.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 7 | \n",
" 6 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" male | \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 1.0 | \n",
" 12.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 8 | \n",
" 7 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" female | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" 1.0 | \n",
" 24.0 | \n",
" 10.0 | \n",
" 5 days 11:58:52 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 9 | \n",
" 8 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" female | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" 1.0 | \n",
" 14.0 | \n",
" 7.0 | \n",
" 0 days 13:29:25.714285714 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 10 | \n",
" 9 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" female | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" 1.0 | \n",
" 23.0 | \n",
" 11.0 | \n",
" 0 days 17:17:44.090909090 | \n",
" 0.0 | \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",
" 152645 | \n",
" 1256102 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" female | \n",
" 1 | \n",
" 0 | \n",
" 0 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152646 | \n",
" 1256103 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152647 | \n",
" 1256104 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152648 | \n",
" 1256105 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
" 152649 | \n",
" 1256106 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" ... | \n",
" 1311 | \n",
" other | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" NaN | \n",
" 0.0 | \n",
" 0.0 | \n",
" NaN | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
125792 rows × 42 columns
\n",
"
"
],
"text/plain": [
" customer_id event_type_id nb_tickets nb_purchases total_amount \\\n",
"6 5 NaN 0.0 0.0 0.0 \n",
"7 6 NaN 0.0 0.0 0.0 \n",
"8 7 NaN 0.0 0.0 0.0 \n",
"9 8 NaN 0.0 0.0 0.0 \n",
"10 9 NaN 0.0 0.0 0.0 \n",
"... ... ... ... ... ... \n",
"152645 1256102 NaN 0.0 0.0 0.0 \n",
"152646 1256103 NaN 0.0 0.0 0.0 \n",
"152647 1256104 NaN 0.0 0.0 0.0 \n",
"152648 1256105 NaN 0.0 0.0 0.0 \n",
"152649 1256106 NaN 0.0 0.0 0.0 \n",
"\n",
" nb_suppliers vente_internet_max purchase_date_min \\\n",
"6 0.0 0.0 NaN \n",
"7 0.0 0.0 NaN \n",
"8 0.0 0.0 NaN \n",
"9 0.0 0.0 NaN \n",
"10 0.0 0.0 NaN \n",
"... ... ... ... \n",
"152645 0.0 0.0 NaN \n",
"152646 0.0 0.0 NaN \n",
"152647 0.0 0.0 NaN \n",
"152648 0.0 0.0 NaN \n",
"152649 0.0 0.0 NaN \n",
"\n",
" purchase_date_max time_between_purchase ... tenant_id gender_label \\\n",
"6 NaN NaN ... 1311 male \n",
"7 NaN NaN ... 1311 male \n",
"8 NaN NaN ... 1311 female \n",
"9 NaN NaN ... 1311 female \n",
"10 NaN NaN ... 1311 female \n",
"... ... ... ... ... ... \n",
"152645 NaN NaN ... 1311 female \n",
"152646 NaN NaN ... 1311 other \n",
"152647 NaN NaN ... 1311 other \n",
"152648 NaN NaN ... 1311 other \n",
"152649 NaN NaN ... 1311 other \n",
"\n",
" gender_female gender_male gender_other country_fr nb_campaigns \\\n",
"6 0 1 0 1.0 2.0 \n",
"7 0 1 0 1.0 12.0 \n",
"8 1 0 0 1.0 24.0 \n",
"9 1 0 0 1.0 14.0 \n",
"10 1 0 0 1.0 23.0 \n",
"... ... ... ... ... ... \n",
"152645 1 0 0 1.0 0.0 \n",
"152646 0 0 1 NaN 0.0 \n",
"152647 0 0 1 NaN 0.0 \n",
"152648 0 0 1 NaN 0.0 \n",
"152649 0 0 1 NaN 0.0 \n",
"\n",
" nb_campaigns_opened time_to_open y_has_purchased \n",
"6 0.0 NaN 0.0 \n",
"7 0.0 NaN 0.0 \n",
"8 10.0 5 days 11:58:52 0.0 \n",
"9 7.0 0 days 13:29:25.714285714 0.0 \n",
"10 11.0 0 days 17:17:44.090909090 0.0 \n",
"... ... ... ... \n",
"152645 0.0 NaN 0.0 \n",
"152646 0.0 NaN 0.0 \n",
"152647 0.0 NaN 0.0 \n",
"152648 0.0 NaN 0.0 \n",
"152649 0.0 NaN 0.0 \n",
"\n",
"[125792 rows x 42 columns]"
]
},
"execution_count": 101,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"\n",
"dataset_train = dataset_train.loc[(dataset_train[\"nb_purchases\"] <= p99_nb_purchases) &\n",
"(dataset_train[\"nb_tickets\"] <= p99_nb_tickets) &\n",
"(dataset_train[\"total_amount\"] <= p99_total_amount) &\n",
"(dataset_train[\"fidelity\"] <= p99_fidelity)]\n",
"\n",
"dataset_train"
]
},
{
"cell_type": "markdown",
"id": "f9487c48-b973-4d9e-abb9-902800ab778f",
"metadata": {},
"source": [
"En enlevant les outliers, on supprime la plupart des clients ayant acheté à nouveau ... Il faut trouver un autre moyen de preprocessing qui ne dégrade pas le dataset"
]
},
{
"cell_type": "code",
"execution_count": 102,
"id": "9fe7513b-f23b-4bee-957d-f98919d6eb30",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"19.0"
]
},
"execution_count": 102,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset_train[\"y_has_purchased\"].sum() # pb : on passe de 161 à 19 clients ayant acheté ..."
]
},
{
"cell_type": "markdown",
"id": "b531aebb-3b2f-4c62-ae01-84bdf8e45f49",
"metadata": {},
"source": [
"### Construction de la pipeline pour le modèle de régression logistique et résultats"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "1476da0d-cbb5-46ac-9f97-10855eec0108",
"metadata": {},
"outputs": [],
"source": [
"# importations pr créer la pipeline\n",
"\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.pipeline import Pipeline\n",
"from sklearn.compose import ColumnTransformer\n",
"from sklearn.preprocessing import OneHotEncoder\n",
"from sklearn.impute import SimpleImputer\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.model_selection import GridSearchCV\n",
"from sklearn.preprocessing import StandardScaler, MaxAbsScaler, MinMaxScaler\n",
"from sklearn.metrics import make_scorer, f1_score, balanced_accuracy_score"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "f905cb6f-b0be-4a47-ac8d-7b3e16ff1dce",
"metadata": {},
"outputs": [],
"source": [
"# debut de la pipeline\n",
"numeric_transformer = Pipeline(steps=[\n",
" (\"imputer\", SimpleImputer(strategy=\"constant\", fill_value=0)), # to deal with missing numeric data\n",
" (\"scaler\", StandardScaler())])\n",
"\"\"\"\n",
"categorical_transformer = Pipeline(steps=[\n",
" (\"imputer\", SimpleImputer(strategy=\"constant\", fill_value=\"Not defined\")),\n",
" (\"onehot\", OneHotEncoder(handle_unknown='ignore'))]) # to deal with missing categorical data\n",
"\n",
"\"\"\"\n",
"preproc = ColumnTransformer(transformers=[(\"num\", numeric_transformer, numeric_features)])\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "d322fb8f-1e97-4a44-96ca-c0f5d7ebd383",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'mean_fit_time': array([0.96252505, 0.94368339, 0.86111466, 0.95700479, 1.13914712,\n",
" 1.10024587, 1.36208344, 1.40060536, 1.56624715, 1.76191751,\n",
" 1.80110041, 1.67103759, 1.67045991, 1.62652612, 1.55767004,\n",
" 2.12057273, 1.5302736 ]), 'std_fit_time': array([0.29823822, 0.30278155, 0.12007493, 0.33517543, 0.09216138,\n",
" 0.2062314 , 0.04610438, 0.07753108, 0.39466125, 0.2932071 ,\n",
" 0.43120394, 0.50535675, 0.33981082, 0.32312159, 0.20155337,\n",
" 0.30868145, 0.39882192]), 'mean_score_time': array([0.23762226, 0.23680433, 0.20498077, 0.17563709, 0.19579411,\n",
" 0.19613473, 0.17243052, 0.19963646, 0.19995451, 0.23090204,\n",
" 0.20571589, 0.22864676, 0.23558458, 0.20300301, 0.20324389,\n",
" 0.20974334, 0.20976925]), 'std_score_time': array([0.03395174, 0.04038772, 0.00520132, 0.03606735, 0.00459383,\n",
" 0.00303405, 0.03295904, 0.00485894, 0.00429703, 0.0379754 ,\n",
" 0.06829149, 0.03898822, 0.04453358, 0.00527175, 0.00196754,\n",
" 0.0057154 , 0.00853897]), 'param_logreg__C': masked_array(data=[0.0009765625, 0.001953125, 0.00390625, 0.0078125,\n",
" 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1.0, 2.0,\n",
" 4.0, 8.0, 16.0, 32.0, 64.0],\n",
" mask=[False, False, False, False, False, False, False, False,\n",
" False, False, False, False, False, False, False, False,\n",
" False],\n",
" fill_value='?',\n",
" dtype=object), 'param_logreg__class_weight': masked_array(data=['balanced', 'balanced', 'balanced', 'balanced',\n",
" 'balanced', 'balanced', 'balanced', 'balanced',\n",
" 'balanced', 'balanced', 'balanced', 'balanced',\n",
" 'balanced', 'balanced', 'balanced', 'balanced',\n",
" 'balanced'],\n",
" mask=[False, False, False, False, False, False, False, False,\n",
" False, False, False, False, False, False, False, False,\n",
" False],\n",
" fill_value='?',\n",
" dtype=object), 'params': [{'logreg__C': 0.0009765625, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.001953125, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.00390625, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.0078125, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.015625, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.03125, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.0625, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.125, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.25, 'logreg__class_weight': 'balanced'}, {'logreg__C': 0.5, 'logreg__class_weight': 'balanced'}, {'logreg__C': 1.0, 'logreg__class_weight': 'balanced'}, {'logreg__C': 2.0, 'logreg__class_weight': 'balanced'}, {'logreg__C': 4.0, 'logreg__class_weight': 'balanced'}, {'logreg__C': 8.0, 'logreg__class_weight': 'balanced'}, {'logreg__C': 16.0, 'logreg__class_weight': 'balanced'}, {'logreg__C': 32.0, 'logreg__class_weight': 'balanced'}, {'logreg__C': 64.0, 'logreg__class_weight': 'balanced'}], 'split0_test_score': array([0.99373228, 0.99368542, 0.9935917 , 0.99363856, 0.9935917 ,\n",
" 0.99339253, 0.99260761, 0.99278334, 0.99386115, 0.99476323,\n",
" 0.99500926, 0.99506783, 0.99511469, 0.99512641, 0.99518499,\n",
" 0.99513812, 0.9951967 ]), 'split1_test_score': array([0.996872, 0.996872, 0.996872, 0.996872, 0.996872, 0.996872,\n",
" 0.996872, 0.996872, 0.996872, 0.996872, 0.996872, 0.996872,\n",
" 0.996872, 0.996872, 0.996872, 0.996872, 0.996872]), 'split2_test_score': array([0.91805656, 0.91806827, 0.91806827, 0.91806827, 0.91806827,\n",
" 0.91806827, 0.91806827, 0.91806827, 0.91806827, 0.91806827,\n",
" 0.91806827, 0.91806827, 0.91806827, 0.91806827, 0.91806827,\n",
" 0.91806827, 0.91806827]), 'mean_test_score': array([0.96955361, 0.9695419 , 0.96951066, 0.96952628, 0.96951066,\n",
" 0.96944427, 0.96918263, 0.9692412 , 0.96960047, 0.96990117,\n",
" 0.96998318, 0.9700027 , 0.97001832, 0.97002223, 0.97004175,\n",
" 0.97002613, 0.97004566]), 'std_test_score': array([0.03643647, 0.03642059, 0.0363999 , 0.03641024, 0.0363999 ,\n",
" 0.03635608, 0.03618521, 0.0362232 , 0.03645949, 0.0366615 ,\n",
" 0.03671726, 0.03673057, 0.03674124, 0.0367439 , 0.03675725,\n",
" 0.03674657, 0.03675992]), 'rank_test_score': array([10, 11, 13, 12, 13, 15, 17, 16, 9, 8, 7, 6, 5, 4, 2, 3, 1],\n",
" dtype=int32)}\n",
"Returned hyperparameter: {'logreg__C': 64.0, 'logreg__class_weight': 'balanced'}\n",
"Best classification accuracy in train is: 0.9700456574978843\n",
"Classification accuracy on test is: 0.9758585408905238\n"
]
}
],
"source": [
"# on doit prendre une métrique adaptée aux datasets déséquilibrés\n",
"balanced_scorer = make_scorer(balanced_accuracy_score)\n",
"\n",
"parameter_space = np.logspace(-10, 6, 17, base=2)\n",
"\n",
"pipe = Pipeline([('preprocessor', preproc), ('logreg', LogisticRegression(max_iter=5000))])\n",
"# on met plus de poids sur les observations rares (utile pr gérer le déséquilibre du dataset)\n",
"parameters4 = {'logreg__C': parameter_space, 'logreg__class_weight': ['balanced']} \n",
"clf4 = GridSearchCV(pipe, parameters4, cv=3, scoring = balanced_scorer)\n",
"clf4.fit(X_train, y_train)\n",
"\n",
"# print results\n",
"# print(clf4.cv_results_)\n",
"print('Returned hyperparameter: {}'.format(clf4.best_params_))\n",
"print('Best classification accuracy in train is: {}'.format(clf4.best_score_))\n",
"print('Classification accuracy on test is: {}'.format(clf4.score(X_test, y_test)))"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "b32bb668-c816-4055-b786-e548eb71f318",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.9517777188411676\n",
"Confusion Matrix:\n",
" [[121855 6182]\n",
" [ 0 161]]\n",
"Classification Report:\n",
" precision recall f1-score support\n",
"\n",
" 0.0 1.00 0.95 0.98 128037\n",
" 1.0 0.03 1.00 0.05 161\n",
"\n",
" accuracy 0.95 128198\n",
" macro avg 0.51 0.98 0.51 128198\n",
"weighted avg 1.00 0.95 0.97 128198\n",
"\n"
]
}
],
"source": [
"# visualisation des résultats \n",
"\n",
"y_pred = clf4.predict(X_test)\n",
"\n",
"#Evaluation du modèle \n",
"accuracy = accuracy_score(y_test, y_pred)\n",
"conf_matrix = confusion_matrix(y_test, y_pred)\n",
"class_report = classification_report(y_test, y_pred)\n",
"\n",
"print(\"Accuracy:\", accuracy)\n",
"print(\"Confusion Matrix:\\n\", conf_matrix)\n",
"print(\"Classification Report:\\n\", class_report)\n"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "faebbecb-3f85-4181-8005-2f52180fa37e",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjYAAAHFCAYAAADhWLMfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAABV70lEQVR4nO3de1xVVf7/8dcR4YgoR0QBMcwbkYSTimVopeZd0a6jRpFMhpa3SDSzi2I1oOZXy7vddMbJodJsrJTRtCxT1FBKzbLygo4gXhATEQj27w9/npkjqKDnoqf3s8d+PGTvz1577ePjxMfPWmtvk2EYBiIiIiJuoJqrOyAiIiJiL0psRERExG0osRERERG3ocRGRERE3IYSGxEREXEbSmxERETEbSixEREREbehxEZERETchhIbERERcRtKbMStff/99/zlL3+hSZMm1KhRg1q1atGmTRumTp3KiRMnHHrt7du307FjRywWCyaTiddff93u1zCZTCQlJdm93ctZtGgRJpMJk8nEl19+We64YRg0b94ck8lEp06drugac+fOZdGiRVU658svv7xon0Tkj6G6qzsg4ihvvfUWw4YNIywsjLFjxxIeHk5JSQnffvst8+fPZ9OmTSxfvtxh13/88ccpKCggNTUVPz8/GjdubPdrbNq0iRtuuMHu7VZW7dq1eeedd8olL+vXr+fXX3+ldu3aV9z23LlzqVevHnFxcZU+p02bNmzatInw8PArvq6IXN+U2Ihb2rRpE0899RTdunXj448/xmw2W49169aNxMRE0tLSHNqHnTt3Eh8fT69evRx2jTvuuMNhbVfGgAEDeO+995gzZw6+vr7W/e+88w5RUVGcOnXKKf0oKSnBZDLh6+vr8s9ERFxLQ1HilpKTkzGZTLz55ps2Sc15Xl5e9OvXz/pzWVkZU6dO5eabb8ZsNhMQEMBjjz3GoUOHbM7r1KkTERERbN26lbvuuouaNWvStGlTJk+eTFlZGfDfYZrff/+defPmWYdsAJKSkqx//l/nz9m/f79137p16+jUqRP+/v54e3vTqFEjHnzwQc6cOWONqWgoaufOndx77734+flRo0YNWrVqxd/+9jebmPNDNv/85z954YUXCA4OxtfXl65du/LTTz9V7kMGHn74YQD++c9/Wvfl5+ezbNkyHn/88QrPmTRpEu3ataNu3br4+vrS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ERG3oYqNiIiIg2koynmU2IiIiDiY8hrn0VCUiIiIuA1VbERERBzMhEo2zqLERkRExMG0Ksp5NBQlIiIibkMVGxEREQfTqijnUWIjIiLiYMprnEdDUSIiIuI2VLERERFxsGoq2TiNEhsREREHU17jPEpsREREHEyTh51Hc2xERETEbahiIyIi4mAq2DiPEhsREREH0+Rh59FQlIiIiLgNVWxEREQcTPUa51FiIyIi4mBaFeU8GooSERERt6GKjYiIiINVU8HGaSqV2KxYsaLSDfbr1++KOyMiIuKONBTlPJVKbO67775KNWYymSgtLb2a/oiIiIhcsUolNmVlZY7uh4iIiNtSwcZ5NMdGRETEwTQU5TxXlNgUFBSwfv16srKyKC4utjk2atQou3RMRETEXWjysPNUObHZvn07vXv35syZMxQUFFC3bl2OHTtGzZo1CQgIUGIjIiIiLlPl59g888wz9O3blxMnTuDt7U16ejoHDhwgMjKSadOmOaKPIiIi1zWTyWSXTS6vyolNZmYmiYmJeHh44OHhQVFRESEhIUydOpXnn3/eEX0UERG5rpnstMnlVTmx8fT0tGaNgYGBZGVlAWCxWKx/FhEREXGFKs+xad26Nd9++y033XQTnTt3ZsKECRw7dozFixfTsmVLR/RRRETkulZNw0hOU+WKTXJyMg0aNADglVdewd/fn6eeeorc3FzefPNNu3dQRETkemcy2WeTy6tyxaZt27bWP9evX5+VK1fatUMiIiIiV0oP6BMREXEwrWhynionNk2aNLnkX9DevXuvqkMiIiLuRnmN81Q5sUlISLD5uaSkhO3bt5OWlsbYsWPt1S8RERGRKqtyYvP0009XuH/OnDl8++23V90hERERd6NVUc5T5VVRF9OrVy+WLVtmr+ZERETchlZFOY/dEpulS5dSt25dezUnIiLiNlz1SoX//Oc/PProo/j7+1OzZk1atWpFRkaG9bhhGCQlJREcHIy3tzedOnVi165dNm0UFRUxcuRI6tWrh4+PD/369ePQoUM2MXl5ecTGxmKxWLBYLMTGxnLy5EmbmKysLPr27YuPjw/16tVj1KhR5V6kbQ9X9IC+//1wDcMgJyeHo0ePMnfuXLt2TkRERK5MXl4eHTp0oHPnzqxatYqAgAB+/fVX6tSpY42ZOnUq06dPZ9GiRdx00028+uqrdOvWjZ9++onatWsD5+bWfvLJJ6SmpuLv709iYiLR0dFkZGTg4eEBQExMDIcOHSItLQ2AIUOGEBsbyyeffAJAaWkpffr0oX79+mzYsIHjx48zaNAgDMNg1qxZdr1vk2EYRlVOSEpKsklsqlWrRv369enUqRM333yzXTt3pc7+7uoeiIjI9aKGEx58MnL5bru0M+v+FpWOfe655/jmm2/4+uuvKzxuGAbBwcEkJCQwbtw44Fx1JjAwkClTpjB06FDy8/OpX78+ixcvZsCAAQAcPnyYkJAQVq5cSY8ePdi9ezfh4eGkp6fTrl07ANLT04mKiuLHH38kLCyMVatWER0dzcGDBwkODgYgNTWVuLg4cnNz8fX1vZqPxUaV/zqTkpLsdnEREZE/Alc8x2bFihX06NGDP//5z6xfv56GDRsybNgw4uPjAdi3bx85OTl0797deo7ZbKZjx45s3LiRoUOHkpGRQUlJiU1McHAwERERbNy4kR49erBp0yYsFos1qQG44447sFgsbNy4kbCwMDZt2kRERIQ1qQHo0aMHRUVFZGRk0LlzZ7vdd5Xn2Hh4eJCbm1tu//Hjx60lKREREbG/oqIiTp06ZbMVFRVVGLt3717mzZtHaGgo//73v3nyyScZNWoUf//73wHIyckBzr3Q+n8FBgZaj+Xk5ODl5YWfn98lYwICAspdPyAgwCbmwuv4+fnh5eVljbGXKic2Fxu5KioqwsvL66o7JCIi4m6qmeyzpaSkWCfont9SUlIqvGZZWRlt2rQhOTmZ1q1bM3ToUOLj45k3b55N3IXVJMMwLlthujCmovgribGHSg9FzZw5EzjXsbfffptatWpZj5WWlvLVV19dM3NsREREriXV7PS7e/z48YwePdpmn9lsrjC2QYMGhIeH2+xr0aKF9dEsQUFBwLlqyvmXWwPk5uZaqytBQUEUFxeTl5dnU7XJzc2lffv21pgjR46Uu/7Ro0dt2tm8ebPN8by8PEpKSspVcq5WpRObGTNmAOeyq/nz59sMO3l5edG4cWPmz59v186JiIjIf5nN5osmMhfq0KEDP/30k82+PXv2cOONNwLnXpEUFBTEmjVraN26NQDFxcWsX7+eKVOmABAZGYmnpydr1qyhf//+AGRnZ7Nz506mTp0KQFRUFPn5+WzZsoXbb78dgM2bN5Ofn29NfqKiovjrX/9Kdna2NYlavXo1ZrOZyMjIq/lIyql0YrNv3z4AOnfuzEcffVRuvE1EREQq5orJw8888wzt27cnOTmZ/v37s2XLFt58803efPNNa58SEhJITk4mNDSU0NBQkpOTqVmzJjExMQBYLBYGDx5MYmIi/v7+1K1blzFjxtCyZUu6du0KnKsC9ezZk/j4eBYsWACcW+4dHR1NWFgYAN27dyc8PJzY2Fhee+01Tpw4wZgxY4iPj7friii4guXe1wMt9xYRkcpyxnLvsZ/+dPmgSngtOqxK8Z9++injx4/n559/pkmTJowePdq6KgrOjcJMmjSJBQsWkJeXR7t27ZgzZw4RERHWmLNnzzJ27FiWLFlCYWEhXbp0Ye7cuYSEhFhjTpw4wahRo1ixYgUA/fr1Y/bs2TbPzMnKymLYsGGsW7cOb29vYmJimDZtWqUrUJVV5cTmoYceom3btjz33HM2+1977TW2bNnChx9+aNcOXgklNiIiUlnunNj8EVV5VdT69evp06dPuf09e/bkq6++skunRERE3IneFeU8Vc5TT58+XeGybk9PT06dOmWXTomIiLgTvd3beapcsYmIiOD9998vtz81NbXcsjIRERE598vWHptcXpUrNi+99BIPPvggv/76K/fccw8Aa9euZcmSJSxdutTuHRQRERGprConNv369ePjjz8mOTmZpUuX4u3tza233sq6devsvmRLRETEHWgkynmuaC54nz59rBOIT548yXvvvUdCQgLfffcdpaWldu2giIjI9U5zbJzniofs1q1bx6OPPkpwcDCzZ8+md+/efPvtt/bsm4iIiEiVVKlic+jQIRYtWsS7775LQUEB/fv3p6SkhGXLlmnisIiIyEWoYOM8la7Y9O7dm/DwcH744QdmzZrF4cOHmTVrliP7JiIi4hbs9XZvubxKV2xWr17NqFGjeOqppwgNDXVkn0RERESuSKUrNl9//TW//fYbbdu2pV27dsyePZujR486sm8iIiJuoZrJZJdNLq/SiU1UVBRvvfUW2dnZDB06lNTUVBo2bEhZWRlr1qzht99+c2Q/RURErlt6pYLzVHlVVM2aNXn88cfZsGEDO3bsIDExkcmTJxMQEEC/fv0c0UcRERGRSrmqJzSHhYUxdepUDh06xD//+U979UlERMStaPKw85gMwzBc3Ql7O/u7q3sgIiLXixpX9Kjaqkle+6td2nm+SzO7tOPOnPDXKSIi8semaovz6GWhIiIi4jZUsREREXEwVWycR4mNiIiIg5m0VttpNBQlIiIibkMVGxEREQfTUJTzKLERERFxMI1EOY+GokRERMRtqGIjIiLiYHqBpfMosREREXEwzbFxHg1FiYiIiNtQxUZERMTBNBLlPEpsREREHKwaymycRYmNiIiIg6li4zyaYyMiIiJuQxUbERERB9OqKOdRYiMiIuJgeo6N82goSkRERNyGKjYiIiIOpoKN8yixERERcTANRTmPhqJERETEbahiIyIi4mAq2DiPEhsREREH0/CI8+izFhEREbehio2IiIiDmTQW5TRKbERERBxMaY3zKLERERFxMC33dh7NsRERERG3oYqNiIiIg6le4zxKbERERBxMI1HOo6EoERERcRuq2IiIiDiYlns7jxIbERERB9PwiPPosxYRERG3oYqNiIiIg2koynlUsREREXEwk522q5GSkoLJZCIhIcG6zzAMkpKSCA4Oxtvbm06dOrFr1y6b84qKihg5ciT16tXDx8eHfv36cejQIZuYvLw8YmNjsVgsWCwWYmNjOXnypE1MVlYWffv2xcfHh3r16jFq1CiKi4uv8q7KU2IjIiLi5rZu3cqbb77Jn/70J5v9U6dOZfr06cyePZutW7cSFBREt27d+O2336wxCQkJLF++nNTUVDZs2MDp06eJjo6mtLTUGhMTE0NmZiZpaWmkpaWRmZlJbGys9XhpaSl9+vShoKCADRs2kJqayrJly0hMTLT7vZoMwzDs3qqLnf3d1T0QEZHrRQ0nTMpY+l22Xdp56NYGVT7n9OnTtGnThrlz5/Lqq6/SqlUrXn/9dQzDIDg4mISEBMaNGwecq84EBgYyZcoUhg4dSn5+PvXr12fx4sUMGDAAgMOHDxMSEsLKlSvp0aMHu3fvJjw8nPT0dNq1awdAeno6UVFR/Pjjj4SFhbFq1Sqio6M5ePAgwcHBAKSmphIXF0dubi6+vr52+XxAFRsRERGHq2anraioiFOnTtlsRUVFl7z28OHD6dOnD127drXZv2/fPnJycujevbt1n9lspmPHjmzcuBGAjIwMSkpKbGKCg4OJiIiwxmzatAmLxWJNagDuuOMOLBaLTUxERIQ1qQHo0aMHRUVFZGRkVOozrCwlNiIiIg5mMpnssqWkpFjnsZzfUlJSLnrd1NRUtm3b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iIjYkxIbESfz8fGhefPmlYpt06YNOTk5VK9encaNG1cY06JFC9LT03nssces+9LT0y/aZmhoKN7e3qxdu5Ynnnii3PHzc2pKS0ut+wIDA2nYsCF79+7lkUceqbDd8PBwFi9eTGFhoTV5ulQ/REQcQUNRItewrl27EhUVxX333ce///1v9u/fz8aNG3nxxRf59ttvAXj66ad59913effdd9mzZw8TJ05k165dF22zRo0ajBs3jmeffZa///3v/Prrr6Snp/POO+8AEBAQgLe3N2lpaRw5coT8/Hzg3EP/UlJSeOONN9izZw87duxg4cKFTJ8+HYCYmBiqVavG4MGD+eGHH1i5ciXTpk1z8CckImJLiY3INcxkMrFy5UruvvtuHn/8cW666SYGDhzI/v37CQwMBGDAgAFMmDCBcePGERkZyYEDB3jqqacu2e5LL71EYmIiEyZMoEWLFgwYMIDc3FwAqlevzsyZM1mwYAHBwcHce++9ADzxxBO8/fbbLFq0iJYtW9KxY0cWLVpkXR5eq1YtPvnkE3744Qdat27NCy+8wJQpUxz46YiIlGcyNDAuIiIibkIVGxEREXEbSmxERETEbSixEREREbehxEZERETchhIbERERcRtKbERERMRtKLERERERt6HERkRERNyGEhsRERFxG0psRERExG0osRERERG3ocRGRERE3Mb/A1RCyYaU5WGGAAAAAElFTkSuQmCC",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# matrice de confusion\n",
"\n",
"sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=['Class 0', 'Class 1'], yticklabels=['Class 0', 'Class 1'])\n",
"plt.xlabel('Predicted')\n",
"plt.ylabel('Actual')\n",
"plt.title('Confusion Matrix')\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}