a70c0802ae
- Enhanced .gitignore to include additional Python-related files. - Updated docker-compose.yml to version 3.8, added container name, health check, and network configuration. - Modified Dockerfile to set environment variables, install system dependencies, and add a health check. - Updated requirements.txt with specific package versions. - Removed obsolete files related to cloud deployment and experiments. - Improved EDA notebook with additional data loading and exploration steps.
300 lines
40 KiB
Plaintext
300 lines
40 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2e06e8ea",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Preprocessing Pipeline and Model Selection for Fraud Detection\n",
|
|
"This notebook sets up preprocessing and compares different models to pick the best one for fraud prediction.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "bc5f3e5f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Cell 2: Imports and Data Loading\n",
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import seaborn as sns\n",
|
|
"\n",
|
|
"from sklearn.model_selection import train_test_split, GridSearchCV\n",
|
|
"from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
|
|
"from sklearn.pipeline import Pipeline\n",
|
|
"from sklearn.compose import ColumnTransformer\n",
|
|
"from sklearn.metrics import classification_report, roc_auc_score\n",
|
|
"\n",
|
|
"from sklearn.linear_model import LogisticRegression\n",
|
|
"from sklearn.ensemble import RandomForestClassifier\n",
|
|
"from xgboost import XGBClassifier\n",
|
|
"from lightgbm import LGBMClassifier"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "9c62f57d",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Load and preprocess\n",
|
|
"df = pd.read_csv(\"../data/processed/resampled_data.csv\")\n",
|
|
"\n",
|
|
"# Dates\n",
|
|
"df['trans_date_trans_time'] = pd.to_datetime(df['trans_date_trans_time'])\n",
|
|
"df['dob'] = pd.to_datetime(df['dob'])\n",
|
|
"\n",
|
|
"# Time features\n",
|
|
"df['hour'] = df['trans_date_trans_time'].dt.hour\n",
|
|
"df['day'] = df['trans_date_trans_time'].dt.day\n",
|
|
"df['month'] = df['trans_date_trans_time'].dt.month\n",
|
|
"df['weekday'] = df['trans_date_trans_time'].dt.weekday\n",
|
|
"df['age'] = (df['trans_date_trans_time'] - df['dob']).dt.days // 365\n",
|
|
"\n",
|
|
"# Drop high-cardinality or unneeded columns\n",
|
|
"df = df.drop(columns=['trans_date_trans_time', 'dob', 'trans_num', 'unix_time', 'cc_num', 'street'])\n",
|
|
"\n",
|
|
"# Encode categorical variables\n",
|
|
"cat_cols = ['gender', 'category', 'job', 'merchant', 'first', 'last', 'city', 'state']\n",
|
|
"for col in cat_cols:\n",
|
|
" df[col] = LabelEncoder().fit_transform(df[col])\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "c15ede5e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Use only RFE-selected features\n",
|
|
"selected_features = [\n",
|
|
" 'merchant', 'category', 'amt', 'last', 'city',\n",
|
|
" 'city_pop', 'merch_lat', 'merch_long', 'hour', 'age'\n",
|
|
"]\n",
|
|
"\n",
|
|
"X = df[selected_features]\n",
|
|
"y = df['is_fraud']\n",
|
|
"\n",
|
|
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "b782c387",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Preprocessing pipeline\n",
|
|
"preprocessor = ColumnTransformer([\n",
|
|
" (\"num\", StandardScaler(), selected_features)\n",
|
|
"])\n",
|
|
"\n",
|
|
"# Define models\n",
|
|
"models = {\n",
|
|
" \"Logistic Regression\": LogisticRegression(max_iter=1000),\n",
|
|
" \"Random Forest\": RandomForestClassifier(n_estimators=100, random_state=42),\n",
|
|
" \"XGBoost\": XGBClassifier(use_label_encoder=False, eval_metric='logloss'),\n",
|
|
" \"LightGBM\": LGBMClassifier()\n",
|
|
"}\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "b9504216",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\\nLogistic Regression\n",
|
|
" precision recall f1-score support\n",
|
|
"\n",
|
|
" 0 0.80 0.95 0.87 1931\n",
|
|
" 1 0.94 0.76 0.84 1930\n",
|
|
"\n",
|
|
" accuracy 0.86 3861\n",
|
|
" macro avg 0.87 0.86 0.86 3861\n",
|
|
"weighted avg 0.87 0.86 0.86 3861\n",
|
|
"\n",
|
|
"AUC-ROC: 0.8519959321997514\n",
|
|
"\\nRandom Forest\n",
|
|
" precision recall f1-score support\n",
|
|
"\n",
|
|
" 0 0.97 0.98 0.98 1931\n",
|
|
" 1 0.98 0.97 0.97 1930\n",
|
|
"\n",
|
|
" accuracy 0.98 3861\n",
|
|
" macro avg 0.98 0.98 0.98 3861\n",
|
|
"weighted avg 0.98 0.98 0.98 3861\n",
|
|
"\n",
|
|
"AUC-ROC: 0.9969229881695705\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"c:\\Users\\babaw\\Documents\\Work\\Mana Knight Digital\\task_fraud_detection\\.venv\\Lib\\site-packages\\xgboost\\training.py:183: UserWarning: [12:43:21] WARNING: C:\\actions-runner\\_work\\xgboost\\xgboost\\src\\learner.cc:738: \n",
|
|
"Parameters: { \"use_label_encoder\" } are not used.\n",
|
|
"\n",
|
|
" bst.update(dtrain, iteration=i, fobj=obj)\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\\nXGBoost\n",
|
|
" precision recall f1-score support\n",
|
|
"\n",
|
|
" 0 0.98 0.98 0.98 1931\n",
|
|
" 1 0.98 0.98 0.98 1930\n",
|
|
"\n",
|
|
" accuracy 0.98 3861\n",
|
|
" macro avg 0.98 0.98 0.98 3861\n",
|
|
"weighted avg 0.98 0.98 0.98 3861\n",
|
|
"\n",
|
|
"AUC-ROC: 0.9981085802142841\n",
|
|
"[LightGBM] [Info] Number of positive: 7721, number of negative: 7720\n",
|
|
"[LightGBM] [Info] Auto-choosing row-wise multi-threading, the overhead of testing was 0.000341 seconds.\n",
|
|
"You can set `force_row_wise=true` to remove the overhead.\n",
|
|
"And if memory is not enough, you can set `force_col_wise=true`.\n",
|
|
"[LightGBM] [Info] Total Bins 1896\n",
|
|
"[LightGBM] [Info] Number of data points in the train set: 15441, number of used features: 10\n",
|
|
"[LightGBM] [Info] [binary:BoostFromScore]: pavg=0.500032 -> initscore=0.000130\n",
|
|
"[LightGBM] [Info] Start training from score 0.000130\n",
|
|
"\\nLightGBM\n",
|
|
" precision recall f1-score support\n",
|
|
"\n",
|
|
" 0 0.98 0.98 0.98 1931\n",
|
|
" 1 0.98 0.98 0.98 1930\n",
|
|
"\n",
|
|
" accuracy 0.98 3861\n",
|
|
" macro avg 0.98 0.98 0.98 3861\n",
|
|
"weighted avg 0.98 0.98 0.98 3861\n",
|
|
"\n",
|
|
"AUC-ROC: 0.9980592084962286\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"c:\\Users\\babaw\\Documents\\Work\\Mana Knight Digital\\task_fraud_detection\\.venv\\Lib\\site-packages\\sklearn\\utils\\validation.py:2739: UserWarning: X does not have valid feature names, but LGBMClassifier was fitted with feature names\n",
|
|
" warnings.warn(\n",
|
|
"c:\\Users\\babaw\\Documents\\Work\\Mana Knight Digital\\task_fraud_detection\\.venv\\Lib\\site-packages\\sklearn\\utils\\validation.py:2739: UserWarning: X does not have valid feature names, but LGBMClassifier was fitted with feature names\n",
|
|
" warnings.warn(\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Cell 4: Model Training & Evaluation\n",
|
|
"results = {}\n",
|
|
"for name, model in models.items():\n",
|
|
" pipe = Pipeline(steps=[('preprocessor', preprocessor), ('classifier', model)])\n",
|
|
" pipe.fit(X_train, y_train)\n",
|
|
" y_pred = pipe.predict(X_test)\n",
|
|
" y_prob = pipe.predict_proba(X_test)[:,1]\n",
|
|
"\n",
|
|
" print(f\"\\\\n{name}\")\n",
|
|
" print(classification_report(y_test, y_pred))\n",
|
|
" print(\"AUC-ROC:\", roc_auc_score(y_test, y_prob))\n",
|
|
"\n",
|
|
" results[name] = {\n",
|
|
" \"model\": pipe,\n",
|
|
" \"roc_auc\": roc_auc_score(y_test, y_prob)\n",
|
|
" }\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "097ea9bf",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAArMAAAIdCAYAAAAu8fWFAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAWetJREFUeJzt3QmcjfX7//HLkq0slZDlmyVryhppV4pCFL4iSyqlklBZUpZkLUu2hBQiSmgjSWlDyhZlCWXJnn0X9//x/vz+9/meGTPMYObM7byej8dh5j7L3HPmPudc9/W5Ptcnled5ngEAAAABlDrSOwAAAACcLYJZAAAABBbBLAAAAAKLYBYAAACBRTALAACAwCKYBQAAQGARzAIAACCwCGYBAAAQWASzAAAACCyCWeAClCpVKuvatWui7/fXX3+5+7777rtJsl8Xmvz589vDDz9sKdHtt99uJUuWjPRuAECSI5gFkogCQgWGuvzwww+nXK+VpPPly+eur1GjhgXRtm3b7Pnnn7dixYpZpkyZ7OKLL7Zy5crZq6++anv27In07iEZ+Me4f8mSJYvddttt9vnnn8d7n99++80aNWpkefLksfTp01vu3LntoYcectvjs3btWnviiSesYMGCliFDBvdzbrrpJnvjjTfs8OHDCd7fYcOGuf2sWLHiaU/oXn/99Tiv13Zdr9vFNnXqVLvnnnsse/bsli5dOvd7/fe//7Wvv/76jPt14MAB69KlizsB0evo8ssvt9KlS9uzzz5rmzdvTvDvB0SjtJHeAeBCpw/eCRMm2M033xxj+7fffmubNm1yH+ZB9PPPP9u9997rPoQVmCiIlV9++cV69+5t3333nX355Zd2IVu1apWlTk1O4K677rImTZq4E7T169fbm2++aTVr1rQZM2ZY1apVY9x2ypQp1qBBA7vsssvs0UcftQIFCrjA8O2337bJkyfbxIkT7f77749xHwXG9erVc68V/RwFfMeOHXMniS+88IILgkeMGJGgfR0/frzLqC9YsMDWrFljV1999Tn//vq9H3nkEXcCW6ZMGWvbtq3lypXLtmzZ4gLcO++803788Ue78cYb47z/8ePH7dZbb7WVK1da06ZN7ZlnnnGvK/1eeu/Q86HAGEA8PABJ4p133vH0EnvggQe87Nmze8ePH49xffPmzb1y5cp5V111lVe9evXz+rP1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LFu0aJG9+uqriXlIAAAAIHmC2fiozOCOO+5wrbmmTJlyPh4SAAAASJ5g1lesWDHbtGnT+XxIAAAAIHmCWfWbzZ079/l8SAAAACDpg9klS5bY888/b9WrVz9fDwkAAACcv24Gl156qetaENvBgwft33//tbvuusu6deuWmIcEAAAAkieYHThwYJzbs2TJYkWLFrUSJUqc/Z4AAAAASRnMNm3a9Iy32bVrl1122WWJ3Q8AAAAgcjWzX375pf33v/+1PHnynK+HBAAAAJIumF2/fr116dLF8ufPb/Xq1bPUqVPb2LFjz+UhAQAAgKQpM5Bjx465hRFGjRplP/74o1WpUsX1ll28eLFde+21iX04AAAAIHkys88884zrI/vGG2/Y/fff74LYTz/91HU4SJMmzdnvBQAAAJDUmdk333zT2rdvbx06dLDMmTOfzc8DAAAAIpOZHTdunC1YsMCuvPJKq1+/vn322Wd24sSJ87c3AAAAQFIFsw0aNLBZs2bZsmXLrFixYvb0009brly57OTJk/b7778n5qEAAACAyHQzKFCggFvp66+//rL33nvP6tSpY40aNbK8efNaq1atzn2vAAAAgKToZhBOE7+qVq3qLlosQW253nnnnXN5SAAAACD5Fk3o3bu37dmzx6361bp1a1u6dOm5PiQAAACQPMFsz549XVYWAAAACFww63ne+dkTAAAAILmDWQAAACCQE8BELbm0KhgAAACQojOzu3fvtsGDB9u+fftC2/Lly+eWst27d+8p1wEAAAApJpgdMmSIfffdd5YlS5ZTrsuaNat9//33LqAFAAAAUlww+9FHH1mLFi3ivf6JJ56wyZMnn4/9AgAAAM5vMLt27VorXLhwvNfrOt0GAAAASHHBrGpjN2/eHO/1ui51ahokAAAAIHkkKvIsU6aMTZs2Ld7rp06d6m4DAAAApLjWXC1btrQHH3zQ8ubNa08++aTL1MqJEyds2LBhNmDAAJswYUJS7SsAAABw9sFsnTp1rF27dtaqVSvr1KmTFSxY0G1ft26dHThwwF544QWrW7duUu0rAAAAcG6LJvTo0cNq1apl48ePtzVr1rjlbG+77TZr2LChVahQIbEPBwAAACTvCmAKWglcAQAAEMhg9ueff7b333/fVq9e7b4vWrSoNWjQwMqXL3++9w8AAACIV6L7aKlmtmLFijZq1CjbtGmTu4wYMcJta9++fWIfDgAAAEieYHbMmDFuudpBgwbZP//8Y0uWLHGXXbt2uU4G2j527Niz3xsAAAAgqcoMhg4daj179nQtusJddNFFrsPBv//+a0OGDLEmTZok5mEBAACApM/M/vbbb66TQXxq167tbgMAAACkyOVsjx07Fu/1x48fDy2kAAAAAKSoYLZs2bKuv2x8xo0b524DAAAApLia2eeff96VEhw9etSee+45y5kzp9u+detW69evnw0cONCmTp2aVPsKAAAAnH0wW6NGDde1QEGtgtesWbO67Xv37rW0adPa66+/7m4DAAAApMhFE5555hmXnZ08ebL98ccfbluRIkWsTp06li9fPjt8+LBlzJgxKfYVAAAAOPcVwBS0tmnTJsY2lR7079/f+vbt68oOAAAAgBQ1AUwBa8eOHd2ytTfeeKNNmzbNbX/nnXesQIECrgQhdpALAAAApIjMbOfOne2tt96yKlWq2Ny5c61evXrWrFkzmz9/vsvK6ntacwEAACBFBrMffvihW672vvvus+XLl9t1113nVv1aunSppUqVKun2EgAAADjXMoNNmzZZuXLl3NclS5a09OnTu7ICAlkAAACk+GD2xIkTli5dutD3asd1ySWXJMV+AQAAAOe3zMDzPHv44YddRlaOHDliLVq0sIsvvjjG7aZMmZKYhwUAAACSPpht2rRpjO8bNWp0dj8VAAAASO5gVi24AAAAgEDWzAIAAAApCcEsAAAAAotgFgAAAIFFMAsAAIDAIpgFAABAYBHMAgAAILAIZgEAABBYKSKYHTp0qOXPn98yZMhgFStWtAULFiTofhMnTrRUqVJZ7dq1k3wfAQAAkPJEPJidNGmStW3b1rp06WKLFi2yUqVKWdWqVW379u2nvd9ff/1lzz//vN1yyy3Jtq8AAABIWSIezPbv39+aN29uzZo1sxIlStjw4cMtU6ZMNnr06Hjvc+LECXvooYesW7duVrBgwWTdXwAAAKQcEQ1mjx07ZgsXLrQqVar8b4dSp3bfz5s3L977vfLKK5YjRw579NFHz/gzjh49avv27YtxAQAAwIUhosHszp07XZY1Z86cMbbr+61bt8Z5nx9++MHefvttGzlyZIJ+Rq9evSxr1qyhS758+c7LvgMAACDyIl5mkBj79++3xo0bu0A2e/bsCbpPx44dbe/evaHLxo0b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9WoXyO7Zs8dWrFjhTqAbN25MUIEkpRVSa9Wq5b4uUKCAOwEfNmyY5ciRg2OPMgMEnf8C/uOPP2zfvn02c+ZMmz17tg0dOtSKFCnihmTmz58f6d1ECuafz6dLl86yZctmd911l8u+9erVy21XIEttJPxjRe8rjz76qC1btswKFixol19+ubuOYV8k5XGXK1cua9OmjW3fvt0Fs7t27bKnn37aduzYwbFHMIsLgeobFYD8/PPPrrxAbrrpJnvhhResbNmyLmtCQIv4PiSUwV+4cKH9/fffNmbMGJs0aZKVKVPGPv744xgBrahWDdF9rOjEJn/+/DZ8+HAXzA4YMMC9BwlBBc4nlRSIf0zdeOONdvPNN7vPN51Qbdy4kYD2/yOYReDpRVy0aFFbuXKlG/rzlS9f3tq1a+f+V7CrWlogdnAydepUu/fee23w4MGuPEXZ2U6dOtn1119vn3zyifXs2dPdvnPnzvbkk08y2SeKj5Uvv/zSWrVqZddcc4099thj9vrrr7sTnbfeess++uij0PvR559/znGCczJ58mSrU6eOzZ07NzQR9T//+Y9lypTJ+vTpYw899JC1bNnSNm/e7P73A9porRylZhaBEl9tkD5kunbt6uqIxo4dG2Pil94MvvjiC+vSpQu1j4hBE770gTFkyBC77777LHv27KHrNJz32muvuWBXJQjbtm2z6dOnW8WKFSO6z4gMBasKYJURU011hQoV3Pbff//d2rZt6zK21apVc5PCXnnlFdcdI1++fJHebQTQqlWr7JZbbnEjQYULF3ZfazTgpZdecgkbBbKPPPKIPfDAA26eyPjx491nmwLgSy+91KIRwSwCGch+++23LvOh4FVZNfnqq69c8KEPk3feecdla2NjMg/Ch/Aef/xxN4Gib9++dvDgQduwYYO99957riatevXqljlzZps3b577cFGgcvXVV0d6txEB6nBx9913W48ePdwx41Pd4mWXXWZ//vmnCzR0nBw6dMgdQypxAs6GRog0ueu7775zn3PNmzd3owB6r9KowNq1a93/vXv3drcfNGiQG5nUSXm0TgQjmEXgqBZ2woQJliFDBtuyZYvdeuutrrZRdY7K0Pbv398FJqpp0wseiK/5uMpP9AGhEoOXX37ZTSTUsJ2G9R588MFQ31lEN2W+9H7y/fff2+7du91IjwLWpUuXuiHeDh06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pUr2+eefuxpXNbH3XXXVVXb06FGbOHGi/fPPP26baiAV9I4cOdLVPgKxs/ZaKENdCXyql1XPWGVntfzxhg0bQtepT7GOL3XEAAAguVAzewFRltXvAbt69Wo3g7xy5cr22WefuW3Kqg0YMMCefPJJu/nmm11T+x49etjOnTttwYIFTPJCjMleOilSq63ly5fbAw88YLfddpvde++97jbqJ6uTpSpVqthTTz3l2nMBABAJZGYvEApI/UBWk72KFCniJuYoqNXMc9FscwW0c+fOtXr16rl2SgpcfvrpJxfIsrIXRIGsuhFoIYSSJUva888/b4sWLbLu3bvbhAkT3G203PGDDz7oAloFvLHLWgAASC5kZi8AyqBp+dl+/fq5oV/1kFV9rFZdmjFjhgtG1NT+008/dbffvn27W35US4+q/MAvNyAzC1m1apXVrVvXLZ7xxBNPuEU2dJxcdtllrh5WJ0H169d3t1Wmv3bt2q6TAQAAkUAwewGYN2+ey7SqbEATuTQJTBk1OXLkiFv8QAHttddeax9//PFpW3ghesS1ApyoDnbYsGHWrl07VzOr8oJq1aq5BTQU5CqgVe2svgcAINKIYAIejCgQ1aSv6tWru5KC66+/PlRuIBkyZHDXvf76665lUlw9Zglko4+OGwWymgyo42LZsmWh6/LkyWPPPfecy8SqtOCGG26w3r17W9myZd3XO3bscGUIyu5zLgwAiDSimIAHI34gevfdd9uYMWPc6ktdu3a1X375JXRblRto4s4rr7zilhmln2x08zPxmth1zz33uJMd1VWrS4HoZEhL1folB1deeaVlzpzZfa//Fehq0QSt8BVXZhcAgOREmUEAhZcFDB482DWwVx3jJZdcYj/++KPr+Vm+fHm3GpOyaaLyglq1asX5GIge/t996dKldtNNN7nFDmrUqGGTJ092LdoGDhzoul1oMqBauen63bt3u2BXJ0paDlkrgSl7CwBASkA0EzA69/CD0BdeeMEN/yqLpkldogBFPWM1+/zVV191XysQeeSRR2JkZAlko5P+7mvWrHHlAjoBUvnJ7bff7rKtooDVz85mypTJGjVq5CYH9u3b10001IVAFgCQkjB9PSA0kUv1r/6w7jvvvONW7lLtoupk/UB3//79dsstt9j48ePdpK+hQ4e6iWFbt251gUx8k34QHXRCM3r0aFcuoJITnxY70Opdf/zxh8vOql5WrblUvqJexeqOoQBXSyIDAJCSUGYQAA0aNHA9PVUm4AejrVu3dsO/qpPVBJ7vv//e1TFqUo6ytZp1rmztsWPH3IpMCmRpvwXZvHmzy7RqFa+mTZu6EyAdM+pQULp0aXcitHHjRrf0cdGiRd2x5vcqBgAgpSGyCQD18NREHVH2LF26dJYvXz57//33XfZViyToNqp9VGsutUxSNi1HjhwxMnIEshCd3HTo0MGt/qa+xCotmDlzpt1xxx3uep006VgZMmSIK1cpVKhQpHcZAIB4Ed0EYLJOz5493fdvvvmmy8yq/lXLi2ril8oMFLxqOLhYsWL23Xff2YoVK07pWECNLMLlypXLXnrpJXdczJkzxxYvXhwKZv1jR4smkM0HAKR0lBmkYH5Jgf+/Mq8KVLUkrcoOlKE9cOCA62IgCjw0HKzgQ0EutbE4E9VSK0OrDgX333+/64AhBLEAgKAgXZdChU/U2rRpk/v/s88+sxtvvNEFH6pr9ANZ/T9lyhSXnVWdo77Wfekni4RkaDt16uQmEWq5Y50oCYEsACAoCGZT8IIIMmHCBDfcq/6xoj6f5cqVsz59+tiHH37olhvVKk5awalw4cJusYSLLrrIZdYoLUBiAlodP3PnznXHEwAAQUGZQQoTvpiBAti33nrL9fasUqWK6wVaoUIFd13Dhg1tyZIlbiKPuh2oa4H6gioIVsP78CVtgYTQ5EHJmTNnpHcFAIAEI3WXwviBbNu2bV3bJC2IoKVoZ8yYYf379w9laJWx1SpfrVq1slmzZtnFF18cqq8lkMXZUBBLIAsACBoysymQAlZ1K5g6daqrkRWVFGhFryJFiriVv/wMbbdu3dysdAJYAAAQjZjlkQJp8o0ytOnTpw9tq1evnisfeOihh1zg+swzz7ila/0JO5QWAACAaESZQYT5ifHYCXJN4Pr7779DCyVI/fr1XS/Z5cuX29ixY0PXC4EsAACIRgSzKaRrgYJXX8WKFe2+++6zhx9+2DWzV3cC0Sxz1clq+6RJk2zhwoUR23cAAICUgJrZFNC1YNCgQfbtt9+67Gz+/PndRC91J1DHAk386tixo2XJksUthKAsrW6r9lyqm9WqYAAAANGKzGyE+IGsAtXu3bu7iV2XXXaZTZ482TWw11K1+vrZZ591rbnefvtt13pr5syZ7n6qpy1atGiEfwsAAIDIIjMbQb///rtbolbZ1apVq7pt69atc50MMmbMaPPmzXPbFNhmyJDBXeTll1+20aNHuwzt1VdfHdHfAQAAIJLIzEaQgtS9e/da8eLF3fc6ryhYsKCNGTPGNmzY4HrJSubMmV0gu3r1anviiSds5MiRbmlbAlkAABDtCGYjSEGsMrBTpkxx3/uTwfLmzeu279u3L0anghw5crgWXVpytEyZMhHccwAAgJSBPrMRmvSlLKzqXmvWrGmffvqpXXnlla71lqg2Nlu2bKEuBrqtAl1t07K2AAAA+D/UzCax2bNnu9pXrdIVO6CVFStWWKdOnVxZgbKt6lLwwQcf2M6dO11bLvrHAgAAxI9gNgkdPXrUWrVq5YLZxo0bu2VowwNaP+O6Zs0amzZtmr333nuWNWtWl6UdN26cy8yyshcAAED8CGaT2ObNm61v3742f/58u//++619+/YxFkwIXzTBD1rDt2lpWwAAAMSNCWBJLHfu3NahQwfXO3bq1KnWp08ft93PzMq2bdusadOmNnHixFAgq+sIZAEAAE6PzGwy2bp1q/Xo0cN+/vlnq127tgtwZcuWLa5Dwfbt213fWQJYAACAhCOYjVBAW6dOHXvkkUdcIKvM7JIlS6iRBQAASCSC2QgEtD179rQFCxbYypUrXRnC0qVLXSBLjSwAAEDiEMxGKKDVRLAdO3bYxx9/TCALAABwlghmI2T37t2uDZcmghHIAgAAnB2C2QiLvYgCAAAAEo5gFgAAAIFFShAAAACBRTALAACAwCKYBQAAQGARzAIAACCwCGYBAAAQWASzAAAACCyCWQAAAAQWwSwAAAACi2AWAAAAgUUwCwAAAAuq/weP8fQOrgSk1AAAAABJRU5ErkJggg==",
|
|
"text/plain": [
|
|
"<Figure size 800x500 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Cell 5: Compare ROC-AUC\n",
|
|
"scores = {k: v[\"roc_auc\"] for k, v in results.items()}\n",
|
|
"\n",
|
|
"plt.figure(figsize=(8,5))\n",
|
|
"sns.barplot(x=list(scores.keys()), y=list(scores.values()))\n",
|
|
"plt.title(\"Model Comparison by ROC-AUC Score\")\n",
|
|
"plt.ylabel(\"ROC-AUC\")\n",
|
|
"plt.xticks(rotation=45)\n",
|
|
"plt.show()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "830073d4",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Best model based on AUC-ROC: XGBoost\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Cell 6: Best Model Summary\n",
|
|
"best_model_name = max(scores, key=scores.get)\n",
|
|
"print(f\"Best model based on AUC-ROC: {best_model_name}\")\n",
|
|
"best_model = results[best_model_name][\"model\"]\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "fb18adc2",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".venv",
|
|
"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.4"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|