{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "nDFUqw5WZPh7",
        "outputId": "07ab1db2-fc69-4ed4-e6df-f53c8aa47594"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Shape: (768, 9)\n",
            "   Pregnancies  Glucose  BloodPressure  SkinThickness  Insulin   BMI  \\\n",
            "0            6      148             72             35        0  33.6   \n",
            "1            1       85             66             29        0  26.6   \n",
            "2            8      183             64              0        0  23.3   \n",
            "3            1       89             66             23       94  28.1   \n",
            "4            0      137             40             35      168  43.1   \n",
            "\n",
            "   DiabetesPedigreeFunction  Age  Outcome  \n",
            "0                     0.627   50        1  \n",
            "1                     0.351   31        0  \n",
            "2                     0.672   32        1  \n",
            "3                     0.167   21        0  \n",
            "4                     2.288   33        1  \n"
          ]
        }
      ],
      "source": [
        "import pandas as pd\n",
        "\n",
        "# load dataset\n",
        "df = pd.read_csv(\"diabetes.csv\")\n",
        "\n",
        "# show shape and first rows\n",
        "print(\"Shape:\", df.shape)\n",
        "print(df.head())"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Step 2: Clean zeros -> NaN for specific columns\n",
        "\n",
        "import pandas as pd\n",
        "import numpy as np\n",
        "\n",
        "df = pd.read_csv(\"diabetes.csv\")\n",
        "\n",
        "ZERO_AS_MISSING = [\"Glucose\", \"BloodPressure\", \"SkinThickness\", \"Insulin\", \"BMI\"]\n",
        "\n",
        "# counts before\n",
        "before_zeros = {c: int((df[c] == 0).sum()) for c in ZERO_AS_MISSING}\n",
        "print(\"Zero counts BEFORE:\", before_zeros)\n",
        "\n",
        "# convert zeros to NaN\n",
        "dfc = df.copy()\n",
        "for c in ZERO_AS_MISSING:\n",
        "    dfc.loc[dfc[c] == 0, c] = np.nan\n",
        "\n",
        "# counts after (NaN)\n",
        "after_nans = dfc[ZERO_AS_MISSING].isna().sum().to_dict()\n",
        "print(\"NaN counts AFTER:\", after_nans)\n",
        "\n",
        "# quick preview\n",
        "print(\"\\nHead after cleaning:\")\n",
        "print(dfc.head())"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "fWOMa_exbPFq",
        "outputId": "66abc122-8f34-4caa-bfb1-43d82403dbda"
      },
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Zero counts BEFORE: {'Glucose': 5, 'BloodPressure': 35, 'SkinThickness': 227, 'Insulin': 374, 'BMI': 11}\n",
            "NaN counts AFTER: {'Glucose': 5, 'BloodPressure': 35, 'SkinThickness': 227, 'Insulin': 374, 'BMI': 11}\n",
            "\n",
            "Head after cleaning:\n",
            "   Pregnancies  Glucose  BloodPressure  SkinThickness  Insulin   BMI  \\\n",
            "0            6    148.0           72.0           35.0      NaN  33.6   \n",
            "1            1     85.0           66.0           29.0      NaN  26.6   \n",
            "2            8    183.0           64.0            NaN      NaN  23.3   \n",
            "3            1     89.0           66.0           23.0     94.0  28.1   \n",
            "4            0    137.0           40.0           35.0    168.0  43.1   \n",
            "\n",
            "   DiabetesPedigreeFunction  Age  Outcome  \n",
            "0                     0.627   50        1  \n",
            "1                     0.351   31        0  \n",
            "2                     0.672   32        1  \n",
            "3                     0.167   21        0  \n",
            "4                     2.288   33        1  \n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Step 3: Preprocessor + Train/Test split + Logistic Regression\n",
        "\n",
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.compose import ColumnTransformer\n",
        "from sklearn.pipeline import Pipeline\n",
        "from sklearn.impute import SimpleImputer\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "from sklearn.linear_model import LogisticRegression\n",
        "from sklearn.metrics import accuracy_score, f1_score, classification_report\n",
        "\n",
        "# separate features and target\n",
        "X = dfc.drop(columns=[\"Outcome\"])\n",
        "y = dfc[\"Outcome\"]\n",
        "\n",
        "# numeric columns\n",
        "num_cols = X.columns.tolist()\n",
        "\n",
        "# preprocessor: impute (median) + scale\n",
        "preprocessor = ColumnTransformer(\n",
        "    transformers=[\n",
        "        (\"num\", Pipeline(steps=[\n",
        "            (\"imputer\", SimpleImputer(strategy=\"median\")),\n",
        "            (\"scaler\", StandardScaler())\n",
        "        ]), num_cols)\n",
        "    ]\n",
        ")\n",
        "\n",
        "# split train/test\n",
        "X_train, X_test, y_train, y_test = train_test_split(\n",
        "    X, y, test_size=0.2, stratify=y, random_state=42\n",
        ")\n",
        "\n",
        "# pipeline with Logistic Regression\n",
        "pipe = Pipeline(steps=[\n",
        "    (\"pre\", preprocessor),\n",
        "    (\"clf\", LogisticRegression(max_iter=2000))\n",
        "])\n",
        "\n",
        "# fit and evaluate\n",
        "pipe.fit(X_train, y_train)\n",
        "y_pred = pipe.predict(X_test)\n",
        "\n",
        "print(\"Accuracy:\", accuracy_score(y_test, y_pred))\n",
        "print(\"F1-weighted:\", f1_score(y_test, y_pred, average=\"weighted\"))\n",
        "print(\"\\nClassification Report:\\n\", classification_report(y_test, y_pred))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "q4NIpjZocb2Y",
        "outputId": "b8141aa1-316e-4bfd-8860-eedfc5067cd1"
      },
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Accuracy: 0.7077922077922078\n",
            "F1-weighted: 0.7008015907537438\n",
            "\n",
            "Classification Report:\n",
            "               precision    recall  f1-score   support\n",
            "\n",
            "           0       0.75      0.82      0.78       100\n",
            "           1       0.60      0.50      0.55        54\n",
            "\n",
            "    accuracy                           0.71       154\n",
            "   macro avg       0.68      0.66      0.67       154\n",
            "weighted avg       0.70      0.71      0.70       154\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Step 4: Confusion Matrix plot\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "from sklearn.metrics import confusion_matrix\n",
        "import seaborn as sns\n",
        "\n",
        "cm = confusion_matrix(y_test, y_pred, labels=[0,1])\n",
        "\n",
        "plt.figure(figsize=(5,4))\n",
        "sns.heatmap(cm, annot=True, fmt=\"d\", cmap=\"Blues\",\n",
        "            xticklabels=[0,1], yticklabels=[0,1])\n",
        "plt.xlabel(\"Predicted\")\n",
        "plt.ylabel(\"Actual\")\n",
        "plt.title(\"Confusion Matrix - Logistic Regression\")\n",
        "plt.show()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 410
        },
        "id": "BQVhuBqtdCaT",
        "outputId": "f533e753-b8c2-42ce-d566-bf3d70f55077"
      },
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 500x400 with 2 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "import pandas as pd, numpy as np\n",
        "from sklearn.model_selection import cross_val_score, StratifiedKFold\n",
        "from sklearn.compose import ColumnTransformer\n",
        "from sklearn.pipeline import Pipeline\n",
        "from sklearn.impute import SimpleImputer\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "from sklearn.linear_model import LogisticRegression\n",
        "from sklearn.svm import SVC\n",
        "from sklearn.ensemble import RandomForestClassifier\n",
        "\n",
        "df = pd.read_csv(\"diabetes.csv\")\n",
        "for c in [\"Glucose\",\"BloodPressure\",\"SkinThickness\",\"Insulin\",\"BMI\"]:\n",
        "    df.loc[df[c]==0, c] = np.nan\n",
        "X, y = df.drop(columns=[\"Outcome\"]), df[\"Outcome\"]\n",
        "\n",
        "pre = ColumnTransformer([(\"num\", Pipeline([(\"imp\", SimpleImputer(strategy=\"median\")),\n",
        "                                           (\"sc\", StandardScaler())]), X.columns)])\n",
        "cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)\n",
        "\n",
        "models = {\n",
        "    \"LR\": LogisticRegression(max_iter=2000),\n",
        "    \"SVC\": SVC(probability=True),\n",
        "    \"RF\": RandomForestClassifier()\n",
        "}\n",
        "\n",
        "for name, est in models.items():\n",
        "    pipe = Pipeline([(\"pre\", pre), (\"clf\", est)])\n",
        "    f1 = cross_val_score(pipe, X, y, cv=cv, scoring=\"f1_weighted\").mean()\n",
        "    print(name, round(f1, 4))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "AAvEa_LrgvYL",
        "outputId": "9a20c50c-6e85-4bc4-e6b7-9528226b71b0"
      },
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "LR 0.7621\n",
            "SVC 0.7387\n",
            "RF 0.7695\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from sklearn.feature_selection import SelectKBest, mutual_info_classif\n",
        "from sklearn.pipeline import Pipeline\n",
        "\n",
        "pipe = Pipeline([\n",
        "    (\"pre\", pre),\n",
        "    (\"select\", SelectKBest(score_func=mutual_info_classif, k=5)),\n",
        "    (\"clf\", RandomForestClassifier(n_estimators=100, random_state=42))\n",
        "])\n",
        "\n",
        "f1 = cross_val_score(pipe, X, y, cv=cv, scoring=\"f1_weighted\").mean()\n",
        "print(\"RandomForest + SelectKBest (k=5):\", round(f1,4))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "SuH-49FLhzId",
        "outputId": "7776a004-acd7-4008-bbe2-ef80b9251809"
      },
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "RandomForest + SelectKBest (k=5): 0.7543\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from sklearn.feature_selection import RFE\n",
        "\n",
        "pipe = Pipeline([\n",
        "    (\"pre\", pre),\n",
        "    (\"select\", RFE(estimator=RandomForestClassifier(n_estimators=100, random_state=42),\n",
        "                   n_features_to_select=5)),\n",
        "    (\"clf\", RandomForestClassifier(n_estimators=100, random_state=42))\n",
        "])\n",
        "\n",
        "f1 = cross_val_score(pipe, X, y, cv=cv, scoring=\"f1_weighted\").mean()\n",
        "print(\"RandomForest + RFE (5 features):\", round(f1,4))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "EcqJFuzqiSk2",
        "outputId": "1f4e00bd-0430-4fd3-a86c-63d9552c7d93"
      },
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "RandomForest + RFE (5 features): 0.7707\n"
          ]
        }
      ]
    }
  ]
}