{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e46934d2-da89-44cb-a2e2-0491b10c1350",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "# from sklearn.metrics import confusion_matrix, roc_curve, roc_auc_score, RocCurveDisplay\n",
    "from sklearn.metrics import confusion_matrix, recall_score, precision_score, roc_auc_score, roc_curve, accuracy_score, RocCurveDisplay\n",
    "\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a320a6f1-c80e-4e53-959d-ddf3488f9302",
   "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>Enroll</th>\n",
       "      <th>Age</th>\n",
       "      <th>Income</th>\n",
       "      <th>Hours</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>26</td>\n",
       "      <td>18000</td>\n",
       "      <td>14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>43</td>\n",
       "      <td>13000</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>55</td>\n",
       "      <td>42000</td>\n",
       "      <td>16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>55</td>\n",
       "      <td>100000</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>55</td>\n",
       "      <td>13000</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Enroll  Age  Income  Hours\n",
       "0       1   26   18000     14\n",
       "1       0   43   13000      9\n",
       "2       1   55   42000     16\n",
       "3       1   55  100000     13\n",
       "4       0   55   13000     12"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Load the data\n",
    "gymEnrollAgeIncomeHoursDf = pd.read_excel(\"gym.xlsx\")\n",
    "gymEnrollAgeIncomeHoursDf.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5c204cb7-ccaa-4f83-8d44-92adc224e876",
   "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>Enroll</th>\n",
       "      <th>Age</th>\n",
       "      <th>Income</th>\n",
       "      <th>Hours</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>1000.000000</td>\n",
       "      <td>1000.000000</td>\n",
       "      <td>1000.000000</td>\n",
       "      <td>1000.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0.403000</td>\n",
       "      <td>44.582000</td>\n",
       "      <td>68340.000000</td>\n",
       "      <td>10.182000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0.490746</td>\n",
       "      <td>13.876737</td>\n",
       "      <td>44466.928247</td>\n",
       "      <td>4.671263</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>21.000000</td>\n",
       "      <td>1000.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>32.000000</td>\n",
       "      <td>31000.000000</td>\n",
       "      <td>6.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>45.000000</td>\n",
       "      <td>64000.000000</td>\n",
       "      <td>10.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>57.000000</td>\n",
       "      <td>97000.000000</td>\n",
       "      <td>14.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>68.000000</td>\n",
       "      <td>198000.000000</td>\n",
       "      <td>18.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            Enroll          Age         Income        Hours\n",
       "count  1000.000000  1000.000000    1000.000000  1000.000000\n",
       "mean      0.403000    44.582000   68340.000000    10.182000\n",
       "std       0.490746    13.876737   44466.928247     4.671263\n",
       "min       0.000000    21.000000    1000.000000     2.000000\n",
       "25%       0.000000    32.000000   31000.000000     6.000000\n",
       "50%       0.000000    45.000000   64000.000000    10.000000\n",
       "75%       1.000000    57.000000   97000.000000    14.000000\n",
       "max       1.000000    68.000000  198000.000000    18.000000"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gymEnrollAgeIncomeHoursDf.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92b6d925-f586-45a6-b89a-3b74204f0b94",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "70586f38-33be-49c7-93c0-867a24de8aa9",
   "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>Enroll</th>\n",
       "      <th>Age</th>\n",
       "      <th>Income</th>\n",
       "      <th>Hours</th>\n",
       "      <th>scalerAge</th>\n",
       "      <th>scalerIncome</th>\n",
       "      <th>scalerHours</th>\n",
       "      <th>EnrollCategories</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>26</td>\n",
       "      <td>18000</td>\n",
       "      <td>14</td>\n",
       "      <td>-1.339746</td>\n",
       "      <td>-1.132644</td>\n",
       "      <td>0.817747</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>43</td>\n",
       "      <td>13000</td>\n",
       "      <td>9</td>\n",
       "      <td>-0.114061</td>\n",
       "      <td>-1.245143</td>\n",
       "      <td>-0.253163</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>55</td>\n",
       "      <td>42000</td>\n",
       "      <td>16</td>\n",
       "      <td>0.751128</td>\n",
       "      <td>-0.592647</td>\n",
       "      <td>1.246111</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>55</td>\n",
       "      <td>100000</td>\n",
       "      <td>13</td>\n",
       "      <td>0.751128</td>\n",
       "      <td>0.712346</td>\n",
       "      <td>0.603565</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>55</td>\n",
       "      <td>13000</td>\n",
       "      <td>12</td>\n",
       "      <td>0.751128</td>\n",
       "      <td>-1.245143</td>\n",
       "      <td>0.389383</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>995</th>\n",
       "      <td>0</td>\n",
       "      <td>39</td>\n",
       "      <td>5000</td>\n",
       "      <td>13</td>\n",
       "      <td>-0.402457</td>\n",
       "      <td>-1.425142</td>\n",
       "      <td>0.603565</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>996</th>\n",
       "      <td>0</td>\n",
       "      <td>38</td>\n",
       "      <td>5000</td>\n",
       "      <td>3</td>\n",
       "      <td>-0.474556</td>\n",
       "      <td>-1.425142</td>\n",
       "      <td>-1.538255</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>997</th>\n",
       "      <td>1</td>\n",
       "      <td>55</td>\n",
       "      <td>70000</td>\n",
       "      <td>17</td>\n",
       "      <td>0.751128</td>\n",
       "      <td>0.037350</td>\n",
       "      <td>1.460293</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>998</th>\n",
       "      <td>1</td>\n",
       "      <td>68</td>\n",
       "      <td>64000</td>\n",
       "      <td>15</td>\n",
       "      <td>1.688417</td>\n",
       "      <td>-0.097649</td>\n",
       "      <td>1.031929</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>999</th>\n",
       "      <td>0</td>\n",
       "      <td>48</td>\n",
       "      <td>67000</td>\n",
       "      <td>18</td>\n",
       "      <td>0.246435</td>\n",
       "      <td>-0.030150</td>\n",
       "      <td>1.674475</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1000 rows × 8 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     Enroll  Age  Income  Hours  scalerAge  scalerIncome  scalerHours  \\\n",
       "0         1   26   18000     14  -1.339746     -1.132644     0.817747   \n",
       "1         0   43   13000      9  -0.114061     -1.245143    -0.253163   \n",
       "2         1   55   42000     16   0.751128     -0.592647     1.246111   \n",
       "3         1   55  100000     13   0.751128      0.712346     0.603565   \n",
       "4         0   55   13000     12   0.751128     -1.245143     0.389383   \n",
       "..      ...  ...     ...    ...        ...           ...          ...   \n",
       "995       0   39    5000     13  -0.402457     -1.425142     0.603565   \n",
       "996       0   38    5000      3  -0.474556     -1.425142    -1.538255   \n",
       "997       1   55   70000     17   0.751128      0.037350     1.460293   \n",
       "998       1   68   64000     15   1.688417     -0.097649     1.031929   \n",
       "999       0   48   67000     18   0.246435     -0.030150     1.674475   \n",
       "\n",
       "    EnrollCategories  \n",
       "0                  1  \n",
       "1                  0  \n",
       "2                  1  \n",
       "3                  1  \n",
       "4                  0  \n",
       "..               ...  \n",
       "995                0  \n",
       "996                0  \n",
       "997                1  \n",
       "998                1  \n",
       "999                0  \n",
       "\n",
       "[1000 rows x 8 columns]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Scale the features\n",
    "scalerAge = StandardScaler()\n",
    "gymEnrollAgeIncomeHoursDf['scalerAge'] = scalerAge.fit_transform(gymEnrollAgeIncomeHoursDf[[\"Age\"]])\n",
    "scalerIncome = StandardScaler()\n",
    "gymEnrollAgeIncomeHoursDf['scalerIncome'] = scalerAge.fit_transform(gymEnrollAgeIncomeHoursDf[[\"Income\"]])\n",
    "scalerHours = StandardScaler()\n",
    "gymEnrollAgeIncomeHoursDf['scalerHours'] = scalerAge.fit_transform(gymEnrollAgeIncomeHoursDf[[\"Hours\"]])\n",
    "gymEnrollAgeIncomeHoursDf['EnrollCategories'] = gymEnrollAgeIncomeHoursDf['Enroll'].astype('category')\n",
    "gymEnrollAgeIncomeHoursDf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "dcbdbd6a-0569-454d-8f26-4cf7e5c7032d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# testTransformer = pd.DataFrame([[26], [43], [55]], columns=['Age'])\n",
    "# scalerAge.transform(tt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "c3add96b-f801-4b29-87d8-77dc8057c721",
   "metadata": {},
   "outputs": [],
   "source": [
    "indAtts = [\"scalerAge\", \"scalerIncome\", \"scalerHours\"]\n",
    "depAtt = \"EnrollCategories\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2285e5a5-0a99-4589-b965-3267a543de5e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Split the data into training and testing sets\n",
    "(gymEnrollAgeIncomeHoursDfX_train,\n",
    "gymEnrollAgeIncomeHoursDfX_test,\n",
    "gymEnrollAgeIncomeHoursDfy_train,\n",
    "gymEnrollAgeIncomeHoursDfy_test) = train_test_split(\n",
    "    gymEnrollAgeIncomeHoursDf[indAtts],\n",
    "    gymEnrollAgeIncomeHoursDf[depAtt],\n",
    "    test_size=0.4,\n",
    "    random_state=1,\n",
    "    stratify=gymEnrollAgeIncomeHoursDf[depAtt]\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "550ac433-5d99-46de-9620-7ef93e79fcbe",
   "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>scalerAge</th>\n",
       "      <th>scalerIncome</th>\n",
       "      <th>scalerHours</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>808</th>\n",
       "      <td>0.030137</td>\n",
       "      <td>0.824845</td>\n",
       "      <td>1.674475</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>393</th>\n",
       "      <td>-0.618755</td>\n",
       "      <td>-0.975145</td>\n",
       "      <td>0.175201</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>416</th>\n",
       "      <td>-0.979250</td>\n",
       "      <td>-1.425142</td>\n",
       "      <td>0.817747</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>486</th>\n",
       "      <td>0.679029</td>\n",
       "      <td>-1.065144</td>\n",
       "      <td>0.817747</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>422</th>\n",
       "      <td>-0.114061</td>\n",
       "      <td>-1.267643</td>\n",
       "      <td>-1.324073</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     scalerAge  scalerIncome  scalerHours\n",
       "808   0.030137      0.824845     1.674475\n",
       "393  -0.618755     -0.975145     0.175201\n",
       "416  -0.979250     -1.425142     0.817747\n",
       "486   0.679029     -1.065144     0.817747\n",
       "422  -0.114061     -1.267643    -1.324073"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gymEnrollAgeIncomeHoursDfX_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "5799c2d6-26f6-483a-9632-42ae9ca6cf05",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>GridSearchCV(cv=5, estimator=CustomKNNClassifier(),\n",
       "             param_grid={&#x27;n_neighbors&#x27;: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" ><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;GridSearchCV<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.model_selection.GridSearchCV.html\">?<span>Documentation for GridSearchCV</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>GridSearchCV(cv=5, estimator=CustomKNNClassifier(),\n",
       "             param_grid={&#x27;n_neighbors&#x27;: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})</pre></div> </div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">best_estimator_: CustomKNNClassifier</label><div class=\"sk-toggleable__content fitted\"><pre>CustomKNNClassifier()</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">CustomKNNClassifier</label><div class=\"sk-toggleable__content fitted\"><pre>CustomKNNClassifier()</pre></div> </div></div></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "GridSearchCV(cv=5, estimator=CustomKNNClassifier(),\n",
       "             param_grid={'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Perform k-NN classification with cross-validation to find the best k\n",
    "class CustomKNNClassifier(KNeighborsClassifier):\n",
    "    def prob(self, X):\n",
    "        return self.predict_proba(X)[:, 1]\n",
    "# gymEnrollAgeIncomeHoursDfKnn = KNeighborsClassifier()\n",
    "gymEnrollAgeIncomeHoursDfKnn = CustomKNNClassifier()\n",
    "param_grid = {'n_neighbors': list(range(1, 11))}\n",
    "grid_search = GridSearchCV(gymEnrollAgeIncomeHoursDfKnn, param_grid, cv=5)\n",
    "grid_search.fit(gymEnrollAgeIncomeHoursDfX_train, gymEnrollAgeIncomeHoursDfy_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d89ab3d4-4fe5-482c-b447-3334a69b28e2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "bestParameters: {'n_neighbors': 5}\n",
      "bestCrossValidationScore: 0.915\n"
     ]
    }
   ],
   "source": [
    "bestParameters = grid_search.best_params_\n",
    "bestCrossValidationScore = grid_search.best_score_\n",
    "print(\"bestParameters:\", bestParameters)\n",
    "print(\"bestCrossValidationScore:\", bestCrossValidationScore)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "18fee4f2-df43-4d0f-a1be-1b0b2458f30a",
   "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>mean_fit_time</th>\n",
       "      <th>std_fit_time</th>\n",
       "      <th>mean_score_time</th>\n",
       "      <th>std_score_time</th>\n",
       "      <th>param_n_neighbors</th>\n",
       "      <th>params</th>\n",
       "      <th>split0_test_score</th>\n",
       "      <th>split1_test_score</th>\n",
       "      <th>split2_test_score</th>\n",
       "      <th>split3_test_score</th>\n",
       "      <th>split4_test_score</th>\n",
       "      <th>mean_test_score</th>\n",
       "      <th>std_test_score</th>\n",
       "      <th>rank_test_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.001510</td>\n",
       "      <td>0.000931</td>\n",
       "      <td>0.004020</td>\n",
       "      <td>0.000658</td>\n",
       "      <td>1</td>\n",
       "      <td>{'n_neighbors': 1}</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.908333</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.900000</td>\n",
       "      <td>0.916667</td>\n",
       "      <td>0.891667</td>\n",
       "      <td>0.021082</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000738</td>\n",
       "      <td>0.000121</td>\n",
       "      <td>0.002698</td>\n",
       "      <td>0.000260</td>\n",
       "      <td>2</td>\n",
       "      <td>{'n_neighbors': 2}</td>\n",
       "      <td>0.833333</td>\n",
       "      <td>0.858333</td>\n",
       "      <td>0.883333</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.861667</td>\n",
       "      <td>0.016330</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000706</td>\n",
       "      <td>0.000082</td>\n",
       "      <td>0.002601</td>\n",
       "      <td>0.000106</td>\n",
       "      <td>3</td>\n",
       "      <td>{'n_neighbors': 3}</td>\n",
       "      <td>0.908333</td>\n",
       "      <td>0.916667</td>\n",
       "      <td>0.883333</td>\n",
       "      <td>0.933333</td>\n",
       "      <td>0.900000</td>\n",
       "      <td>0.908333</td>\n",
       "      <td>0.016667</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000620</td>\n",
       "      <td>0.000074</td>\n",
       "      <td>0.002359</td>\n",
       "      <td>0.000102</td>\n",
       "      <td>4</td>\n",
       "      <td>{'n_neighbors': 4}</td>\n",
       "      <td>0.850000</td>\n",
       "      <td>0.925000</td>\n",
       "      <td>0.858333</td>\n",
       "      <td>0.933333</td>\n",
       "      <td>0.900000</td>\n",
       "      <td>0.893333</td>\n",
       "      <td>0.033912</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000538</td>\n",
       "      <td>0.000012</td>\n",
       "      <td>0.002157</td>\n",
       "      <td>0.000035</td>\n",
       "      <td>5</td>\n",
       "      <td>{'n_neighbors': 5}</td>\n",
       "      <td>0.875000</td>\n",
       "      <td>0.941667</td>\n",
       "      <td>0.883333</td>\n",
       "      <td>0.950000</td>\n",
       "      <td>0.925000</td>\n",
       "      <td>0.915000</td>\n",
       "      <td>0.030459</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.000511</td>\n",
       "      <td>0.000016</td>\n",
       "      <td>0.002073</td>\n",
       "      <td>0.000035</td>\n",
       "      <td>6</td>\n",
       "      <td>{'n_neighbors': 6}</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.941667</td>\n",
       "      <td>0.858333</td>\n",
       "      <td>0.933333</td>\n",
       "      <td>0.916667</td>\n",
       "      <td>0.903333</td>\n",
       "      <td>0.034400</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.000478</td>\n",
       "      <td>0.000006</td>\n",
       "      <td>0.002026</td>\n",
       "      <td>0.000036</td>\n",
       "      <td>7</td>\n",
       "      <td>{'n_neighbors': 7}</td>\n",
       "      <td>0.875000</td>\n",
       "      <td>0.933333</td>\n",
       "      <td>0.858333</td>\n",
       "      <td>0.941667</td>\n",
       "      <td>0.916667</td>\n",
       "      <td>0.905000</td>\n",
       "      <td>0.032745</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0.000476</td>\n",
       "      <td>0.000017</td>\n",
       "      <td>0.001979</td>\n",
       "      <td>0.000015</td>\n",
       "      <td>8</td>\n",
       "      <td>{'n_neighbors': 8}</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.933333</td>\n",
       "      <td>0.858333</td>\n",
       "      <td>0.933333</td>\n",
       "      <td>0.908333</td>\n",
       "      <td>0.900000</td>\n",
       "      <td>0.032059</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0.000472</td>\n",
       "      <td>0.000011</td>\n",
       "      <td>0.001990</td>\n",
       "      <td>0.000017</td>\n",
       "      <td>9</td>\n",
       "      <td>{'n_neighbors': 9}</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.925000</td>\n",
       "      <td>0.883333</td>\n",
       "      <td>0.941667</td>\n",
       "      <td>0.916667</td>\n",
       "      <td>0.906667</td>\n",
       "      <td>0.027588</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0.000469</td>\n",
       "      <td>0.000008</td>\n",
       "      <td>0.002008</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>10</td>\n",
       "      <td>{'n_neighbors': 10}</td>\n",
       "      <td>0.841667</td>\n",
       "      <td>0.941667</td>\n",
       "      <td>0.866667</td>\n",
       "      <td>0.941667</td>\n",
       "      <td>0.916667</td>\n",
       "      <td>0.901667</td>\n",
       "      <td>0.040620</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   mean_fit_time  std_fit_time  mean_score_time  std_score_time  \\\n",
       "0       0.001510      0.000931         0.004020        0.000658   \n",
       "1       0.000738      0.000121         0.002698        0.000260   \n",
       "2       0.000706      0.000082         0.002601        0.000106   \n",
       "3       0.000620      0.000074         0.002359        0.000102   \n",
       "4       0.000538      0.000012         0.002157        0.000035   \n",
       "5       0.000511      0.000016         0.002073        0.000035   \n",
       "6       0.000478      0.000006         0.002026        0.000036   \n",
       "7       0.000476      0.000017         0.001979        0.000015   \n",
       "8       0.000472      0.000011         0.001990        0.000017   \n",
       "9       0.000469      0.000008         0.002008        0.000031   \n",
       "\n",
       "   param_n_neighbors               params  split0_test_score  \\\n",
       "0                  1   {'n_neighbors': 1}           0.866667   \n",
       "1                  2   {'n_neighbors': 2}           0.833333   \n",
       "2                  3   {'n_neighbors': 3}           0.908333   \n",
       "3                  4   {'n_neighbors': 4}           0.850000   \n",
       "4                  5   {'n_neighbors': 5}           0.875000   \n",
       "5                  6   {'n_neighbors': 6}           0.866667   \n",
       "6                  7   {'n_neighbors': 7}           0.875000   \n",
       "7                  8   {'n_neighbors': 8}           0.866667   \n",
       "8                  9   {'n_neighbors': 9}           0.866667   \n",
       "9                 10  {'n_neighbors': 10}           0.841667   \n",
       "\n",
       "   split1_test_score  split2_test_score  split3_test_score  split4_test_score  \\\n",
       "0           0.908333           0.866667           0.900000           0.916667   \n",
       "1           0.858333           0.883333           0.866667           0.866667   \n",
       "2           0.916667           0.883333           0.933333           0.900000   \n",
       "3           0.925000           0.858333           0.933333           0.900000   \n",
       "4           0.941667           0.883333           0.950000           0.925000   \n",
       "5           0.941667           0.858333           0.933333           0.916667   \n",
       "6           0.933333           0.858333           0.941667           0.916667   \n",
       "7           0.933333           0.858333           0.933333           0.908333   \n",
       "8           0.925000           0.883333           0.941667           0.916667   \n",
       "9           0.941667           0.866667           0.941667           0.916667   \n",
       "\n",
       "   mean_test_score  std_test_score  rank_test_score  \n",
       "0         0.891667        0.021082                9  \n",
       "1         0.861667        0.016330               10  \n",
       "2         0.908333        0.016667                2  \n",
       "3         0.893333        0.033912                8  \n",
       "4         0.915000        0.030459                1  \n",
       "5         0.903333        0.034400                5  \n",
       "6         0.905000        0.032745                4  \n",
       "7         0.900000        0.032059                7  \n",
       "8         0.906667        0.027588                3  \n",
       "9         0.901667        0.040620                6  "
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Display detailed results\n",
    "cv_results = pd.DataFrame(grid_search.cv_results_)\n",
    "cv_results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "90b63369-b0c5-43ff-a93f-6742af667a8f",
   "metadata": {},
   "outputs": [],
   "source": [
    "gymEnrollAgeIncomeHoursDfKnnFit = grid_search.best_estimator_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c230dab1-b0ef-4dde-b3f8-00db325ef856",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from copy import deepcopy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "933f59a6-19ca-4d42-81ef-0b7f31c59c59",
   "metadata": {},
   "outputs": [],
   "source": [
    "# gymEnrollAgeIncomeHoursDfKnnFit.predictHalfCutOff = deepcopy( gymEnrollAgeIncomeHoursDfKnnFit.predict)\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.predictHalfCutOff = gymEnrollAgeIncomeHoursDfKnnFit.predict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "55875572-b648-486a-9941-5ea39fa37274",
   "metadata": {},
   "outputs": [],
   "source": [
    " gymEnrollAgeIncomeHoursDfKnnFit.predict =  gymEnrollAgeIncomeHoursDfKnnFit.prob"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "392ddc06-c0fb-4ac7-b327-89fb9a44cda0",
   "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>scalerAge</th>\n",
       "      <th>scalerIncome</th>\n",
       "      <th>scalerHours</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>489</th>\n",
       "      <td>1.111624</td>\n",
       "      <td>1.049844</td>\n",
       "      <td>0.389383</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>241</th>\n",
       "      <td>-0.041962</td>\n",
       "      <td>-0.705146</td>\n",
       "      <td>0.175201</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>119</th>\n",
       "      <td>-0.186160</td>\n",
       "      <td>-0.705146</td>\n",
       "      <td>-0.681527</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>577</th>\n",
       "      <td>-1.267647</td>\n",
       "      <td>-0.052650</td>\n",
       "      <td>-1.109891</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>287</th>\n",
       "      <td>0.246435</td>\n",
       "      <td>-0.885145</td>\n",
       "      <td>1.674475</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>804</th>\n",
       "      <td>0.174336</td>\n",
       "      <td>1.387342</td>\n",
       "      <td>-0.895709</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>974</th>\n",
       "      <td>1.400020</td>\n",
       "      <td>1.139844</td>\n",
       "      <td>-1.752437</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>810</th>\n",
       "      <td>0.895327</td>\n",
       "      <td>0.577347</td>\n",
       "      <td>1.246111</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>395</th>\n",
       "      <td>0.174336</td>\n",
       "      <td>0.172349</td>\n",
       "      <td>1.246111</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>861</th>\n",
       "      <td>0.246435</td>\n",
       "      <td>-0.075150</td>\n",
       "      <td>0.603565</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>400 rows × 3 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     scalerAge  scalerIncome  scalerHours\n",
       "489   1.111624      1.049844     0.389383\n",
       "241  -0.041962     -0.705146     0.175201\n",
       "119  -0.186160     -0.705146    -0.681527\n",
       "577  -1.267647     -0.052650    -1.109891\n",
       "287   0.246435     -0.885145     1.674475\n",
       "..         ...           ...          ...\n",
       "804   0.174336      1.387342    -0.895709\n",
       "974   1.400020      1.139844    -1.752437\n",
       "810   0.895327      0.577347     1.246111\n",
       "395   0.174336      0.172349     1.246111\n",
       "861   0.246435     -0.075150     0.603565\n",
       "\n",
       "[400 rows x 3 columns]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gymEnrollAgeIncomeHoursDfX_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "fd901e0c-b0cb-479d-a579-6e2fcd4bd9af",
   "metadata": {},
   "outputs": [],
   "source": [
    "predictionProb = gymEnrollAgeIncomeHoursDfKnnFit.predict(gymEnrollAgeIncomeHoursDfX_test)\n",
    "predictHalfCutOff = gymEnrollAgeIncomeHoursDfKnnFit.predictHalfCutOff(gymEnrollAgeIncomeHoursDfX_test)\n",
    "gymEnrollAgeIncomeHoursDfX_test['predictionProb'] = predictionProb\n",
    "gymEnrollAgeIncomeHoursDfX_test['predictHalfCutOff'] = predictHalfCutOff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "0983f992-c261-402f-8bb2-e120146e0ad8",
   "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>scalerAge</th>\n",
       "      <th>scalerIncome</th>\n",
       "      <th>scalerHours</th>\n",
       "      <th>predictionProb</th>\n",
       "      <th>predictHalfCutOff</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>489</th>\n",
       "      <td>1.111624</td>\n",
       "      <td>1.049844</td>\n",
       "      <td>0.389383</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>241</th>\n",
       "      <td>-0.041962</td>\n",
       "      <td>-0.705146</td>\n",
       "      <td>0.175201</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>119</th>\n",
       "      <td>-0.186160</td>\n",
       "      <td>-0.705146</td>\n",
       "      <td>-0.681527</td>\n",
       "      <td>0.2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>577</th>\n",
       "      <td>-1.267647</td>\n",
       "      <td>-0.052650</td>\n",
       "      <td>-1.109891</td>\n",
       "      <td>0.4</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>287</th>\n",
       "      <td>0.246435</td>\n",
       "      <td>-0.885145</td>\n",
       "      <td>1.674475</td>\n",
       "      <td>0.2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>804</th>\n",
       "      <td>0.174336</td>\n",
       "      <td>1.387342</td>\n",
       "      <td>-0.895709</td>\n",
       "      <td>0.6</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>974</th>\n",
       "      <td>1.400020</td>\n",
       "      <td>1.139844</td>\n",
       "      <td>-1.752437</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>810</th>\n",
       "      <td>0.895327</td>\n",
       "      <td>0.577347</td>\n",
       "      <td>1.246111</td>\n",
       "      <td>0.8</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>395</th>\n",
       "      <td>0.174336</td>\n",
       "      <td>0.172349</td>\n",
       "      <td>1.246111</td>\n",
       "      <td>0.2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>861</th>\n",
       "      <td>0.246435</td>\n",
       "      <td>-0.075150</td>\n",
       "      <td>0.603565</td>\n",
       "      <td>0.2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>400 rows × 5 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     scalerAge  scalerIncome  scalerHours  predictionProb  predictHalfCutOff\n",
       "489   1.111624      1.049844     0.389383             1.0                  1\n",
       "241  -0.041962     -0.705146     0.175201             0.0                  0\n",
       "119  -0.186160     -0.705146    -0.681527             0.2                  0\n",
       "577  -1.267647     -0.052650    -1.109891             0.4                  0\n",
       "287   0.246435     -0.885145     1.674475             0.2                  0\n",
       "..         ...           ...          ...             ...                ...\n",
       "804   0.174336      1.387342    -0.895709             0.6                  1\n",
       "974   1.400020      1.139844    -1.752437             1.0                  1\n",
       "810   0.895327      0.577347     1.246111             0.8                  1\n",
       "395   0.174336      0.172349     1.246111             0.2                  0\n",
       "861   0.246435     -0.075150     0.603565             0.2                  0\n",
       "\n",
       "[400 rows x 5 columns]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gymEnrollAgeIncomeHoursDfX_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "6adf11fd-106f-42dc-9ac0-fe7b4378fc3e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion Matrix as DataFrame:\n",
      "             Actual_0  Actual_1\n",
      "Predicted_0       217        22\n",
      "Predicted_1        17       144\n"
     ]
    }
   ],
   "source": [
    "# Confusion matrix\n",
    "conf_matrix = confusion_matrix(gymEnrollAgeIncomeHoursDfy_test, gymEnrollAgeIncomeHoursDfX_test['predictHalfCutOff'])\n",
    "\n",
    "# Convert confusion matrix to DataFrame with predicted as rows and actual as columns\n",
    "conf_matrix_df = pd.DataFrame(conf_matrix, index=['Predicted_0', 'Predicted_1'], columns=['Actual_0', 'Actual_1'])\n",
    "print(\"Confusion Matrix as DataFrame:\")\n",
    "print(conf_matrix_df)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "0d372830-8fc0-48ae-b4d2-82208c3479e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.9025\n",
      "Precision: 0.8674698795180723\n",
      "Recall (Sensitivity): 0.8944099378881988\n",
      "Specificity: 0.9079497907949791\n",
      "F1 f1Score: 0.8807339449541285\n"
     ]
    }
   ],
   "source": [
    "# Calculate metrics\n",
    "precision = precision_score(gymEnrollAgeIncomeHoursDfy_test, gymEnrollAgeIncomeHoursDfX_test['predictHalfCutOff'])\n",
    "recall = recall_score(gymEnrollAgeIncomeHoursDfy_test, gymEnrollAgeIncomeHoursDfX_test['predictHalfCutOff'])\n",
    "accuracy = accuracy_score(gymEnrollAgeIncomeHoursDfy_test, gymEnrollAgeIncomeHoursDfX_test['predictHalfCutOff'])\n",
    "specificity = conf_matrix[0, 0] / (conf_matrix[0, 0] + conf_matrix[0, 1])\n",
    "f1Score = 2 * (precision * recall) / (precision + recall)\n",
    "\n",
    "print(f\"Accuracy: {accuracy}\")\n",
    "print(f\"Precision: {precision}\")\n",
    "print(f\"Recall (Sensitivity): {recall}\")\n",
    "print(f\"Specificity: {specificity}\")\n",
    "print(f\"F1 f1Score: {f1Score}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "a2929726-c175-4fdf-bedd-6aae4b4b29e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ROC AUC: 0.9423191870890616\n"
     ]
    }
   ],
   "source": [
    "roc_auc = roc_auc_score(gymEnrollAgeIncomeHoursDfy_test, gymEnrollAgeIncomeHoursDfX_test['predictionProb'])\n",
    "print(\"ROC AUC:\", roc_auc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "3e864f0c-15ea-44d8-a047-47559c5f2ec3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 45368 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot ROC curve\n",
    "fpr, tpr, _ = roc_curve(gymEnrollAgeIncomeHoursDfy_test, gymEnrollAgeIncomeHoursDfX_test['predictionProb'] )\n",
    "plt.figure()\n",
    "plt.plot(fpr, tpr, label=f'ROC curve (area = {roc_auc:.2f})')\n",
    "plt.plot([0, 1], [0, 1], 'k--')\n",
    "plt.xlim([0.0, 1.0])\n",
    "plt.ylim([0.0, 1.05])\n",
    "plt.xlabel('False Positive Rate')\n",
    "plt.ylabel('True Positive Rate')\n",
    "plt.title('Receiver Operating Characteristic')\n",
    "plt.legend(loc=\"lower right\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "dd3d8160-083d-4748-bb46-576cf43486ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'accuracy': 0.9025,\n",
       " 'recall': 0.8944099378881988,\n",
       " 'precision': 0.8674698795180723,\n",
       " 'sensitivity': 0.8944099378881988,\n",
       " 'specificity': 0.9079497907949791,\n",
       " 'f1Score': 0.8807339449541285,\n",
       " 'roc_auc': 0.9423191870890616,\n",
       " 'cvK': 5,\n",
       " 'bestParameters': {'n_neighbors': 5},\n",
       " 'bestCrossValidationScore': 0.915}"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics = {}\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['accuracy'] = accuracy\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['recall'] = recall\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['precision'] = precision\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['sensitivity'] = recall\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['specificity'] = specificity\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['f1Score'] = f1Score\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['roc_auc'] = roc_auc\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['cvK'] = 5\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['bestParameters'] = bestParameters\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics['bestCrossValidationScore'] = bestCrossValidationScore\n",
    "gymEnrollAgeIncomeHoursDfKnnFit.customMetrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "ad7005e8-82d3-4ac4-beab-964f0c3992c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "gymEnrollAgeIncomeHoursDfKnnFit.internaltransformers = [\n",
    "    {\n",
    "        \"origin\": \"Age\",\n",
    "        \"to\": \"scalerAge\",\n",
    "        \"transformerModel\": scalerAge,\n",
    "        \"methodToCall\": \"fit_transform\"\n",
    "    },\n",
    "    {\n",
    "        \"origin\": \"Income\",\n",
    "        \"to\": \"scalerIncome\",\n",
    "        \"transformerModel\": scalerIncome,\n",
    "        \"methodToCall\": \"fit_transform\"\n",
    "    },\n",
    "    {\n",
    "        \"origin\": \"Hours\",\n",
    "        \"to\": \"scalerHours\",\n",
    "        \"transformerModel\": scalerHours,\n",
    "        \"methodToCall\": \"fit_transform\"\n",
    "    },\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "8e29e775-b422-4d03-a037-82d8b3795214",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-2 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-2 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-2 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-2 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-2 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>CustomKNNClassifier()</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" checked><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;CustomKNNClassifier<span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>CustomKNNClassifier()</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "CustomKNNClassifier()"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from functions.exportModel import exportModel\n",
    "exportModel({\n",
    "    \"modelName\": \"gymEnrollAgeIncomeHoursDfKnnFit\",\n",
    "    \"model\": gymEnrollAgeIncomeHoursDfKnnFit,\n",
    "    \"description\": \"gymEnrollAgeIncomeHoursDf\",\n",
    "    \"modelType\": \"knn\",\n",
    "    \"baseRelativePath\": \"..\",\n",
    "    \"inputs\": [\n",
    "        {\n",
    "            \"name\": \"Age\",\n",
    "            \"type\": \"int\"\n",
    "        },\n",
    "        {\n",
    "            \"name\": \"Income\",\n",
    "            \"type\": \"int\"\n",
    "        },\n",
    "        {\n",
    "            \"name\": \"Hours\",\n",
    "            \"type\": \"int\"\n",
    "        }\n",
    "    ],\n",
    "    \"output\": {\n",
    "        \"name\": \"Enroll_probibility\",\n",
    "        \"type\": \"float\"\n",
    "    }\n",
    "})"
   ]
  }
 ],
 "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.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
