{ "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", " \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", "
event_type_idname_event_types
02.0offre muséale individuel
14.0spectacle vivant
25.0offre muséale groupe
3NaNNaN
\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": "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", "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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", "
nb_ticketsnb_purchasestotal_amountnb_suppliersnb_tickets_internetfidelitynb_campaignsnb_campaigns_openedopt_invente_internet_max
2122983.065082.0878762.55.09.03308310.00.001.0
30.00.00.00.00.01732.00.010.0
152773.081.032338.02.02.094126.050.011.0
240.00.00.00.00.022421.00.010.0
28282.015.00.02.053.03432.013.011.0
.................................
14490514.08.0136.02.00.091.00.010.0
144906190.0120.01757.02.00.01201.00.010.0
144950761.0418.05406.52.00.09071.00.010.0
14495911.08.0103.01.00.081.00.010.0
1506860.00.00.00.00.060.00.010.0
\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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idevent_type_idnb_ticketsnb_purchasestotal_amountnb_suppliersvente_internet_maxpurchase_date_minpurchase_date_maxtime_between_purchase...tenant_idgender_labelgender_femalegender_malegender_othercountry_frnb_campaignsnb_campaigns_openedtime_to_openy_has_purchased
215.0122983.065082.0878762.55.01.0267.4377890.23066267.20713...1311other0011.00.00.0NaN1.0
32NaN0.00.00.00.00.0NaNNaNNaN...1311male0101.02.00.0NaN0.0
65NaN0.00.00.00.00.0NaNNaNNaN...1311male0101.02.00.0NaN0.0
76NaN0.00.00.00.00.0NaNNaNNaN...1311male0101.012.00.0NaN0.0
87NaN0.00.00.00.00.0NaNNaNNaN...1311female1001.024.010.05 days 11:58:520.0
..................................................................
1526451256102NaN0.00.00.00.00.0NaNNaNNaN...1311female1001.00.00.0NaN0.0
1526461256103NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
1526471256104NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
1526481256105NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
1526491256106NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", "
nb_ticketsnb_purchasestotal_amountnb_suppliersnb_tickets_internetfidelitynb_campaignsnb_campaigns_openedopt_invente_internet_max
2122983.065082.0878762.55.09.03308310.00.001.0
30.00.00.00.00.01732.00.010.0
60.00.00.00.00.012.00.010.0
70.00.00.00.00.0112.00.010.0
80.00.00.00.00.0124.010.010.0
.................................
1526450.00.00.00.00.000.00.000.0
1526460.00.00.00.00.000.00.000.0
1526470.00.00.00.00.000.00.000.0
1526480.00.00.00.00.000.00.000.0
1526490.00.00.00.00.000.00.000.0
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", "
nb_ticketsnb_purchasestotal_amountnb_suppliersnb_tickets_internetfidelitynb_campaignsnb_campaigns_openedopt_invente_internet_max
2122983.065082.0878762.55.09.03308310.00.001.0
152773.081.032338.02.02.094126.050.011.0
28282.015.00.02.053.03432.013.011.0
2940.02.00.01.00.0424.017.010.0
3152.02.00.01.00.0522.06.010.0
.................................
1471554.02.044.01.04.020.00.001.0
1472423.02.040.01.03.020.00.001.0
14741412.02.0132.01.012.020.00.001.0
14763615.02.0165.01.015.020.00.001.0
1479502.02.029.01.02.020.00.001.0
\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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nb_ticketsnb_purchasestotal_amountnb_suppliersnb_tickets_internetfidelitynb_campaignsnb_campaigns_openedopt_invente_internet_max
60.00.00.00.00.012.00.010.0
70.00.00.00.00.0112.00.010.0
80.00.00.00.00.0124.010.010.0
90.00.00.00.00.0114.07.010.0
100.00.00.00.00.0123.011.010.0
\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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idevent_type_idnb_ticketsnb_purchasestotal_amountnb_suppliersvente_internet_maxpurchase_date_minpurchase_date_maxtime_between_purchase...tenant_idgender_labelgender_femalegender_malegender_othercountry_frnb_campaignsnb_campaigns_openedtime_to_openy_has_purchased
65NaN0.00.00.00.00.0NaNNaNNaN...1311male0101.02.00.0NaN0.0
76NaN0.00.00.00.00.0NaNNaNNaN...1311male0101.012.00.0NaN0.0
87NaN0.00.00.00.00.0NaNNaNNaN...1311female1001.024.010.05 days 11:58:520.0
98NaN0.00.00.00.00.0NaNNaNNaN...1311female1001.014.07.00 days 13:29:25.7142857140.0
109NaN0.00.00.00.00.0NaNNaNNaN...1311female1001.023.011.00 days 17:17:44.0909090900.0
..................................................................
1526451256102NaN0.00.00.00.00.0NaNNaNNaN...1311female1001.00.00.0NaN0.0
1526461256103NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
1526471256104NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
1526481256105NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
1526491256106NaN0.00.00.00.00.0NaNNaNNaN...1311other001NaN0.00.0NaN0.0
\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 }