{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d8a8b207-e2a2-46f5-a6ab-2cba136c1a58",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Here we declare the libs that we want to use\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "fc86b9eb-5977-449d-9666-55cdff68058b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>bmi</th>\n",
       "      <th>glucose_level</th>\n",
       "      <th>physical_activity_level</th>\n",
       "      <th>family_history</th>\n",
       "      <th>smoker</th>\n",
       "      <th>at_risk_diabetes</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>58</td>\n",
       "      <td>33.154816</td>\n",
       "      <td>71.049867</td>\n",
       "      <td>low</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>71</td>\n",
       "      <td>26.786882</td>\n",
       "      <td>125.964887</td>\n",
       "      <td>low</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>48</td>\n",
       "      <td>20.977319</td>\n",
       "      <td>61.876196</td>\n",
       "      <td>moderate</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>34</td>\n",
       "      <td>27.959924</td>\n",
       "      <td>137.648074</td>\n",
       "      <td>low</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>62</td>\n",
       "      <td>28.304175</td>\n",
       "      <td>65.879564</td>\n",
       "      <td>moderate</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   age        bmi  glucose_level physical_activity_level  family_history  \\\n",
       "0   58  33.154816      71.049867                     low               0   \n",
       "1   71  26.786882     125.964887                     low               0   \n",
       "2   48  20.977319      61.876196                moderate               1   \n",
       "3   34  27.959924     137.648074                     low               0   \n",
       "4   62  28.304175      65.879564                moderate               0   \n",
       "\n",
       "   smoker  at_risk_diabetes  \n",
       "0       0                 1  \n",
       "1       0                 0  \n",
       "2       1                 0  \n",
       "3       0                 0  \n",
       "4       0                 0  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#To read the dataset we use lib pandas which have class to read csv data\n",
    "dt = pd.read_csv('diabetes.csv')\n",
    "#after reading we will need to see sample of that data \n",
    "#so that we will use the Head function which is available in pythohn\n",
    "dt.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "fb05b567-09e3-48bc-8417-a53f78be7a8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "age                          int64\n",
       "bmi                        float64\n",
       "glucose_level              float64\n",
       "physical_activity_level     object\n",
       "family_history               int64\n",
       "smoker                       int64\n",
       "at_risk_diabetes             int64\n",
       "dtype: object"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#dtypes functions used to get the data type of dataset\n",
    "dt.dtypes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "cc87b504-e4f2-449f-82d6-90ca40f0021c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>bmi</th>\n",
       "      <th>glucose_level</th>\n",
       "      <th>family_history</th>\n",
       "      <th>smoker</th>\n",
       "      <th>at_risk_diabetes</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>100000.000000</td>\n",
       "      <td>100000.000000</td>\n",
       "      <td>100000.000000</td>\n",
       "      <td>100000.000000</td>\n",
       "      <td>100000.000000</td>\n",
       "      <td>100000.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>49.545230</td>\n",
       "      <td>27.034009</td>\n",
       "      <td>101.274228</td>\n",
       "      <td>0.299320</td>\n",
       "      <td>0.202000</td>\n",
       "      <td>0.207310</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>17.310892</td>\n",
       "      <td>4.957869</td>\n",
       "      <td>27.608618</td>\n",
       "      <td>0.457962</td>\n",
       "      <td>0.401494</td>\n",
       "      <td>0.405382</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>20.000000</td>\n",
       "      <td>15.000000</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>35.000000</td>\n",
       "      <td>23.657095</td>\n",
       "      <td>79.809212</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>49.000000</td>\n",
       "      <td>27.002693</td>\n",
       "      <td>100.023378</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>65.000000</td>\n",
       "      <td>30.381817</td>\n",
       "      <td>120.199707</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>79.000000</td>\n",
       "      <td>45.000000</td>\n",
       "      <td>200.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 age            bmi  glucose_level  family_history  \\\n",
       "count  100000.000000  100000.000000  100000.000000   100000.000000   \n",
       "mean       49.545230      27.034009     101.274228        0.299320   \n",
       "std        17.310892       4.957869      27.608618        0.457962   \n",
       "min        20.000000      15.000000      60.000000        0.000000   \n",
       "25%        35.000000      23.657095      79.809212        0.000000   \n",
       "50%        49.000000      27.002693     100.023378        0.000000   \n",
       "75%        65.000000      30.381817     120.199707        1.000000   \n",
       "max        79.000000      45.000000     200.000000        1.000000   \n",
       "\n",
       "              smoker  at_risk_diabetes  \n",
       "count  100000.000000     100000.000000  \n",
       "mean        0.202000          0.207310  \n",
       "std         0.401494          0.405382  \n",
       "min         0.000000          0.000000  \n",
       "25%         0.000000          0.000000  \n",
       "50%         0.000000          0.000000  \n",
       "75%         0.000000          0.000000  \n",
       "max         1.000000          1.000000  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#to get more information about the data  we use descripe\n",
    "dt.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "bcab42e0-f428-47a8-bf73-55aa30b7117a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "age                        0\n",
       "bmi                        0\n",
       "glucose_level              0\n",
       "physical_activity_level    0\n",
       "family_history             0\n",
       "smoker                     0\n",
       "at_risk_diabetes           0\n",
       "dtype: int64"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#isnull is function we use it to know the missing fields in the dataset and we use sum to get total of them\n",
    "dt.isnull().sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "93a4f1b6-190e-40ce-a993-648a893193e0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 100000 entries, 0 to 99999\n",
      "Data columns (total 7 columns):\n",
      " #   Column                   Non-Null Count   Dtype  \n",
      "---  ------                   --------------   -----  \n",
      " 0   age                      100000 non-null  int64  \n",
      " 1   bmi                      100000 non-null  float64\n",
      " 2   glucose_level            100000 non-null  float64\n",
      " 3   physical_activity_level  100000 non-null  object \n",
      " 4   family_history           100000 non-null  int64  \n",
      " 5   smoker                   100000 non-null  int64  \n",
      " 6   at_risk_diabetes         100000 non-null  int64  \n",
      "dtypes: float64(2), int64(4), object(1)\n",
      "memory usage: 5.3+ MB\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# Check data types\n",
    "print(dt.info())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fa9887ae-f799-4a97-8e68-1c44f27c8cd0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split, GridSearchCV\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.svm import SVC\n",
    "from sklearn.naive_bayes import GaussianNB\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score,f1_score,classification_report\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import classification_report"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "98783513-27b9-483d-94cf-6ef63dadf388",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "at_risk_diabetes\n",
       "0    79269\n",
       "1    20731\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dt['at_risk_diabetes'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e048e4a1-8801-4d9c-8eea-9c422c0ecab3",
   "metadata": {},
   "outputs": [],
   "source": [
    "label_encoders = {}\n",
    "for column in dt.select_dtypes(include=['object']).columns:\n",
    "    le = LabelEncoder()\n",
    "    dt[column] = le.fit_transform(dt[column])\n",
    "    label_encoders[column] = le"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a5c4aff6-3225-4ed2-8b1f-8417bc1fa1ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>bmi</th>\n",
       "      <th>glucose_level</th>\n",
       "      <th>physical_activity_level</th>\n",
       "      <th>family_history</th>\n",
       "      <th>smoker</th>\n",
       "      <th>at_risk_diabetes</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>58</td>\n",
       "      <td>33.154816</td>\n",
       "      <td>71.049867</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>71</td>\n",
       "      <td>26.786882</td>\n",
       "      <td>125.964887</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>48</td>\n",
       "      <td>20.977319</td>\n",
       "      <td>61.876196</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>34</td>\n",
       "      <td>27.959924</td>\n",
       "      <td>137.648074</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>62</td>\n",
       "      <td>28.304175</td>\n",
       "      <td>65.879564</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   age        bmi  glucose_level  physical_activity_level  family_history  \\\n",
       "0   58  33.154816      71.049867                        1               0   \n",
       "1   71  26.786882     125.964887                        1               0   \n",
       "2   48  20.977319      61.876196                        2               1   \n",
       "3   34  27.959924     137.648074                        1               0   \n",
       "4   62  28.304175      65.879564                        2               0   \n",
       "\n",
       "   smoker  at_risk_diabetes  \n",
       "0       0                 1  \n",
       "1       0                 0  \n",
       "2       1                 0  \n",
       "3       0                 0  \n",
       "4       0                 0  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dt.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "493bb1d6-0b0d-4e61-87f9-db8e300fb342",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Preprocessing to separate the features and target variable from the dataset\n",
    "X = dt.drop('at_risk_diabetes', axis=1).values\n",
    "y = dt['at_risk_diabetes'].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7d1bf6a4-b2c3-4ccc-8aff-d6612059aba8",
   "metadata": {},
   "outputs": [],
   "source": [
    "### this query to divide the dataset to training and testing sets\n",
    "X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.30, random_state=42, stratify=y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "3e53a57b-a53b-4313-b16a-f73526045915",
   "metadata": {},
   "outputs": [],
   "source": [
    "### here our model evaluation method we will use Accuracy,Precision,Recall and F1 Score since our dataset classification\n",
    "def evaluate_model(model_name, y_true, y_pred):\n",
    "    # Calculate metrics\n",
    "    accuracy = accuracy_score(y_true, y_pred)\n",
    "    precision = precision_score(y_true, y_pred, average='weighted')\n",
    "    recall = recall_score(y_true, y_pred, average='weighted')\n",
    "    f1 = f1_score(y_true, y_pred, average='weighted')\n",
    "    cm = confusion_matrix(y_true, y_pred)\n",
    "    # Create a report\n",
    "    report = classification_report(y_true, y_pred)\n",
    "    # Output results\n",
    "    metrics = {\n",
    "        'Model Name': model_name,\n",
    "        'Accuracy': accuracy,\n",
    "        'Precision': precision,\n",
    "        'Recall': recall,\n",
    "        'F1 Score': f1,\n",
    "        'Classification Report': report\n",
    "    }\n",
    "        # Plot Confusion Matrix\n",
    "    plt.figure(figsize=(4, 4))\n",
    "    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False,\n",
    "    xticklabels=np.unique(y_true), yticklabels=np.unique(y_true))\n",
    "    plt.title(f'Confusion Matrix for {model_name}')\n",
    "    plt.xlabel('Predicted Label')\n",
    "    plt.ylabel('True Label')\n",
    "    plt.show()\n",
    "    return metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "101085b7-35c0-41fd-88da-6c42a3e0f28e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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YzuySpcuLXPnzpXMmTOb/orwaH+BXlirVKli3utw4k2bNpnPhkdrPVob+vXXX01nvy9XjUg7ul2KFi1qLrpaK4ioJqP9M66BAy5r164VG7///rtUrFhR2rdv756mNTFfWnPT2oorSOr3as1P+3x0gMK90g7cL0ZtId579dVXJWPGjGaklna2a6e4dih37txZjh49apbp0qWLjBw5UhYuXCg7d+40F9273QOi923oI15btWplPuNa57x588x8HVGmo7W0Ge706dOmRK81Aa0ZdOvWTWbNmmUu5ps3b5YJEyaY90pHSu3Zs0d69eplOuo/++yzSD9G9tixY6bJzfN1/vx50zGunfbLli2T3bt3S//+/WXDhg13fF6bqXR01/bt283IsYEDB0rHjh3F398/UmkH7lukelKAGOhsj8r848ePO82aNXMyZsxoOufz5s3rtG7d2rl48aK7c1070tOkSeOkTZvW6d69u1k+os52df36dadbt26moz558uRO/vz5nenTp7vnDxkyxMmaNavj5+dn0qW0w3/s2LGm8z9ZsmROpkyZnFq1ajm//vqr+3OLFy8269J0PvHEE2adkels12V8XzrQQDvKW7Ro4QQHB5tta9eundO7d2+nRIkSd+y3AQMGOBkyZDCd7Lp/9LMu90o7ne24XzyzHQBghaYtAIAVAgkAwAqBBABghUACALBCIAEAWCGQAACsEEgAAFYIJAAAKwQSAIAVAgkAwAqBBAAgNv4PiUcXVFZUANoAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 400x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "RandomForestClassifier\n",
      "Accuracy: 0.9174\n",
      "Precision: 0.9152\n",
      "Recall: 0.9174\n",
      "F1 Score: 0.9156\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.94      0.96      0.95     23781\n",
      "           1       0.84      0.75      0.79      6219\n",
      "\n",
      "    accuracy                           0.92     30000\n",
      "   macro avg       0.89      0.85      0.87     30000\n",
      "weighted avg       0.92      0.92      0.92     30000\n",
      "\n",
      "\n",
      "Best hyperparameters found:\n",
      "{'n_estimators': 100, 'min_samples_split': 2, 'min_samples_leaf': 4, 'max_features': 0.5, 'max_depth': 10}\n",
      "\n",
      "Time Taken : 18.18226933479309\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.model_selection import RandomizedSearchCV  # Faster than GridSearchCV\n",
    "import numpy as np\n",
    "\n",
    "# Define the Random Forest Classifier with warm_start for faster iterations\n",
    "rf_classifier = RandomForestClassifier(random_state=42, warm_start=True, n_jobs=-1)\n",
    "\n",
    "# Define optimized hyperparameter distributions for faster tuning\n",
    "param_dist = {\n",
    "    'n_estimators': [50, 100, 200],  # Much smaller range for speed\n",
    "    'max_depth': [None, 10, 20],  # Limited depth options\n",
    "    'min_samples_split': [2, 5, 10],  # Fewer options\n",
    "    'min_samples_leaf': [1, 2, 4],  # Fewer options\n",
    "    'max_features': ['sqrt', 0.5]  # Adding feature sampling for speed\n",
    "}\n",
    "\n",
    "# Initialize RandomizedSearchCV (faster than GridSearchCV)\n",
    "random_search = RandomizedSearchCV(\n",
    "    estimator=rf_classifier, \n",
    "    param_distributions=param_dist,\n",
    "    n_iter=10,  # Number of parameter combinations to try\n",
    "    cv=3, \n",
    "    scoring='accuracy',\n",
    "    n_jobs=-1,  # Use all cores\n",
    "    random_state=42\n",
    ")\n",
    "start_time= time.time()\n",
    "# Fit the Randomized Search to the training data\n",
    "random_search.fit(X_train, y_train)\n",
    "\n",
    "# Retrieve the best estimator\n",
    "best_rf_classifier = random_search.best_estimator_\n",
    "\n",
    "# Make predictions\n",
    "y_pred = best_rf_classifier.predict(X_test)\n",
    "\n",
    "# Evaluate (assuming evaluate_model exists)\n",
    "evaluation_results = evaluate_model('RandomForestClassifier', y_test, y_pred)\n",
    "end_time= time.time()\n",
    "# Print results\n",
    "for key, value in evaluation_results.items():\n",
    "    if key == 'Classification Report':\n",
    "        print(value)\n",
    "    else:\n",
    "        print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "\n",
    "print(\"\\nBest hyperparameters found:\")\n",
    "print(random_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a1e13c25-9b62-4657-a3d1-c42fafb47533",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 400x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "LogisticRegression\n",
      "Accuracy: 0.8514\n",
      "Precision: 0.8404\n",
      "Recall: 0.8514\n",
      "F1 Score: 0.8402\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.87      0.95      0.91     23781\n",
      "           1       0.71      0.48      0.57      6219\n",
      "\n",
      "    accuracy                           0.85     30000\n",
      "   macro avg       0.79      0.71      0.74     30000\n",
      "weighted avg       0.84      0.85      0.84     30000\n",
      "\n",
      "\n",
      "Best hyperparameters found by GridSearchCV:\n",
      "{'C': 0.01, 'max_iter': 100, 'solver': 'lbfgs'}\n",
      "\n",
      "Time Taken : 6.510556697845459\n"
     ]
    }
   ],
   "source": [
    "###LogisticRegression\n",
    "# Define the Logistic Regression model\n",
    "LR = LogisticRegression(random_state=42)\n",
    "# Define the hyperparameters for grid search\n",
    "param_grid = {\n",
    "    'C': [0.01, 0.1, 1, 10], # Regularization strength\n",
    "    'solver': ['liblinear', 'lbfgs'], # Solver type\n",
    "    'max_iter': [100, 200, 300] # Maximum iterations for convergence\n",
    "}\n",
    "# Initialize GridSearchCV\n",
    "start_time=time.time()\n",
    "grid_search = GridSearchCV(estimator=LR, param_grid=param_grid, cv=5, scoring='accuracy',n_jobs=-1)\n",
    "# Fit the grid search to the data\n",
    "grid_search.fit(X_train, y_train)\n",
    "# Get the best estimator from grid search\n",
    "best_LR = grid_search.best_estimator_\n",
    "# Make predictions using the best model\n",
    "y_pred = best_LR.predict(X_test)\n",
    "# Evaluate the model\n",
    "evaluation_results = evaluate_model('LogisticRegression', y_test, y_pred)\n",
    "\n",
    "end_time=time.time()\n",
    "# Print the evaluation results\n",
    "for key, value in evaluation_results.items():\n",
    "    if key == 'Classification Report':\n",
    "        print(value) # Print report separately for better readability\n",
    "    else:\n",
    "        print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "# Print the best hyperparameters found by grid search\n",
    "print(\"\\nBest hyperparameters found by GridSearchCV:\")\n",
    "print(grid_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "ddf29d81-5d79-4c0d-8f42-daa08fe038b8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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LGmOVV9/4403JF++fKYLKS70WHv27CkffPCBdOnSxSzTbintx61Zs2a09Q8ePGgG+rV7UPer/b6vvvqqNGnSRH755RcpVKiQVKxY0Rxz1K4Gz8/y7Nmz5ji1Oa3dAPnz5/eZPh2b+vrrr83npN0Z2l2n+9MuAh2D0P35omnQ1/UzLFKkiLtbKG/evCZPtWtBP49nn33WHId2E2kZ0L7qvn37em1Lu9K0ea/Hop9jrly55FZoGXrooYfkzTffNHmlZU3pmJyOq3Tu3Fmee+45003zyiuvyI4dO0x50W5KpevoZ6TvCw0NNWVU1/n888/liSee8LnPL7/80pThZs2aucuEnhO63ajH6cmVHu1K1LKln7N+Fvo+3afu2yUiIkJatGgh9erVM+NbWoanTJliupV0rCg+nnnmGfMZadm5cuWKWaafo37+ug89hrCwMJk7d640atTIpMV1Tug5p+dJ4cKFZfDgwWYMYtmyZWbwV7utNe/VypUrJVOmTOYacCsuXbpkzjPN1+7du5uuRv1MNX2bN2+W6tWrxznv9RzX/NXrV926dc22tStMz+V77rkn2r41bzQ/dBxVu9D0va7y7ot+btoVq2NCWtb1/Z999pm59um+ok74GD16tOmO1G5n7SKPU3ew40cXL140UU5rKnGhtVpdv1u3bl7LBw4caJZ7RnytdemytWvXupedOnXKRHWtDfmqVXqKa8tCa4r6/PTp0zGm21fLonr16qYGoDV4l127dpkardayo+5Pa8eeHnroIVMLtHHVCNXDDz/sNGvWzF3LLVCggDNy5EifeaAttahNU11P809bdnHpatBamr42b948n69FbfKvXr3arD9mzBh396SvrrO41vS1ZqfbW7x4sVcNr379+mbbly5dch+Xrqe1Ry0jt7o/T65y4artagvXVy33888/91p+4cIFUzOtV6+e6R7w5NlKiVo+tcWm6Y+plu+rZaF5oWVQa8Ge+1q1apVZb9iwYV7702Wen72qUaOGqdXHt2WhNXTPtGprTFsY3bt3j9ZVpK1pz+VahqtUqeLVm6B506BBA9Ot6qKtjmrVqjlxFbVMavqidkWeP3/edGt5no9xyXtNh62b1Fevhat1HlXUlkXXrl2dggULOmfOnPFa7/HHHzf5p92jnmVAW8+uZXHl19lQGvFUtmzZ4rT+p59+av7279/fa7mr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",
      "text/plain": [
       "<Figure size 400x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "DecisionTreeClassifier\n",
      "Accuracy: 0.9132\n",
      "Precision: 0.9107\n",
      "Recall: 0.9132\n",
      "F1 Score: 0.9112\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.93      0.96      0.95     23781\n",
      "           1       0.83      0.73      0.78      6219\n",
      "\n",
      "    accuracy                           0.91     30000\n",
      "   macro avg       0.88      0.85      0.86     30000\n",
      "weighted avg       0.91      0.91      0.91     30000\n",
      "\n",
      "\n",
      "Best hyperparameters found by GridSearchCV:\n",
      "{'criterion': 'entropy', 'max_depth': 10, 'max_features': None, 'min_samples_leaf': 4, 'min_samples_split': 10}\n",
      "\n",
      "Time Taken : 12.237826108932495\n"
     ]
    }
   ],
   "source": [
    "# Define the Decision Tree model\n",
    "DT = DecisionTreeClassifier(random_state=42)\n",
    "# Define the hyperparameters for grid search\n",
    "param_grid = {\n",
    "'criterion': ['gini', 'entropy'], \n",
    "'max_depth': [None, 10, 20, 30],\n",
    "'min_samples_split': [2, 5, 10],\n",
    "'min_samples_leaf': [1, 2, 4], \n",
    "'max_features': [None, 'sqrt', 'log2']\n",
    "}\n",
    "# Initialize GridSearchCV\n",
    "start_time= time.time()\n",
    "grid_search = GridSearchCV(estimator=DT, param_grid=param_grid, cv=5, scoring='accuracy',n_jobs=-1)\n",
    "# Fit the grid search to the data\n",
    "grid_search.fit(X_train, y_train)\n",
    "# Get the best estimator from grid search\n",
    "best_DT = grid_search.best_estimator_\n",
    "# Make predictions using the best model\n",
    "y_pred = best_DT.predict(X_test)\n",
    "# Evaluate the model\n",
    "evaluation_results = evaluate_model('DecisionTreeClassifier', y_test, y_pred)\n",
    "end_time= time.time()\n",
    "# Print the evaluation results\n",
    "for key, value in evaluation_results.items():\n",
    "    if key == 'Classification Report':\n",
    "        print(value) # Print report separately for better readability\n",
    "    else:\n",
    "        print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "# Print the best hyperparameters found by grid search\n",
    "print(\"\\nBest hyperparameters found by GridSearchCV:\")\n",
    "print(grid_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "1f44ff47-797f-4968-b0d5-a99126b58549",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 400x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "Gaussian Naive Bayes\n",
      "Accuracy: 0.8560\n",
      "Precision: 0.8478\n",
      "Recall: 0.8560\n",
      "F1 Score: 0.8390\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.87      0.97      0.91     23781\n",
      "           1       0.78      0.43      0.55      6219\n",
      "\n",
      "    accuracy                           0.86     30000\n",
      "   macro avg       0.82      0.70      0.73     30000\n",
      "weighted avg       0.85      0.86      0.84     30000\n",
      "\n",
      "\n",
      "Best hyperparameters found by GridSearchCV:\n",
      "{'var_smoothing': 1e-09}\n",
      "\n",
      "Time Taken : 0.2773256301879883\n"
     ]
    }
   ],
   "source": [
    "# Define the Gaussian Naive Bayes model\n",
    "gnb = GaussianNB()\n",
    "# Define the hyperparameters for grid search\n",
    "param_grid = {\n",
    "    'var_smoothing': [1e-9, 1e-8, 1e-7, 1e-6] # Smoothing parameter\n",
    "}\n",
    "# Initialize GridSearchCV\n",
    "start_time= time.time()\n",
    "grid_search = GridSearchCV(estimator=gnb, param_grid=param_grid, cv=5, scoring='accuracy',n_jobs=-1)\n",
    "# Fit the grid search to the data\n",
    "grid_search.fit(X_train, y_train)\n",
    "# Get the best estimator from grid search\n",
    "best_gnb = grid_search.best_estimator_\n",
    "# Make predictions using the best model\n",
    "y_pred = best_gnb.predict(X_test)\n",
    "# Evaluate the model\n",
    "evaluation_results = evaluate_model('Gaussian Naive Bayes', y_test, y_pred)\n",
    "end_time= time.time()\n",
    "# Print the evaluation results\n",
    "for key, value in evaluation_results.items():\n",
    "    if key == 'Classification Report':\n",
    "        print(value) # Print report separately for better readability\n",
    "    else:\n",
    "        print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "# Print the best hyperparameters found by grid search\n",
    "print(\"\\nBest hyperparameters found by GridSearchCV:\")\n",
    "print(grid_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8d692b25-89b9-420b-8462-54e00ce17cf8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 400x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "K-Nearest Neighbors\n",
      "Accuracy: 0.9030\n",
      "Precision: 0.8996\n",
      "Recall: 0.9030\n",
      "F1 Score: 0.8998\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.92      0.96      0.94     23781\n",
      "           1       0.82      0.69      0.75      6219\n",
      "\n",
      "    accuracy                           0.90     30000\n",
      "   macro avg       0.87      0.82      0.84     30000\n",
      "weighted avg       0.90      0.90      0.90     30000\n",
      "\n",
      "\n",
      "Best hyperparameters found by GridSearchCV:\n",
      "{'algorithm': 'auto', 'metric': 'manhattan', 'n_neighbors': 9, 'weights': 'uniform'}\n",
      "\n",
      "Time Taken : 58.3023943901062\n"
     ]
    }
   ],
   "source": [
    "# Define the K-Nearest Neighbors model\n",
    "knn = KNeighborsClassifier()\n",
    "# Define the hyperparameters for grid search\n",
    "param_grid = {\n",
    "    'n_neighbors': [1, 3, 5, 7, 9], # Number of neighbors to use\n",
    "    'weights': ['uniform', 'distance'], # Weight function used in prediction\n",
    "    'metric': ['euclidean', 'manhattan'], # Distance metric\n",
    "    'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute'] # Algorithm to compute\n",
    "}\n",
    "# Initialize GridSearchCV\n",
    "start_time= time.time()\n",
    "grid_search = GridSearchCV(estimator=knn, param_grid=param_grid, cv=5, scoring='accuracy',n_jobs=-1)\n",
    "# Fit the grid search to the data\n",
    "grid_search.fit(X_train, y_train)\n",
    "# Get the best estimator from grid search\n",
    "best_knn = grid_search.best_estimator_\n",
    "# Make predictions using the best model\n",
    "y_pred = best_knn.predict(X_test)\n",
    "# Evaluate the model\n",
    "evaluation_results = evaluate_model('K-Nearest Neighbors', y_test, y_pred)\n",
    "end_time= time.time()\n",
    "# Print the evaluation results\n",
    "for key, value in evaluation_results.items():\n",
    "    if key == 'Classification Report':\n",
    "        print(value) # Print report separately for better readability\n",
    "    else:\n",
    "        print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "# Print the best hyperparameters found by grid search\n",
    "print(\"\\nBest hyperparameters found by GridSearchCV:\")\n",
    "print(grid_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "d945bbc8-64e0-443e-9e8a-cf0295585306",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.datasets import load_iris\n",
    "from sklearn.feature_selection import SelectKBest, chi2, RFE\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.svm import SVC\n",
    "from sklearn.naive_bayes import GaussianNB\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.metrics import (\n",
    "    confusion_matrix,\n",
    "    accuracy_score,\n",
    "    precision_score,\n",
    "    recall_score,\n",
    "    f1_score,\n",
    "    classification_report\n",
    ")\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "4bdcdaa2-9cc7-44c7-a8d9-6a7fed61c51f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>bmi</th>\n",
       "      <th>glucose_level</th>\n",
       "      <th>physical_activity_level</th>\n",
       "      <th>family_history</th>\n",
       "      <th>smoker</th>\n",
       "      <th>at_risk_diabetes</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>58</td>\n",
       "      <td>33.154816</td>\n",
       "      <td>71.049867</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>71</td>\n",
       "      <td>26.786882</td>\n",
       "      <td>125.964887</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>48</td>\n",
       "      <td>20.977319</td>\n",
       "      <td>61.876196</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>34</td>\n",
       "      <td>27.959924</td>\n",
       "      <td>137.648074</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>62</td>\n",
       "      <td>28.304175</td>\n",
       "      <td>65.879564</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   age        bmi  glucose_level  physical_activity_level  family_history  \\\n",
       "0   58  33.154816      71.049867                        1               0   \n",
       "1   71  26.786882     125.964887                        1               0   \n",
       "2   48  20.977319      61.876196                        2               1   \n",
       "3   34  27.959924     137.648074                        1               0   \n",
       "4   62  28.304175      65.879564                        2               0   \n",
       "\n",
       "   smoker  at_risk_diabetes  \n",
       "0       0                 1  \n",
       "1       0                 0  \n",
       "2       1                 0  \n",
       "3       0                 0  \n",
       "4       0                 0  "
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.read_csv('diabetes.csv')\n",
    "label_encoders = {}\n",
    "for column in data.select_dtypes(include=['object']).columns:\n",
    "    le = LabelEncoder()\n",
    "    data[column] = le.fit_transform(data[column])\n",
    "    label_encoders[column] = le\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "6453bbcb-b319-4d6b-a217-a2cbb7efcdf0",
   "metadata": {},
   "outputs": [],
   "source": [
    "X1 = data.drop('at_risk_diabetes', axis=1)\n",
    "y1 = data['at_risk_diabetes']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "0cdd6825-dcb9-451b-bf9b-7baed458f154",
   "metadata": {},
   "outputs": [],
   "source": [
    "###Split dataset into train and test sets\n",
    "X_train, X_test, y_train, y_test = train_test_split(X1, y1,test_size=0.2, random_state=42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "97655de1-4441-4c60-9465-1423bf1be72d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Feature</th>\n",
       "      <th>Score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>age</td>\n",
       "      <td>28544.583486</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>bmi</td>\n",
       "      <td>11308.745838</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>glucose_level</td>\n",
       "      <td>25493.940627</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>physical_activity_level</td>\n",
       "      <td>16.499958</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>family_history</td>\n",
       "      <td>927.736741</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>smoker</td>\n",
       "      <td>858.755429</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                   Feature         Score\n",
       "0                      age  28544.583486\n",
       "1                      bmi  11308.745838\n",
       "2            glucose_level  25493.940627\n",
       "3  physical_activity_level     16.499958\n",
       "4           family_history    927.736741\n",
       "5                   smoker    858.755429"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "###Feature Selection Methods\n",
    "###1. Filter Method (Chi-Square Test)\n",
    "select_feature = SelectKBest(chi2,k=min(6,8)).fit(X_train, y_train)\n",
    "dt = pd.DataFrame([])\n",
    "dt._append(pd.DataFrame({'Feature': X1.columns, 'Score': select_feature .scores_}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "a286d612-92af-44ae-ab43-4ce6ad23fc3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train_selected = select_feature.transform(X_train)\n",
    "X_test_selected = select_feature.transform(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "5eabbefc-79e6-4655-8694-c884e2a2679d",
   "metadata": {},
   "outputs": [],
   "source": [
    "###Applying RF on selected features\n",
    "def evaluate_model(model_name, y_true, y_pred):\n",
    "    # Calculate metrics\n",
    "    accuracy = accuracy_score(y_true, y_pred)\n",
    "    precision = precision_score(y_true, y_pred, average='weighted')\n",
    "    recall = recall_score(y_true, y_pred, average='weighted')\n",
    "    f1 = f1_score(y_true, y_pred, average='weighted')\n",
    "    # Output results\n",
    "    metrics = {\n",
    "        'Model Name': model_name,\n",
    "        'Accuracy': accuracy,\n",
    "        'Precision': precision,\n",
    "        'Recall': recall,\n",
    "        'F1 Score': f1,\n",
    "    }\n",
    "    return metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "dbfa69a0-b1a6-4f29-b0fe-5370adfb06b7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "RandomForestClassifier\n",
      "Accuracy: 0.9176\n",
      "Precision: 0.9153\n",
      "Recall: 0.9176\n",
      "F1 Score: 0.9157\n",
      "\n",
      "Best hyperparameters found by GridSearchCV:\n",
      "{'max_depth': 10, 'min_samples_leaf': 2, 'min_samples_split': 5, 'n_estimators': 100}\n",
      "\n",
      "Time Taken : 539.6843228340149\n"
     ]
    }
   ],
   "source": [
    "###RandomForestClassifier\n",
    "# Define the Random Forest Classifier\n",
    "rf_classifier = RandomForestClassifier(random_state=42)\n",
    "# Define the hyperparameters for grid search\n",
    "param_grid = {\n",
    "    'n_estimators': [100, 200, 300],\n",
    "    'max_depth': [None, 10, 20, 30],\n",
    "    'min_samples_split': [2, 5, 10],\n",
    "    'min_samples_leaf': [1, 2, 4]\n",
    "}\n",
    "# Initialize GridSearchCV\n",
    "start_time= time.time()\n",
    "grid_search = GridSearchCV(estimator=rf_classifier,\n",
    "param_grid=param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
    "# Fit the grid search to the data\n",
    "grid_search.fit(X_train_selected, y_train)\n",
    "# Get the best estimator from grid search\n",
    "best_rf_classifier = grid_search.best_estimator_\n",
    "# Make predictions using the best model\n",
    "y_pred = best_rf_classifier.predict(X_test_selected)\n",
    "# Evaluate the model\n",
    "evaluation_results = evaluate_model('RandomForestClassifier', y_test, y_pred)\n",
    "end_time= time.time()\n",
    "# Print the evaluation results\n",
    "for key, value in evaluation_results.items():\n",
    "    print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "# Print the best parameters found by grid search\n",
    "print(\"\\nBest hyperparameters found by GridSearchCV:\")\n",
    "print(grid_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "954b713d-30d4-4176-9863-296d659650a9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selected Features (RFE): [0 1 2 3 4 5]\n"
     ]
    }
   ],
   "source": [
    "###2. Wrapper Method (Recursive Feature Elimination - RFE\n",
    "from sklearn.feature_selection import RFE\n",
    "clf_rf_2 = RandomForestClassifier(random_state=43)\n",
    "rfe_selector =RFE(estimator=clf_rf_2, n_features_to_select=min(6,8)) #in here i modifed the n_features_to_select to min (6,8) because my dataset with 7 columns only\n",
    "\n",
    "X_train_selected_rfe = rfe_selector.fit_transform(X_train, y_train)\n",
    "X_test_selected_rfe = rfe_selector.transform(X_test)\n",
    "# Get the selected feature indices\n",
    "selected_features = rfe_selector.get_support(indices=True)\n",
    "print(\"Selected Features (RFE):\", selected_features)###Applying RF on selected features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "7e0dcb3f-3230-4c6f-81b9-3ab100677875",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Name: \n",
      "RandomForestClassifier\n",
      "Accuracy: 0.9176\n",
      "Precision: 0.9153\n",
      "Recall: 0.9176\n",
      "F1 Score: 0.9157\n",
      "\n",
      "Best hyperparameters found by GridSearchCV:\n",
      "{'max_depth': 10, 'min_samples_leaf': 2, 'min_samples_split': 5, 'n_estimators': 100}\n",
      "\n",
      "Time Taken : 564.0279126167297\n"
     ]
    }
   ],
   "source": [
    "###Applying RF on selected features\n",
    "# Define the Random Forest Classifier\n",
    "rf_classifier = RandomForestClassifier(random_state=42)\n",
    "# Define the hyperparameters for grid search\n",
    "param_grid = {\n",
    "    'n_estimators': [100, 200, 300],\n",
    "    'max_depth': [None, 10, 20, 30],\n",
    "    'min_samples_split': [2, 5, 10],\n",
    "    'min_samples_leaf': [1, 2, 4]\n",
    "}\n",
    "# Initialize GridSearchCV\n",
    "start_time= time.time()\n",
    "grid_search = GridSearchCV(estimator=rf_classifier,\n",
    "param_grid=param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
    "# Fit the grid search to the data\n",
    "grid_search.fit(X_train_selected_rfe, y_train)\n",
    "# Get the best estimator from grid search\n",
    "best_rf_classifier = grid_search.best_estimator_\n",
    "# Make predictions using the best model\n",
    "y_pred = best_rf_classifier.predict(X_test_selected_rfe)\n",
    "# Evaluate the model\n",
    "evaluation_results = evaluate_model('RandomForestClassifier', y_test, y_pred)\n",
    "end_time= time.time()\n",
    "# Print the evaluation results\n",
    "for key, value in evaluation_results.items():\n",
    "    print(f\"{key}: {value:.4f}\" if isinstance(value, float) else f\"{key}: \\n{value}\")\n",
    "# Print the best parameters found by grid search\n",
    "print(\"\\nBest hyperparameters found by GridSearchCV:\")\n",
    "print(grid_search.best_params_)\n",
    "print (\"\\nTime Taken : \"+ format(end_time-start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d27748fa-85fe-4c77-a260-f1b2d5e87d33",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
