{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d67b0805-ba49-4000-8834-934fa73cd32f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.8042\n",
      "Precision: 0.8571\n",
      "Recall: 0.6667\n",
      "F1 Score: 0.7500\n",
      "Accuracy: 0.7902\n",
      "Precision: 0.8113\n",
      "Recall: 0.6825\n",
      "F1 Score: 0.7414\n",
      "Accuracy: 0.7552\n",
      "Precision: 0.7593\n",
      "Recall: 0.6508\n",
      "F1 Score: 0.7009\n",
      "Accuracy: 0.7902\n",
      "Precision: 0.8367\n",
      "Recall: 0.6508\n",
      "F1 Score: 0.7321\n",
      "Accuracy: 0.7552\n",
      "Precision: 0.7258\n",
      "Recall: 0.7143\n",
      "F1 Score: 0.7200\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.naive_bayes import GaussianNB\n",
    "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
    "\n",
    "# Load dataset\n",
    "df = pd.read_csv('./titanic.csv')\n",
    "\n",
    "# Preprocess data\n",
    "def preprocess_data(df):\n",
    "    df = df.drop(['Name', 'Ticket', 'Cabin'], axis=1, errors='ignore')  # Drop non-numeric features\n",
    "    df = df.dropna()  # Drop missing values\n",
    "    \n",
    "    # Encode categorical variables\n",
    "    label_encoders = {}\n",
    "    for col in ['Sex', 'Embarked']:\n",
    "        if col in df.columns:\n",
    "            le = LabelEncoder()\n",
    "            df[col] = le.fit_transform(df[col])\n",
    "            label_encoders[col] = le\n",
    "    \n",
    "    return df\n",
    "\n",
    "df = preprocess_data(df)\n",
    "X = df.drop('Survived', axis=1)\n",
    "y = df['Survived']\n",
    "\n",
    "# Split data\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# Train Random Forest classifier\n",
    "rf = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf.fit(X_train, y_train)\n",
    "\n",
    "def evaluate_model(model, X_test, y_test):\n",
    "    y_pred = model.predict(X_test)\n",
    "    print(f\"Accuracy: {accuracy_score(y_test, y_pred):.4f}\")\n",
    "    print(f\"Precision: {precision_score(y_test, y_pred):.4f}\")\n",
    "    print(f\"Recall: {recall_score(y_test, y_pred):.4f}\")\n",
    "    print(f\"F1 Score: {f1_score(y_test, y_pred):.4f}\")\n",
    "\n",
    "evaluate_model(rf, X_test, y_test)\n",
    "\n",
    "# Feature selection: manually selecting important features\n",
    "important_features = X.columns[rf.feature_importances_ > 0.05]\n",
    "X_train_imp = X_train[important_features]\n",
    "X_test_imp = X_test[important_features]\n",
    "\n",
    "rf_imp = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf_imp.fit(X_train_imp, y_train)\n",
    "evaluate_model(rf_imp, X_test_imp, y_test)\n",
    "\n",
    "# PCA for dimensionality reduction\n",
    "scaler = StandardScaler()\n",
    "X_train_scaled = scaler.fit_transform(X_train)\n",
    "X_test_scaled = scaler.transform(X_test)\n",
    "\n",
    "pca = PCA(n_components=5)\n",
    "X_train_pca = pca.fit_transform(X_train_scaled)\n",
    "X_test_pca = pca.transform(X_test_scaled)\n",
    "\n",
    "rf_pca = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf_pca.fit(X_train_pca, y_train)\n",
    "evaluate_model(rf_pca, X_test_pca, y_test)\n",
    "\n",
    "# Train Logistic Regression and Naïve Bayes\n",
    "log_reg = LogisticRegression()\n",
    "log_reg.fit(X_train_scaled, y_train)\n",
    "evaluate_model(log_reg, X_test_scaled, y_test)\n",
    "\n",
    "nb = GaussianNB()\n",
    "nb.fit(X_train, y_train)\n",
    "evaluate_model(nb, X_test, y_test)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "c9dcd04d-f05c-4ab8-b170-b52b8c396951",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from sklearn.ensemble import RandomForestClassifier \n",
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "dde0ae7d-0633-4807-bee0-e91e54f3a38c",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('titanic.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e35e3537-037c-4fdb-bcad-17c3364a5e05",
   "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>PassengerId</th>\n",
       "      <th>Survived</th>\n",
       "      <th>Pclass</th>\n",
       "      <th>Name</th>\n",
       "      <th>Sex</th>\n",
       "      <th>Age</th>\n",
       "      <th>SibSp</th>\n",
       "      <th>Parch</th>\n",
       "      <th>Ticket</th>\n",
       "      <th>Fare</th>\n",
       "      <th>Cabin</th>\n",
       "      <th>Embarked</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>Braund\\t Mr. Owen Harris</td>\n",
       "      <td>male</td>\n",
       "      <td>22.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>A/5 21171</td>\n",
       "      <td>7.2500</td>\n",
       "      <td>NaN</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Cumings\\t Mrs. John Bradley (Florence Briggs T...</td>\n",
       "      <td>female</td>\n",
       "      <td>38.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>PC 17599</td>\n",
       "      <td>71.2833</td>\n",
       "      <td>C85</td>\n",
       "      <td>C</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>Heikkinen\\t Miss Laina</td>\n",
       "      <td>female</td>\n",
       "      <td>26.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>STON/O2. 3101282</td>\n",
       "      <td>7.9250</td>\n",
       "      <td>NaN</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Futrelle\\t Mrs. Jacques Heath (Lily May Peel)</td>\n",
       "      <td>female</td>\n",
       "      <td>35.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>113803</td>\n",
       "      <td>53.1000</td>\n",
       "      <td>C123</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>Allen\\t Mr. William Henry</td>\n",
       "      <td>male</td>\n",
       "      <td>35.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>373450</td>\n",
       "      <td>8.0500</td>\n",
       "      <td>NaN</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   PassengerId  Survived  Pclass  \\\n",
       "0            1         0       3   \n",
       "1            2         1       1   \n",
       "2            3         1       3   \n",
       "3            4         1       1   \n",
       "4            5         0       3   \n",
       "\n",
       "                                                Name     Sex   Age  SibSp  \\\n",
       "0                           Braund\\t Mr. Owen Harris    male  22.0      1   \n",
       "1  Cumings\\t Mrs. John Bradley (Florence Briggs T...  female  38.0      1   \n",
       "2                             Heikkinen\\t Miss Laina  female  26.0      0   \n",
       "3      Futrelle\\t Mrs. Jacques Heath (Lily May Peel)  female  35.0      1   \n",
       "4                          Allen\\t Mr. William Henry    male  35.0      0   \n",
       "\n",
       "   Parch            Ticket     Fare Cabin Embarked  \n",
       "0      0         A/5 21171   7.2500   NaN        S  \n",
       "1      0          PC 17599  71.2833   C85        C  \n",
       "2      0  STON/O2. 3101282   7.9250   NaN        S  \n",
       "3      0            113803  53.1000  C123        S  \n",
       "4      0            373450   8.0500   NaN        S  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c6a56c4-247d-4e1c-a56f-f1971723856b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b38c2072-4d6b-449e-b399-a273a015cd45",
   "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>PassengerId</th>\n",
       "      <th>Survived</th>\n",
       "      <th>Pclass</th>\n",
       "      <th>Name</th>\n",
       "      <th>Sex</th>\n",
       "      <th>Age</th>\n",
       "      <th>SibSp</th>\n",
       "      <th>Parch</th>\n",
       "      <th>Ticket</th>\n",
       "      <th>Fare</th>\n",
       "      <th>Cabin</th>\n",
       "      <th>Embarked</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>Braund\\t Mr. Owen Harris</td>\n",
       "      <td>male</td>\n",
       "      <td>22.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>A/5 21171</td>\n",
       "      <td>7.2500</td>\n",
       "      <td>NaN</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Cumings\\t Mrs. John Bradley (Florence Briggs T...</td>\n",
       "      <td>female</td>\n",
       "      <td>38.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>PC 17599</td>\n",
       "      <td>71.2833</td>\n",
       "      <td>C85</td>\n",
       "      <td>C</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>Heikkinen\\t Miss Laina</td>\n",
       "      <td>female</td>\n",
       "      <td>26.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>STON/O2. 3101282</td>\n",
       "      <td>7.9250</td>\n",
       "      <td>NaN</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Futrelle\\t Mrs. Jacques Heath (Lily May Peel)</td>\n",
       "      <td>female</td>\n",
       "      <td>35.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>113803</td>\n",
       "      <td>53.1000</td>\n",
       "      <td>C123</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>Allen\\t Mr. William Henry</td>\n",
       "      <td>male</td>\n",
       "      <td>35.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>373450</td>\n",
       "      <td>8.0500</td>\n",
       "      <td>NaN</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   PassengerId  Survived  Pclass  \\\n",
       "0            1         0       3   \n",
       "1            2         1       1   \n",
       "2            3         1       3   \n",
       "3            4         1       1   \n",
       "4            5         0       3   \n",
       "\n",
       "                                                Name     Sex   Age  SibSp  \\\n",
       "0                           Braund\\t Mr. Owen Harris    male  22.0      1   \n",
       "1  Cumings\\t Mrs. John Bradley (Florence Briggs T...  female  38.0      1   \n",
       "2                             Heikkinen\\t Miss Laina  female  26.0      0   \n",
       "3      Futrelle\\t Mrs. Jacques Heath (Lily May Peel)  female  35.0      1   \n",
       "4                          Allen\\t Mr. William Henry    male  35.0      0   \n",
       "\n",
       "   Parch            Ticket     Fare Cabin Embarked  \n",
       "0      0         A/5 21171   7.2500   NaN        S  \n",
       "1      0          PC 17599  71.2833   C85        C  \n",
       "2      0  STON/O2. 3101282   7.9250   NaN        S  \n",
       "3      0            113803  53.1000  C123        S  \n",
       "4      0            373450   8.0500   NaN        S  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "c400125e-40e3-476a-acb2-553e258402e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "y = df['Survived']\n",
    "x = df['Sex']\n",
    "x_train,x_test,y_train,y_test = train_test_split(x, y, test_size=0.25)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "59588973-5bf3-4cd0-8b6b-39818cb3835d",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\SIMRAN\\AppData\\Local\\Temp\\ipykernel_25216\\2602413913.py:18: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n",
      "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n",
      "\n",
      "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n",
      "\n",
      "\n",
      "  df[\"Age\"].fillna(df[\"Age\"].median(), inplace=True)\n",
      "C:\\Users\\SIMRAN\\AppData\\Local\\Temp\\ipykernel_25216\\2602413913.py:19: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n",
      "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n",
      "\n",
      "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n",
      "\n",
      "\n",
      "  df[\"Embarked\"].fillna(df[\"Embarked\"].mode()[0], inplace=True)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Random Forest Performance:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.83      0.88      0.85       105\n",
      "           1       0.81      0.74      0.77        74\n",
      "\n",
      "    accuracy                           0.82       179\n",
      "   macro avg       0.82      0.81      0.81       179\n",
      "weighted avg       0.82      0.82      0.82       179\n",
      "\n",
      "Performance after Feature Selection:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.81      0.89      0.85       105\n",
      "           1       0.81      0.70      0.75        74\n",
      "\n",
      "    accuracy                           0.81       179\n",
      "   macro avg       0.81      0.79      0.80       179\n",
      "weighted avg       0.81      0.81      0.81       179\n",
      "\n",
      "Performance after PCA:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.84      0.87      0.85       105\n",
      "           1       0.80      0.77      0.79        74\n",
      "\n",
      "    accuracy                           0.83       179\n",
      "   macro avg       0.82      0.82      0.82       179\n",
      "weighted avg       0.83      0.83      0.83       179\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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n3zI24IFCxzaf/75Zx08ePCutulmzZrpzz//VI4cOVLdfpLfN27m7u6u2rVra9y4cZKk8PBwe7uU+t8HgPuLPUMA7lqHDh00ZcoUvfbaazp69KjKlCmjHTt2aMyYMWrSpInq16/v0N/Hx0d169bV0KFD7aPJHTp06J4Mrz1hwgQ988wzqlmzpnr06KGCBQvq4sWLOnLkiL788kv7SE3Jw1z37NlTbdq0UWRkpN5//33lzp1bhw8fdlhmmTJltGXLFn355ZfKnTu3smbNqhIlSqhJkybKnj27OnfurFGjRsnFxUVz585VZGTkXdc7atQobdiwQdWrV1fv3r1VokQJXb16VUePHtW6des0ffr0DBk9KkeOHOrRo4ciIiJUvHhxrVu3Tp9++ql69OihJ598UlLaX/fUZM2aVQUKFNDq1atVr149Zc+eXT4+PvahyOfOnauSJUuqbNmyCgsLU0hISLqfjyxZsujjjz9Wly5dVL9+fXXt2lW+vr46cuSIfvnlF/soeTNmzFDjxo313HPPKSgoSHnz5tW5c+d08OBB7dmzR8uXL5ckValSRc2aNVPZsmWVLVs2HTx4UJ9//rmqVav20FxrpkOHDho/frw++ugj9erVS15eXqpVq5ZCQkLsz/PWrVs1e/bsdO1tk26cr/Pqq68qNDRUrq6uql+/vvbv36+PPvooxciLw4cPt58nN2zYMGXPnl0LFy7U2rVr9eGHH8rb2/serHX6lShRQt26ddOkSZPk5OSkxo0b20eTy58/v956661/XUbfvn21YsUK1apVS2+99ZbKli2r69evKyIiQt9++63efvttValSRcOGDdPx48dVr1495cuXT+fPn9eECRPk6uqq2rVrS7px6GOmTJm0cOFClSpVSlmyZFGePHky7EcSwFIydPgGAA+1W0eTM8aYs2fPmu7du5vcuXMbFxcXU6BAATNo0CBz9epVh36STK9evczUqVNNkSJFjKurqylZsqRZuHDhXT128vx38vfff5tOnTqZvHnzGldXV5MzZ05TvXp1M3r0aId+Y8eONQULFjTu7u6mVKlS5tNPP011hLi9e/eaGjVqGE9PTyPJ1K5d237fTz/9ZKpXr24yZ85s8ubNa4YPH25mzZqV6mhyTZs2TbXeM2fOmN69e5tChQoZV1dXkz17dhMQEGCGDBniMCJcam43mtytz9Hff/9tJJmQkBCH9uRRu5YvX55imVu2bDGVKlUy7u7uJnfu3Gbw4MEpRlhL6+uemo0bN5oKFSoYd3d3h9HH/vnnH9O5c2eTK1cu4+npaZ555hmzfft2U7t2bYfXILV1uHmdbx2Ja926daZ27domc+bMxtPT0/j7+5tx48Y59Pnll19M27ZtTa5cuYyrq6vx8/MzdevWdRiZ7d133zWVKlUy2bJlM+7u7qZw4cLmrbfeMjExMamu56313jqa3K1/U8bcfsTCW6W2HSRbu3atkWRGjhxpjDHm+PHj5oUXXjDZsmUzWbNmNY0aNTL79+83BQoUcBj5LXk0uVtHRUut/vj4ePP222+bXLlyGQ8PD1O1alWza9euFMs0xphff/3VNG/e3Hh7exs3NzdTrly5FK/R7V7T29WU/DydOXPmjs/T7Z7nmyUlJZlx48aZ4sWLG1dXV+Pj42NeffVVExkZ6dDvTs95XFycee+990yJEiWMm5ub8fb2NmXKlDFvvfWWfSTNr776yjRu3NjkzZvXuLm5mVy5cpkmTZqY7du3Oyxr8eLFpmTJksbV1fWuR14E8N/ZjLnNMQQA8B/YbDb16tXL/is8Hj7PPvusYmJiHK69AwCAlXDOEAAAAABLIgwBAAAAsCQOkwMAAABgSewZAgAAAGBJhCEAAAAAlvTYXGfo+vXrOnnypLJmzZrmq58DAAAAeHwYY3Tx4kXlyZNHTk633//z2IShkydPKn/+/BldBgAAAICHRGRk5B0v4v3YhKGsWbNKurHCt14JGwAAAIB1xMbGKn/+/PaMcDuPTRhKPjTOy8uLMAQAAADgX0+fYQAFAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAAAAAJbkktEFPCwC3pmf0SXgAQoL6ZDRJQAAACCDsWcIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYUrrC0NSpU1WoUCF5eHgoICBA27dvv23flStXqkGDBsqZM6e8vLxUrVo1rV+/3qHP3LlzZbPZUkxXr15NT3kAAAAA8K/SHIaWLl2qvn37asiQIQoPD1fNmjXVuHFjRUREpNp/27ZtatCggdatW6ewsDDVqVNHzZs3V3h4uEM/Ly8vRUVFOUweHh7pWysAAAAA+BcuaZ1h/Pjx6ty5s7p06SJJCg0N1fr16zVt2jQFBwen6B8aGupwe8yYMVq9erW+/PJLVahQwd5us9nk5+eX1nIAAAAAIF3StGcoISFBYWFhatiwoUN7w4YNtXPnzrtaxvXr13Xx4kVlz57doT0uLk4FChRQvnz51KxZsxR7jm4VHx+v2NhYhwkAAAAA7laawlBMTIySkpLk6+vr0O7r66vo6Oi7WsbHH3+sS5cuqW3btva2kiVLau7cuVqzZo0WL14sDw8P1ahRQ4cPH77tcoKDg+Xt7W2f8ufPn5ZVAQAAAGBx6RpAwWazOdw2xqRoS83ixYs1YsQILV26VLly5bK3V61aVa+++qrKlSunmjVratmyZSpevLgmTZp022UNGjRIFy5csE+RkZHpWRUAAAAAFpWmc4Z8fHzk7OycYi/Q6dOnU+wtutXSpUvVuXNnLV++XPXr179jXycnJ1WuXPmOe4bc3d3l7u5+98UDAAAAwE3StGfIzc1NAQEB2rBhg0P7hg0bVL169dvOt3jxYgUFBWnRokVq2rTpvz6OMUZ79+5V7ty501IeAAAAANy1NI8m169fP7Vv316VKlVStWrVNHPmTEVERKh79+6Sbhy+duLECc2fP1/SjSDUoUMHTZgwQVWrVrXvVcqUKZO8vb0lSSNHjlTVqlVVrFgxxcbGauLEidq7d6+mTJlyr9YTAAAAABykOQwFBgbq7NmzGjVqlKKiolS6dGmtW7dOBQoUkCRFRUU5XHNoxowZSkxMVK9evdSrVy97+2uvvaa5c+dKks6fP69u3bopOjpa3t7eqlChgrZt26ann376P64eAAAAAKTOZowxGV3EvRAbGytvb29duHBBXl5eaZ4/4J3596EqPKzCQjpkdAkAAAC4T+42G6RrNDkAAAAAeNQRhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCURhgAAAABYEmEIAAAAgCWlKwxNnTpVhQoVkoeHhwICArR9+/bb9l25cqUaNGignDlzysvLS9WqVdP69etT9FuxYoX8/f3l7u4uf39/ffHFF+kpDQAAAADuSprD0NKlS9W3b18NGTJE4eHhqlmzpho3bqyIiIhU+2/btk0NGjTQunXrFBYWpjp16qh58+YKDw+399m1a5cCAwPVvn17/fLLL2rfvr3atm2rH3/8Mf1rBgAAAAB3YDPGmLTMUKVKFVWsWFHTpk2zt5UqVUotW7ZUcHDwXS3jqaeeUmBgoIYNGyZJCgwMVGxsrL7++mt7n0aNGilbtmxavHhxqsuIj49XfHy8/XZsbKzy58+vCxcuyMvLKy2rJEkKeGd+mufBoysspENGlwAAAID7JDY2Vt7e3v+aDdK0ZyghIUFhYWFq2LChQ3vDhg21c+fOu1rG9evXdfHiRWXPnt3etmvXrhTLfO655+64zODgYHl7e9un/Pnzp2FNAAAAAFhdmsJQTEyMkpKS5Ovr69Du6+ur6Ojou1rGxx9/rEuXLqlt27b2tujo6DQvc9CgQbpw4YJ9ioyMTMOaAAAAALA6l/TMZLPZHG4bY1K0pWbx4sUaMWKEVq9erVy5cv2nZbq7u8vd3T0NVQMAAADA/0lTGPLx8ZGzs3OKPTanT59OsWfnVkuXLlXnzp21fPly1a9f3+E+Pz+/dC0TAAAAANIrTYfJubm5KSAgQBs2bHBo37Bhg6pXr37b+RYvXqygoCAtWrRITZs2TXF/tWrVUizz22+/veMyAQAAAOC/SPNhcv369VP79u1VqVIlVatWTTNnzlRERIS6d+8u6ca5PCdOnND8+TdGZ1u8eLE6dOigCRMmqGrVqvY9QJkyZZK3t7ckqU+fPqpVq5bGjRunFi1aaPXq1dq4caN27Nhxr9YTAAAAAByk+TpDgYGBCg0N1ahRo1S+fHlt27ZN69atU4ECBSRJUVFRDtccmjFjhhITE9WrVy/lzp3bPvXp08fep3r16lqyZInmzJmjsmXLau7cuVq6dKmqVKlyD1YRAAAAAFJK83WGHlZ3O5b47XCdIWvhOkMAAACPr/tynSEAAAAAeFwQhgAAAABYEmEIAAAAgCURhgAAAABYUpqH1gbw3zBYh7UwWAcAAA8v9gwBAAAAsCTCEAAAAABL4jA5AHhMcUimtXBIJgCkHXuGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFgSYQgAAACAJRGGAAAAAFiSS0YXAAAAHm0B78zP6BLwAIWFdMjoEoB7hj1DAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAkghDAAAAACyJMAQAAADAktIVhqZOnapChQrJw8NDAQEB2r59+237RkVF6eWXX1aJEiXk5OSkvn37pugzd+5c2Wy2FNPVq1fTUx4AAAAA/Ks0h6GlS5eqb9++GjJkiMLDw1WzZk01btxYERERqfaPj49Xzpw5NWTIEJUrV+62y/Xy8lJUVJTD5OHhkdbyAAAAAOCupDkMjR8/Xp07d1aXLl1UqlQphYaGKn/+/Jo2bVqq/QsWLKgJEyaoQ4cO8vb2vu1ybTab/Pz8HCYAAAAAuF/SFIYSEhIUFhamhg0bOrQ3bNhQO3fu/E+FxMXFqUCBAsqXL5+aNWum8PDwO/aPj49XbGyswwQAAAAAdytNYSgmJkZJSUny9fV1aPf19VV0dHS6iyhZsqTmzp2rNWvWaPHixfLw8FCNGjV0+PDh284THBwsb29v+5Q/f/50Pz4AAAAA60nXAAo2m83htjEmRVtaVK1aVa+++qrKlSunmjVratmyZSpevLgmTZp023kGDRqkCxcu2KfIyMh0Pz4AAAAA63FJS2cfHx85Ozun2At0+vTpFHuL/gsnJydVrlz5jnuG3N3d5e7ufs8eEwAAAIC1pGnPkJubmwICArRhwwaH9g0bNqh69er3rChjjPbu3avcuXPfs2UCAAAAwM3StGdIkvr166f27durUqVKqlatmmbOnKmIiAh1795d0o3D106cOKH58+fb59m7d6+kG4MknDlzRnv37pWbm5v8/f0lSSNHjlTVqlVVrFgxxcbGauLEidq7d6+mTJlyD1YRAAAAAFJKcxgKDAzU2bNnNWrUKEVFRal06dJat26dChQoIOnGRVZvveZQhQoV7P8PCwvTokWLVKBAAR09elSSdP78eXXr1k3R0dHy9vZWhQoVtG3bNj399NP/YdUAAAAA4PbSHIYkqWfPnurZs2eq982dOzdFmzHmjsv75JNP9Mknn6SnFAAAAABIl3SNJgcAAAAAjzrCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsKR0haGpU6eqUKFC8vDwUEBAgLZv337bvlFRUXr55ZdVokQJOTk5qW/fvqn2W7Fihfz9/eXu7i5/f3998cUX6SkNAAAAAO5KmsPQ0qVL1bdvXw0ZMkTh4eGqWbOmGjdurIiIiFT7x8fHK2fOnBoyZIjKlSuXap9du3YpMDBQ7du31y+//KL27durbdu2+vHHH9NaHgAAAADclTSHofHjx6tz587q0qWLSpUqpdDQUOXPn1/Tpk1LtX/BggU1YcIEdejQQd7e3qn2CQ0NVYMGDTRo0CCVLFlSgwYNUr169RQaGnrbOuLj4xUbG+swAQAAAMDdSlMYSkhIUFhYmBo2bOjQ3rBhQ+3cuTPdRezatSvFMp977rk7LjM4OFje3t72KX/+/Ol+fAAAAADWk6YwFBMTo6SkJPn6+jq0+/r6Kjo6Ot1FREdHp3mZgwYN0oULF+xTZGRkuh8fAAAAgPW4pGcmm83mcNsYk6Ltfi/T3d1d7u7u/+kxAQAAAFhXmvYM+fj4yNnZOcUem9OnT6fYs5MWfn5+93yZAAAAAHAnaQpDbm5uCggI0IYNGxzaN2zYoOrVq6e7iGrVqqVY5rfffvuflgkAAAAAd5Lmw+T69eun9u3bq1KlSqpWrZpmzpypiIgIde/eXdKNc3lOnDih+fPn2+fZu3evJCkuLk5nzpzR3r175ebmJn9/f0lSnz59VKtWLY0bN04tWrTQ6tWrtXHjRu3YseMerCIAAAAApJTmMBQYGKizZ89q1KhRioqKUunSpbVu3ToVKFBA0o2LrN56zaEKFSrY/x8WFqZFixapQIECOnr0qCSpevXqWrJkid577z0NHTpURYoU0dKlS1WlSpX/sGoAAAAAcHvpGkChZ8+e6tmzZ6r3zZ07N0WbMeZfl9mmTRu1adMmPeUAAAAAQJql+aKrAAAAAPA4IAwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCTCEAAAAABLIgwBAAAAsCSXjC4AAAAAuBsB78zP6BLwAIWFdLjvj8GeIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWRBgCAAAAYEmEIQAAAACWlK4wNHXqVBUqVEgeHh4KCAjQ9u3b79h/69atCggIkIeHhwoXLqzp06c73D937lzZbLYU09WrV9NTHgAAAAD8qzSHoaVLl6pv374aMmSIwsPDVbNmTTVu3FgRERGp9v/777/VpEkT1axZU+Hh4Ro8eLB69+6tFStWOPTz8vJSVFSUw+Th4ZG+tQIAAACAf+GS1hnGjx+vzp07q0uXLpKk0NBQrV+/XtOmTVNwcHCK/tOnT9eTTz6p0NBQSVKpUqW0e/duffTRR3rhhRfs/Ww2m/z8/NK5GgAAAACQNmnaM5SQkKCwsDA1bNjQob1hw4bauXNnqvPs2rUrRf/nnntOu3fv1rVr1+xtcXFxKlCggPLly6dmzZopPDz8jrXEx8crNjbWYQIAAACAu5WmMBQTE6OkpCT5+vo6tPv6+io6OjrVeaKjo1Ptn5iYqJiYGElSyZIlNXfuXK1Zs0aLFy+Wh4eHatSoocOHD9+2luDgYHl7e9un/Pnzp2VVAAAAAFhcugZQsNlsDreNMSna/q3/ze1Vq1bVq6++qnLlyqlmzZpatmyZihcvrkmTJt12mYMGDdKFCxfsU2RkZHpWBQAAAIBFpemcIR8fHzk7O6fYC3T69OkUe3+S+fn5pdrfxcVFOXLkSHUeJycnVa5c+Y57htzd3eXu7p6W8gEAAADALk17htzc3BQQEKANGzY4tG/YsEHVq1dPdZ5q1aql6P/tt9+qUqVKcnV1TXUeY4z27t2r3Llzp6U8AAAAALhraT5Mrl+/fpo1a5Y+++wzHTx4UG+99ZYiIiLUvXt3STcOX+vQoYO9f/fu3XXs2DH169dPBw8e1GeffabZs2erf//+9j4jR47U+vXr9ddff2nv3r3q3Lmz9u7da18mAAAAANxraR5aOzAwUGfPntWoUaMUFRWl0qVLa926dSpQoIAkKSoqyuGaQ4UKFdK6dev01ltvacqUKcqTJ48mTpzoMKz2+fPn1a1bN0VHR8vb21sVKlTQtm3b9PTTT9+DVQQAAACAlNIchiSpZ8+e6tmzZ6r3zZ07N0Vb7dq1tWfPntsu75NPPtEnn3ySnlIAAAAAIF3SNZocAAAAADzqCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCSCEMAAAAALIkwBAAAAMCS0hWGpk6dqkKFCsnDw0MBAQHavn37Hftv3bpVAQEB8vDwUOHChTV9+vQUfVasWCF/f3+5u7vL399fX3zxRXpKAwAAAIC7kuYwtHTpUvXt21dDhgxReHi4atasqcaNGysiIiLV/n///beaNGmimjVrKjw8XIMHD1bv3r21YsUKe59du3YpMDBQ7du31y+//KL27durbdu2+vHHH9O/ZgAAAABwBy5pnWH8+PHq3LmzunTpIkkKDQ3V+vXrNW3aNAUHB6foP336dD355JMKDQ2VJJUqVUq7d+/WRx99pBdeeMG+jAYNGmjQoEGSpEGDBmnr1q0KDQ3V4sWLU60jPj5e8fHx9tsXLlyQJMXGxqZ1lSRJSfFX0jUfHk3p3U7uBbY1a2Fbw4PCtoYHhW0ND8p/2daS5zXG3LmjSYP4+Hjj7OxsVq5c6dDeu3dvU6tWrVTnqVmzpundu7dD28qVK42Li4tJSEgwxhiTP39+M378eIc+48ePN08++eRtaxk+fLiRxMTExMTExMTExMTElOoUGRl5x3yTpj1DMTExSkpKkq+vr0O7r6+voqOjU50nOjo61f6JiYmKiYlR7ty5b9vndsuUbuw96tevn/329evXde7cOeXIkUM2my0tq2VZsbGxyp8/vyIjI+Xl5ZXR5eAxxraGB4VtDQ8K2xoeFLa19DHG6OLFi8qTJ88d+6X5MDlJKcKGMeaOASS1/re2p3WZ7u7ucnd3d2h74okn7lg3Uufl5cUfFx4ItjU8KGxreFDY1vCgsK2lnbe397/2SdMACj4+PnJ2dk6xx+b06dMp9uwk8/PzS7W/i4uLcuTIccc+t1smAAAAAPxXaQpDbm5uCggI0IYNGxzaN2zYoOrVq6c6T7Vq1VL0//bbb1WpUiW5urresc/tlgkAAAAA/1WaD5Pr16+f2rdvr0qVKqlatWqaOXOmIiIi1L17d0k3zuU5ceKE5s+fL0nq3r27Jk+erH79+qlr167atWuXZs+e7TBKXJ8+fVSrVi2NGzdOLVq00OrVq7Vx40bt2LHjHq0mUuPu7q7hw4enONwQuNfY1vCgsK3hQWFbw4PCtnZ/2Yz5t/HmUpo6dao+/PBDRUVFqXTp0vrkk09Uq1YtSVJQUJCOHj2qLVu22Ptv3bpVb731ln777TflyZNHAwcOtIenZP/73//03nvv6a+//lKRIkX0wQcfqHXr1v9t7QAAAADgNtIVhgAAAADgUZemc4YAAAAA4HFBGAIAAABgSYQhAAAAAJZEGAIAAABgSYQhAADS6Pr16xldAgDgHiAMAQBwlyZPnqyTJ0/KycmJQAQAjwHCEP4TRmYHYBVr167VpEmTNHToUJ06dYpABLvkz8KbPxPZNpCR+H529whDSLfr16/LZrNJkg4fPqy//vpLf/31VwZXBQD3R9OmTfXGG2/o0KFDGjhwoKKjowlEcPgsvHDhgi5fvqzr16+zbeCBSg4/hw8f1rlz5+zbJP4dYQjpYoyRk9ONzWfYsGF6+eWXVadOHQUGBuqDDz7I4OrwsEt+07527ZouX76c6n3AwyQhIUGS9Oabb6pVq1Y6duyYhg4dqpiYGL70WtjNn4UhISF64YUXVLduXTVp0kQnTpyw3wfcT8YY2Ww2rVq1Si+++KJmzpypK1euZHRZjwz+SpEmyR/4yb84jB49WlOmTNGHH36ozZs3q0yZMho6dKgOHDiQkWXiIZb8pr127Vq9/PLLqlChgt566y0tW7ZMkvg1Cw8dY4zc3NwkSVOmTNHBgwf1119/af78+Ro0aBCHzFlY8vvVkCFDFBISovbt22vs2LHav3+/mjVrpnPnzmVwhbACm82mNWvW6KWXXlK3bt30yiuvKFOmTPb7+ZHxzghDSBMnJyclJSVJki5duqQff/xRs2bNUp06dXTgwAF98cUXmjZtmvz9/e2/pAI3s9ls+vLLL9W2bVv5+/tr9OjR2rdvnwYPHqyff/45o8sDUkj+whscHKzBgwerWbNmWrx4sbp166bdu3dr0KBBOn36NIHIoiIiIvTtt99qwYIFCgoKUlxcnOLi4tStWzdlz57d3o9tA/dLTEyMPvroI40dO1Y9e/ZUzpw5dfr0ac2bN09hYWH8yPgvCEO4K6+//roaNGggSXJ2dpYxRlevXlVYWJj8/Py0fv16tWvXTsHBwXr99deVkJCgTz75RD/99FMGV46HiTFG//zzj0JDQ/X+++9r5MiRatasmfbv36/nn39elStXzugSgRSSkpIUFxen9evXa8CAAWrVqpWqV6+uSZMmqV27dtq8ebPDIXP8Cmst586d04kTJ9SwYUOtW7dO7dq107hx49SjRw/FxcVp6tSpSkpK4pA53Ddubm7284SuXbumkSNHqnXr1nr33XdVvXp1rVmzJqNLfKjxl4l/de3aNVWvXl1HjhzRSy+9JOnGL6Xu7u6qVauWpk2bpsDAQH388cfq3r27JOnkyZP6/vvvdfTo0QysHA+L5C+HNptNnp6eio2NVaNGjXT06FEVLVpULVq00Pjx4yVJGzZs0OHDhzOyXEDr16+3f4FwdnZWlixZ5OrqqhMnTjj0GzBggMqWLaulS5eqa9euOnv2LL/CPsZSC7r58+eXv7+/+vfvr8DAQI0fP16vv/66pBt7jdasWaOdO3c+6FLxGEveDo8ePapTp07Jy8tLzz33nCZMmKDs2bPr4MGDevnllxUZGanGjRtr4cKF7Jm8A8IQ/pWrq6vatm2rDz/8ULt27VLbtm0lSVmyZNHTTz+tBQsW6LnnnlO7du0k3fiVrFevXoqNjdULL7yQkaXjIWGz2bRo0SJ98MEHOnv2rC5cuKCNGzeqQYMGatKkiaZNmyZJioyM1Jw5c3To0KEMrhhWdv78ec2ZM0d9+vTRunXrJN348lGkSBHt3LkzxaiZZcqUUalSpVS8eHFly5YtI0rGA3DzqHFjx47Vl19+KenGZ2T27NkVGhqqjh07qmvXrpKkK1eu6J133pGLi4tq1KiRYXXj8ZJ83u3q1avVrl07LV++XElJSXrzzTf16aefatq0aVqyZIl69uwpFxcXZcqUSYUKFWLP5J0Y4C5dvnzZLF261Dz55JPmhRdesLcPGTLEZMuWzdSvX980bdrU1KhRw5QrV84kJCQYY4xJTEzMqJKRwa5fv26MMSYyMtJ4e3ub8ePHG2OM+fDDD43NZjONGjVy6D948GDj7+9vjh079sBrBYz5v212165dJigoyPj7+5vVq1cbY4y5ePGiKVSokKlZs6bZt2+fuXjxoklISDCtW7c206ZNs8+blJSUYfXj/rj5Nf3jjz9M/fr1jZubm9m4caMxxpijR4+ap59+2lSpUsV06dLFjB492tSqVcuUKVPG/lnIdoF7ZdWqVcbDw8OEhoaayMjIVPucPHnSDBkyxOTIkcMcOHDgAVf4aLEZw8HNSJ35/78+JP8r3Rg0Ye3atXrnnXcUEBCglStXSpKWLFmiP/74Q1FRUSpdurRef/11ubi4KDExUS4uLhm5GshgW7ZssY++FRISIkk6ceKERo8erRkzZuj999+XzWZTRESEFi9erK1bt6p8+fIZWzQs6eb3umPHjun8+fMaP368du/erQ8++EAtW7bUyZMnVbduXUk3Dp9zdXXV5cuXdeDAAbm4uNivL4PH0+DBg7VlyxblyJFD33//vS5fvqz//e9/atasmY4eParZs2dry5Yt8vHxUYECBfTRRx/xWYh7Kjo6Ws8//7zat2+vN998U/Hx8bp48aK2bNmiIkWKqEKFClq7dq2WL1+ubdu2aeXKlXym/gvCEFJ18wf68ePHlSlTJrm4uMjb21sXL17U119/nSIQ3SopKUnOzs4Psmw8ZC5duqTOnTtr2bJlql+/vr799lv7fadPn9bChQs1f/58Zc6cWYUKFdLAgQNVunTpDKwYVnXze16vXr20du1a7d+/XwcOHNDkyZMVFhamMWPGqEWLFrp27Zo+//xzRUdHy9nZWW+//bZcXFx4z3vMff755+rRo4c2btyop556SkePHtXHH3+sRYsW6YsvvlDTpk3th9LdfN4Y2wXupYsXL6pWrVp6/fXXFRQUpA8++ECbN2/Wn3/+qZiYGH377bfy9/fXd999p+rVq6tgwYIZXfJDjzCEFG7+UjBmzBh98cUXunr1qry9vfXpp5+qVKlSiouL07p16zRgwABVqVJFS5cuzeCq8bDas2ePJk+erIULF2rr1q2qWrWqwy/wsbGx8vLyUnx8vNzd3TO4WljdmTNnNHDgQHXo0EHPPvusJGn37t2aOHGiwsLC7HuIbsUX3sffyJEjtWvXLn3zzTf2tqioKPXu3VtfffWVvv76az377LPsHcR9FRMTo/79+2vfvn06fPiw6tWrp/r16+vFF19UUFCQcufOrc8++4ztMA14lpBC8h/Pe++9pwkTJqh///6aMGGCkpKSVKdOHf3888/KkiWLmjRpopCQEK1atUpDhw7N4KrxMEjtt5WKFSvqrbfeUtOmTdWsWTP9/PPPstlsSkpKkjFGWbNmlST7RS2BjDJ79myVKVNGBw8eVLFixeyjL1WqVEm9e/dWpUqVNGzYMP3vf/9LMS9B6PGS/Nrf/J6WNWtWhYWF6cKFC/b7cufOrcDAQMXHx6tRo0baunUrw6vjnknejv755x9duHBBxhj5+Pho0KBBGjFihCZNmqRFixbpjTfekK+vrzw9PZU3b15JIgilAc8UUrV161Z9++23Wr58uQIDA3Xp0iUdOnRIOXPmVL169eyBqFGjRvr66681YsSIjC4ZGSx5b8+OHTs0cOBADRw4UHPnzpV0Y7StUaNGqW7dumrWrJnCwsLs16tK3kPEcMTISMYY5cyZU4ULF9Yff/whd3d3OTk52S8enRyIChYsqFWrVmVssbivFi9erI4dO+rAgQOKi4uzt9epU0cFCxbU+++/r9OnT9vfs/Lly6du3bopKChInTp10vHjx3k/w3+W/Pm4du1aNW3aVLVq1VLZsmW1a9cuFSlSRM8//7yCgoLk6empmJgYDRkyRNu2bdMrr7yS0aU/eh7ocA14ZISFhZlRo0YZY4xZv369yZUrl5kyZYo5duyYKVq0qMmTJ4/ZsWOHwzyMGmdNcXFx9v+vXLnSZM+e3bRs2dK8+uqrxsvLywwfPtx+/759+0y7du2Ms7Oz2bNnTwZUC9yQ2she8fHxZuPGjaZw4cKmUqVK9ve0+Ph4e59Dhw4xKthj7Pz586ZIkSImZ86cpnTp0ua1114zn332mf3+8ePHm8qVK5vOnTubX375xRw6dMg0bdrUdOrUyWzZssX4+vraR5gD0uPm95c1a9aYrFmzmpEjR5off/zRNGvWzBQuXNgsW7bMXLlyxRhz43M3KCjIFChQgM/VdCIM4bYf7KdOnTLGGNOiRQvzzjvvGGOMSUhIME2aNDE5cuQwdevWfWA14uG0e/duU6RIEXPmzBnz888/m/z585upU6caY4z5/fffjbe3t7HZbObNN9+0z7Nnzx4TFBRkfv/994wqGxZ383ve119/bT777DOzePFi+5DumzZtMv7+/qZmzZqpBqJbl4HHR2Jiohk0aJCZPn26CQsLMyEhIcbb29u0adPGjB8/3iQkJJiQkBDTvHlzY7PZTNGiRU2ZMmWMMcZER0ebYsWKma1bt2bwWuBRtH//fofbERERpkaNGuajjz4yxhgTFRVlChcubAoUKGCyZMlilixZYowx5vDhw2bmzJnmr7/+euA1Py4IQxZ38wd6WFiYCQsLM5cuXbK3nTp1yhQtWtR8/vnnxhhjYmNjTZs2bczOnTvt19SANe3du9dkzZrV9OnTxxhjzGeffWbefvttY8yNN/GCBQuarl27mhkzZhibzWaGDRtmn/fWL5ZARhgwYIDJmzevadiwofH39zfVqlUzX3zxhTHmxh7xsmXLmtq1a5tr165lbKF4oL7++mvj5eVlfvnlF2OMMVeuXDHDhg0zNpvN1KhRw3zwwQdm586d5qeffjJ79+61f46+/fbbpnTp0iYqKiojy8cjaNWqVeapp56yf9cyxpg///zTfPzxx+b8+fMmKirKFC9e3Lz++uvGGGMaNmxoihQpYubNm2eMMXwf+48IQzDGGPPOO++Y/PnzG1dXV9O6dWvz5Zdf2u97/vnnTd68ec3kyZPNM888Y6pUqWL/tZRfR63pl19+MZ6enmbw4MEO7Vu2bDHGGFO/fn3TsWNHY8yNC67mzZvX2Gw2079//wdeK5CaefPmmTx58pgffvjBGGPMhAkTjIeHh/0Cq4mJiWbjxo0mV65cpkePHhlZKjJAr169TM+ePe23/f39TcuWLU3//v1No0aNjM1mM7NnzzbGGLN161bTo0cPky1bNhMeHp5BFeNRtnv3bvPiiy+a2rVrmwULFtjbk/f29OvXz7Ro0cLExsYaY4zp0aOHcXd3N/ny5TMXLlzIkJofJ1wBzKLMTSeu79ixQ19//bUWLFigq1evasyYMQoNDdXFixfVrl07ffTRR/aT4fPly6dly5bJ2dmZYRstKjIyUvXq1VOzZs30wQcf2NunTZumo0ePqkCBAjp37px9UA1PT081aNBA9evXV6VKlTKoasDRgQMH1Lx5c1WpUkX/+9//NHToUH3yySd6/vnndenSJV24cEF169bVV199pYoVK2Z0uXjAKlSooDlz5ujcuXOqX7++smXLpnnz5snLy0vR0dHavn27WrVqJUny8PCQs7Ozvv/+e5UqVSqDK8ejKCAgQO+9957Gjh2radOmyRijV199VYUKFZIkRUREKF++fMqSJYukG9vc999/r3z58snLyysjS38s8E3WgpIvCpcsa9asqlu3rmrVqqWGDRtq1qxZcnd316effqoVK1aoWLFiWrlypdauXauVK1fK1dVViYmJBCGLSkpKUqFChXT16lV9//33kqTg4GC9++67atq0qdzc3PTrr7/ar87+0Ucf6ddff1Xjxo1VokSJDK4eVmRuGebYGKMzZ86oRIkS2rVrlzp27Khx48ape/fuun79upYuXaovv/xSxhhVrlxZzs7OSkpKyqDqkRE6d+6shIQE+fj4yMvLS2vWrLF/6fTz89OLL74oFxcXJSYm6umnn9bHH39MEEK6JA/jXrZsWQ0cOFD58+fX9OnTtWjRInsfLy8vffHFF5o4caK6du2q2bNnK1u2bPL19c2osh8rXHTVwj788ENt3rxZFy5cUOHChbVgwQL7fUeOHFGfPn2UkJCgdu3aqVOnTvb7bt6rBGs6fPiwevfuLTc3N/n6+mr16tX6/PPP1bBhQ0lSSEiIBg4cqKJFi+rcuXPasGGDKlSokMFVw+rCwsJUrlw5ubi4aNq0aerVq5ecnJy0aNEitW3bVpIUFxenVq1aqXLlyhozZkwGV4yMkPwZt2DBAo0bN05z585VQEAAn32455K3qfDwcLm5uempp57Sr7/+quDgYEVGRqpbt25q3769JKlly5b6+++/5eHhoRkzZqh8+fIZW/xjhJ/2LST51wdJmjBhgt5//32VLFlSsbGx2rBhgyZOnGi/v2jRopo4caJiY2P1yy+/OCyHDwMUK1ZMEyZM0JUrV7RgwQINGDDAHoQkqU+fPtq9e7dCQkIUHh5OEEKGuPk9b82aNeratatmzpyppKQk9ejRQ507d5abm5v8/PwUHR2tw4cPq02bNjp37pxGjRqVgZUjIyV/xtWpU0dnz57Vhg0bHNqBeyE5CK1cuVKNGzfW8uXLFR0drTJlytj3EM2YMUOff/65JGnVqlXauHGjNm3aRBC6x9gzZEFbtmzR999/r8qVK6thw4aKiIjQyJEjdejQIb388svq1auXve+JEyeUO3duDolDqv7880/17NlTzs7OGjx4sJ555hlJ4nwyZLibt8ElS5YoLCxMM2fOVK5cufTuu++qU6dOOnr0qEaMGKElS5bI19dXPj4+ypIli7777ju5uroqKSlJzs7OGbwmyEiTJk3SyJEjtW3bNvn7+2d0OXjMbN68Wc8//7wmTJig5s2bK2fOnPb7fvnlF40bN04nT57UK6+8oq5du2ZgpY83wpDFbNu2TS+//LKuXbumL7/8Uk8//bSkG19qg4ODdeDAAbVv3149evRwmI8vt7id5EPmjDEaOnSoatSokdElAXbvvfeepk2bpjFjxsjJycm+Z6hnz57q3LmzbDabtm7dqkuXLsnb21vVqlWTk5OTEhMT5eLCGENW9+eff2rUqFGaM2cOn4FIt9t9h+rbt69Onz6tRYsW2fcU3fzes3//fr377rtKSkrS0qVLGSzhPiEMWczRo0c1c+ZMTZ06Vd27d9fYsWPt9/31118aO3asNm/erHHjxql169YZWCkeJYcPH1a/fv0UExOjTz75RFWrVs3okmBxxhgdO3ZMDRo00OjRoxUYGChJOnfunLp06aLffvtNAwYMUFBQUIq9P/z4g5slf0llTyHSI/n9JDIyUuvXr9elS5fk7++vBg0aqG7dusqbN6/9ULibz0uLjIxU/vz5tX//fmXLlk158+bNyNV4rPGzl8UULFhQb775ppycnOy/MgwePFiSVLhwYfXv31+FCxdWixYtMrhSPEqKFSumkJAQDR06VHny5MnocgDZbDZlzZpVknTlyhVJUmJiorJnz67PP/9cTz31lCZMmKDExER17dpVTk5O9i8iBCHcLPnLKUEIaZUchPbt26cWLVroiSee0J9//ilJmjJlilq3bq3p06frjz/+UPHixe3b2vHjxzVp0iR16dJFpUuXzshVsATe8S0od+7c6t69uwIDAzV//nwFBwfb7ytevLjeffddhpJFmpUsWVILFy7Uk08+mdGlwIJuHiwhmYuLizJnzqwtW7ZIkv19LXPmzAoICJDNZtPSpUvtQ8QDwL1ycxCqVq2aAgMDtWnTJm3YsEEtWrTQgAEDdP78eXl6eio0NFR//PGHpBuXr0i+tImnp2cGr4U1sGfIovLly6fu3bvLZrNp4cKFunjxYophZPkVDGnl5uaW0SXAgm4+rO3QoUPKli2bXFxclCNHDo0fP16NGjVS3rx59cEHH9gvGO3h4aEPPvhAAwYM0Jw5c1SzZk1GCwNwzyQfGlevXj01bdrUflpClSpV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",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.metrics import accuracy_score, classification_report\n",
    "\n",
    "# Load the dataset\n",
    "DATASET_PATH = \"./titanic.csv\"  # Change to \"/mnt/data/diabetes.csv\" if needed\n",
    "df = pd.read_csv(DATASET_PATH)\n",
    "\n",
    "# Preprocess the dataset (Handling missing values, encoding categorical variables)\n",
    "def preprocess_titanic(df):\n",
    "    df = df.drop([\"Name\", \"Ticket\", \"Cabin\"], axis=1, errors='ignore')  # Drop unnecessary columns\n",
    "    df[\"Age\"].fillna(df[\"Age\"].median(), inplace=True)\n",
    "    df[\"Embarked\"].fillna(df[\"Embarked\"].mode()[0], inplace=True)\n",
    "    df = pd.get_dummies(df, columns=[\"Sex\", \"Embarked\"], drop_first=True)\n",
    "    df.dropna(inplace=True)\n",
    "    return df\n",
    "\n",
    "def preprocess_diabetes(df):\n",
    "    return df  # Assume no major preprocessing needed for diabetes dataset\n",
    "\n",
    "if \"titanic\" in DATASET_PATH:\n",
    "    df = preprocess_titanic(df)\n",
    "    target_column = \"Survived\"\n",
    "else:\n",
    "    df = preprocess_diabetes(df)\n",
    "    target_column = \"Outcome\"\n",
    "\n",
    "X = df.drop(target_column, axis=1)\n",
    "y = df[target_column]\n",
    "\n",
    "# Split into training and testing sets\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# Train a Random Forest Classifier\n",
    "rf = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf.fit(X_train, y_train)\n",
    "y_pred = rf.predict(X_test)\n",
    "print(\"Random Forest Performance:\")\n",
    "print(classification_report(y_test, y_pred))\n",
    "\n",
    "# Feature Importance Selection\n",
    "feature_importances = pd.Series(rf.feature_importances_, index=X.columns)\n",
    "feature_importances.sort_values(ascending=False, inplace=True)\n",
    "\n",
    "# Select Top N Features\n",
    "N = 5  # Change to desired number of top features\n",
    "selected_features = feature_importances[:N].index\n",
    "X_train_selected = X_train[selected_features]\n",
    "X_test_selected = X_test[selected_features]\n",
    "\n",
    "# Retrain model with selected features\n",
    "rf_selected = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf_selected.fit(X_train_selected, y_train)\n",
    "y_pred_selected = rf_selected.predict(X_test_selected)\n",
    "print(\"Performance after Feature Selection:\")\n",
    "print(classification_report(y_test, y_pred_selected))\n",
    "\n",
    "# Apply PCA for Feature Selection\n",
    "scaler = StandardScaler()\n",
    "X_scaled = scaler.fit_transform(X)\n",
    "pca = PCA(n_components=5)  # Adjust components as needed\n",
    "X_pca = pca.fit_transform(X_scaled)\n",
    "X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split(X_pca, y, test_size=0.2, random_state=42)\n",
    "\n",
    "rf_pca = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf_pca.fit(X_train_pca, y_train_pca)\n",
    "y_pred_pca = rf_pca.predict(X_test_pca)\n",
    "print(\"Performance after PCA:\")\n",
    "print(classification_report(y_test_pca, y_pred_pca))\n",
    "\n",
    "# Plot Feature Importances\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.barplot(x=feature_importances.index[:N], y=feature_importances.values[:N])\n",
    "plt.xticks(rotation=45)\n",
    "plt.title(\"Top Feature Importances in Random Forest\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "f80806b4-9f16-4c9b-90eb-d4171b67aba1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                  Accuracy  Precision    Recall  F1 Score\n",
      "Random Forest                     0.746753   0.633333  0.690909  0.660870\n",
      "Logistic Regression               0.753247   0.649123  0.672727  0.660714\n",
      "Naïve Bayes                       0.759740   0.650000  0.709091  0.678261\n",
      "Random Forest (Feature Selected)  0.785714   0.703704  0.690909  0.697248\n",
      "Random Forest (PCA Reduced)       0.681818   0.557692  0.527273  0.542056\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.naive_bayes import GaussianNB\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
    "\n",
    "# Load dataset (change the path accordingly)\n",
    "DATASET_PATH = \"./diabetes.csv\"  # Change to Titanic dataset if needed\n",
    "df = pd.read_csv(DATASET_PATH)\n",
    "\n",
    "# Preprocessing function\n",
    "def preprocess_data(df):\n",
    "    if \"Survived\" in df.columns:  # Titanic dataset\n",
    "        df = df.drop([\"Name\", \"Ticket\", \"Cabin\"], axis=1, errors='ignore')  # Drop irrelevant columns\n",
    "        df[\"Age\"].fillna(df[\"Age\"].median(), inplace=True)\n",
    "        df[\"Embarked\"].fillna(df[\"Embarked\"].mode()[0], inplace=True)\n",
    "        df = pd.get_dummies(df, drop_first=True)  # One-hot encoding for categorical variables\n",
    "        X = df.drop(\"Survived\", axis=1)\n",
    "        y = df[\"Survived\"]\n",
    "    else:  # Diabetes dataset\n",
    "        X = df.drop(\"Outcome\", axis=1)\n",
    "        y = df[\"Outcome\"]\n",
    "    \n",
    "    return X, y\n",
    "\n",
    "X, y = preprocess_data(df)\n",
    "\n",
    "# Standardize features\n",
    "scaler = StandardScaler()\n",
    "X_scaled = scaler.fit_transform(X)\n",
    "\n",
    "# Split dataset\n",
    "X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# Train classifiers\n",
    "models = {\n",
    "    \"Random Forest\": RandomForestClassifier(n_estimators=100, random_state=42),\n",
    "    \"Logistic Regression\": LogisticRegression(max_iter=1000),\n",
    "    \"Naïve Bayes\": GaussianNB()\n",
    "}\n",
    "\n",
    "# Train and evaluate models\n",
    "results = {}\n",
    "for name, model in models.items():\n",
    "    model.fit(X_train, y_train)\n",
    "    y_pred = model.predict(X_test)\n",
    "    results[name] = {\n",
    "        \"Accuracy\": accuracy_score(y_test, y_pred),\n",
    "        \"Precision\": precision_score(y_test, y_pred),\n",
    "        \"Recall\": recall_score(y_test, y_pred),\n",
    "        \"F1 Score\": f1_score(y_test, y_pred)\n",
    "    }\n",
    "\n",
    "# Feature Selection using Random Forest\n",
    "rf = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf.fit(X_train, y_train)\n",
    "importances = rf.feature_importances_\n",
    "important_features = np.argsort(importances)[-5:]  # Select top 5 features\n",
    "X_train_selected, X_test_selected = X_train[:, important_features], X_test[:, important_features]\n",
    "\n",
    "# Train Random Forest with selected features\n",
    "rf_selected = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf_selected.fit(X_train_selected, y_train)\n",
    "y_pred_selected = rf_selected.predict(X_test_selected)\n",
    "\n",
    "results[\"Random Forest (Feature Selected)\"] = {\n",
    "    \"Accuracy\": accuracy_score(y_test, y_pred_selected),\n",
    "    \"Precision\": precision_score(y_test, y_pred_selected),\n",
    "    \"Recall\": recall_score(y_test, y_pred_selected),\n",
    "    \"F1 Score\": f1_score(y_test, y_pred_selected)\n",
    "}\n",
    "\n",
    "# Apply PCA for dimensionality reduction\n",
    "pca = PCA(n_components=5)\n",
    "X_train_pca = pca.fit_transform(X_train)\n",
    "X_test_pca = pca.transform(X_test)\n",
    "\n",
    "# Train PCA-Reduced Random Forest\n",
    "rf_pca = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf_pca.fit(X_train_pca, y_train)\n",
    "y_pred_pca = rf_pca.predict(X_test_pca)\n",
    "\n",
    "results[\"Random Forest (PCA Reduced)\"] = {\n",
    "    \"Accuracy\": accuracy_score(y_test, y_pred_pca),\n",
    "    \"Precision\": precision_score(y_test, y_pred_pca),\n",
    "    \"Recall\": recall_score(y_test, y_pred_pca),\n",
    "    \"F1 Score\": f1_score(y_test, y_pred_pca)\n",
    "}\n",
    "\n",
    "# Print comparison results\n",
    "df_results = pd.DataFrame(results).T\n",
    "print(df_results)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "920a9ea7-c030-43a6-a2a7-8920d7df23a7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "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.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
