{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# CSC 3105 Project"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "cda961ffb493d00c"
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Load and Clean the Data\n",
    "\n",
    "This code block performs the following operations:\n",
    "\n",
    "1. Imports necessary libraries for data handling and cleaning.\n",
    "2. Defines a function `load_data` to load the data from a given directory into a pandas dataframe.\n",
    "3. Defines a function `clean_data` to clean the loaded data. The cleaning process includes:\n",
    "   - Handling missing values by dropping them.\n",
    "   - Removing duplicate rows.\n",
    "   - Converting the 'NLOS' column to integer data type.\n",
    "   - Normalizing the 'Measured range (time of flight)' column.\n",
    "   - Creating new features 'FP_SUM' and 'SNR'.\n",
    "   - One-hot encoding categorical features.\n",
    "   - Performing feature extraction on 'CIR' columns.\n",
    "   - Dropping the original 'CIR' columns.\n",
    "   - Checking for columns with only one unique value and dropping them.\n",
    "4. Checks if a pickle file with the cleaned data exists. If it does, it loads the data from the file. If it doesn't, it loads and cleans the data using the defined functions.\n",
    "5. Prints the first few rows of the cleaned data and its column headers."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "73fe8802e95a784f"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "\n",
    "DATASET_DIR = './UWB-LOS-NLOS-Data-Set/dataset'\n",
    "\n",
    "def load_data(dataset_dir):\n",
    "    # Load the data\n",
    "    file_paths = [os.path.join(dirpath, file) for dirpath, _, filenames in os.walk(dataset_dir) for file in filenames]\n",
    "    data = pd.concat((pd.read_csv(file_path) for file_path in file_paths))\n",
    "    print(f\"Original data shape: {data.shape}\")\n",
    "    return data\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:04:43.785217Z",
     "start_time": "2024-02-28T13:04:43.429035Z"
    }
   },
   "id": "883affb0ec11a93f",
   "execution_count": 1
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "def clean_data(data):\n",
    "    print(\"Starting data cleaning process...\")\n",
    "\n",
    "    # Calculate total number of missing values in the data\n",
    "    total_missing = data.isnull().sum().sum()\n",
    "    print(f\"Total number of missing values: {total_missing}\")\n",
    "\n",
    "    # Data has no missing values\n",
    "    data = data.dropna()\n",
    "    print(\"Missing values dropped.\")\n",
    "\n",
    "    # Data has no duplicate rows\n",
    "    data = data.drop_duplicates()\n",
    "    print(\"Duplicate rows dropped.\")\n",
    "\n",
    "    # Convert 'NLOS' column to integer data type (0 for LOS, 1 for NLOS)\n",
    "    data['NLOS'] = data['NLOS'].astype(int)\n",
    "    print(\"'NLOS' column converted to integer data type.\")\n",
    "\n",
    "    # Normalize 'Measured range (time of flight)' column using MinMaxScaler\n",
    "    scaler = MinMaxScaler()\n",
    "    data['RANGE'] = scaler.fit_transform(data[['RANGE']])\n",
    "    print(\"'RANGE' column normalized.\")\n",
    "\n",
    "    # Create new feature 'FP_SUM' by adding 'FP_AMP1', 'FP_AMP2', and 'FP_AMP3'\n",
    "    data['FP_SUM'] = data['FP_AMP1'] + data['FP_AMP2'] + data['FP_AMP3']\n",
    "    print(\"New feature 'FP_SUM' created.\")\n",
    "\n",
    "    # Create new feature 'SNR' by dividing 'CIR_PWR' by 'STDEV_NOISE'\n",
    "    data['SNR'] = data['CIR_PWR'] / data['STDEV_NOISE']\n",
    "    print(\"New feature 'SNR' created.\")\n",
    "\n",
    "    # One-hot encode categorical features\n",
    "    categorical_features = ['CH', 'FRAME_LEN', 'PREAM_LEN', 'BITRATE', 'PRFR']\n",
    "    encoder = LabelEncoder()\n",
    "    for feature in categorical_features:\n",
    "        data[feature] = encoder.fit_transform(data[feature])\n",
    "    print(\"Categorical features one-hot encoded.\")\n",
    "\n",
    "    # Extract the 'CIR' columns\n",
    "    cir_columns = [f\"CIR{i}\" for i in range(1016)]\n",
    "    cir_data = data[cir_columns]\n",
    "    print(\"'CIR' columns extracted.\")\n",
    "\n",
    "    # Standardize the 'CIR' columns\n",
    "    scaler = StandardScaler()\n",
    "    cir_data = scaler.fit_transform(cir_data)\n",
    "    print(\"'CIR' columns standardized.\")\n",
    "\n",
    "    # Perform PCA on the 'CIR' columns\n",
    "    pca = PCA(n_components=0.95)\n",
    "    cir_pca = pca.fit_transform(cir_data)\n",
    "    print(\"PCA performed on 'CIR' columns.\")\n",
    "\n",
    "    # Create a DataFrame with the principal components\n",
    "    cir_pca_df = pd.DataFrame(cir_pca, columns=[f\"PC{i}\" for i in range(1, pca.n_components_ + 1)])\n",
    "    print(\"DataFrame with principal components created.\")\n",
    "\n",
    "    # Drop the original 'CIR' columns from the data\n",
    "    data = data.drop(columns=cir_columns)\n",
    "    print(\"Original 'CIR' columns dropped.\")\n",
    "\n",
    "    # Add the principal components to the original data\n",
    "    # Reset the index of both dataframes\n",
    "    data = data.reset_index(drop=True)\n",
    "    cir_pca_df = cir_pca_df.reset_index(drop=True)\n",
    "    print(\"Indexes of both dataframes reset.\")\n",
    "\n",
    "    # Concatenate the dataframes\n",
    "    data = pd.concat([data, cir_pca_df], axis=1)\n",
    "    print(\"Dataframes concatenated.\")\n",
    "\n",
    "    # List of columns to check for unique values\n",
    "    columns_to_check = ['CH', 'PREAM_LEN', 'BITRATE', 'PRFR']\n",
    "\n",
    "    # Iterate over the columns\n",
    "    for column in columns_to_check:\n",
    "        # If the column has only one unique value, drop it\n",
    "        if data[column].nunique() == 1:\n",
    "            data = data.drop(column, axis=1)\n",
    "            print(f\"Column '{column}' dropped due to having only one unique value.\")\n",
    "\n",
    "    # Standardize the numerical columns (excluding 'NLOS')\n",
    "    numerical_cols = data.select_dtypes(include=[np.number]).columns\n",
    "    numerical_cols = numerical_cols.drop('NLOS')\n",
    "    scaler = StandardScaler()\n",
    "    data[numerical_cols] = scaler.fit_transform(data[numerical_cols])\n",
    "    print(\"Numerical columns standardized.\")\n",
    "\n",
    "    # Print the shape of the cleaned data\n",
    "    print(f\"Cleaned data shape: {data.shape}\")\n",
    "\n",
    "    print(\"Data cleaning process completed.\")\n",
    "    # Return the cleaned data\n",
    "    return data"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:04:44.283910Z",
     "start_time": "2024-02-28T13:04:43.786728Z"
    }
   },
   "id": "6da110e119fcb241",
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loading data from pickle file...\n",
      "Data loaded successfully.\n",
      "First few rows of the data:\n",
      "   NLOS     RANGE    FP_IDX   FP_AMP1   FP_AMP2   FP_AMP3  STDEV_NOISE  \\\n",
      "0     1  0.996831  0.742698 -0.600475  0.393039  0.135624     5.720436   \n",
      "1     1  0.300720 -1.033118 -1.048256 -1.511261 -1.521810    -0.146138   \n",
      "2     1  0.237051 -0.367187 -1.148380 -1.412951 -1.050793    -0.691866   \n",
      "3     1 -1.087256  0.520721  1.465434  1.008240  0.127403    -0.282570   \n",
      "4     0 -1.133947 -0.589164  2.214331  1.356897  1.118949     0.126726   \n",
      "\n",
      "    CIR_PWR  MAX_NOISE    RXPACC  ...     PC853     PC854     PC855     PC856  \\\n",
      "0 -0.150980   4.038101  1.329048  ... -0.404292  1.461861 -2.752515  0.597843   \n",
      "1 -0.666808  -0.489497  1.329048  ...  0.027621  0.013342  0.109247  0.849932   \n",
      "2 -1.406553  -0.892980  1.329048  ... -0.260973  1.325900  0.599507  2.509442   \n",
      "3  0.623982   0.365545 -0.955965  ...  0.218869 -0.619145  0.168861 -1.821147   \n",
      "4  0.369936   1.212001 -1.043975  ... -1.120861  0.308253 -0.601820 -0.364235   \n",
      "\n",
      "      PC857     PC858     PC859     PC860     PC861     PC862  \n",
      "0 -0.881172  0.038895 -1.766754 -0.299121 -0.523959  0.606114  \n",
      "1  2.423935 -0.549676  0.221286  0.521278  1.889760  1.685267  \n",
      "2  1.165853 -0.564825 -1.242861  2.311629 -0.225971 -0.951055  \n",
      "3  1.095607 -0.035574  0.606152  0.501785 -0.643971  0.185514  \n",
      "4  1.457933 -0.494171  0.164085 -0.409371 -2.974599  1.348899  \n",
      "\n",
      "[5 rows x 876 columns]\n",
      "Column headers:\n",
      "Index(['NLOS', 'RANGE', 'FP_IDX', 'FP_AMP1', 'FP_AMP2', 'FP_AMP3',\n",
      "       'STDEV_NOISE', 'CIR_PWR', 'MAX_NOISE', 'RXPACC',\n",
      "       ...\n",
      "       'PC853', 'PC854', 'PC855', 'PC856', 'PC857', 'PC858', 'PC859', 'PC860',\n",
      "       'PC861', 'PC862'],\n",
      "      dtype='object', length=876)\n"
     ]
    }
   ],
   "source": [
    "import pickle\n",
    "\n",
    "# Check if the file exists\n",
    "if os.path.exists('data.pkl'):\n",
    "    # If the file exists, load it\n",
    "    print(\"Loading data from pickle file...\")\n",
    "    with open('data.pkl', 'rb') as f:\n",
    "        data = pickle.load(f)\n",
    "    print(\"Data loaded successfully.\")\n",
    "else:\n",
    "    # If the file doesn't exist, load and clean the data\n",
    "    print(\"Pickle file not found. Loading and cleaning data...\")\n",
    "    data = load_data(DATASET_DIR)\n",
    "    data = clean_data(data)\n",
    "    print(\"Data loaded and cleaned successfully.\")\n",
    "    print(\"Saving cleaned data to pickle file...\")\n",
    "    with open('data.pkl', 'wb') as f:\n",
    "        pickle.dump(data, f)\n",
    "    print(\"Cleaned data saved to pickle file successfully.\")\n",
    "\n",
    "print(\"First few rows of the data:\")\n",
    "print(data.head())\n",
    "\n",
    "# Print Headers\n",
    "print(\"Column headers:\")\n",
    "print(data.columns)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:04:44.507940Z",
     "start_time": "2024-02-28T13:04:44.285169Z"
    }
   },
   "id": "e01fe23e950f89a",
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "MODEL_DIR = './models'\n",
    "\n",
    "def train_and_save_model(classifier, X_train, y_train, file_name):\n",
    "    if not os.path.exists(MODEL_DIR):\n",
    "        os.makedirs(MODEL_DIR)\n",
    "        \n",
    "    file_path = os.path.join(MODEL_DIR, file_name)\n",
    "    \n",
    "    # Check if the file exists\n",
    "    if not os.path.exists(file_path):\n",
    "        print(f\"Training the model and saving it to {file_path}\")\n",
    "        # Train the classifier\n",
    "        classifier.fit(X_train, y_train)\n",
    "\n",
    "        # Save the trained model as a pickle string.\n",
    "        saved_model = pickle.dumps(classifier)\n",
    "\n",
    "        # Save the pickled model to a file\n",
    "        with open(file_path, 'wb') as file:\n",
    "            file.write(saved_model)\n",
    "\n",
    "    # Load the pickled model from the file\n",
    "    with open(file_path, 'rb') as file:\n",
    "        loaded_model = pickle.load(file)\n",
    "    \n",
    "    return loaded_model"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:04:44.513613Z",
     "start_time": "2024-02-28T13:04:44.509109Z"
    }
   },
   "id": "c33f69f01c3106dd",
   "execution_count": 4
  },
  {
   "cell_type": "markdown",
   "source": [
    "The selected code is performing data standardization, which is a common preprocessing step in many machine learning workflows. \n",
    "\n",
    "The purpose of standardization is to transform the data such that it has a mean of 0 and a standard deviation of 1. This is done to ensure that all features have the same scale, which is a requirement for many machine learning algorithms.\n",
    "\n",
    "The mathematical formulas used in this process are as follows:\n",
    "\n",
    "1. Calculate the mean (μ) of the data:\n",
    "\n",
    "$$\n",
    "\\mu = \\frac{1}{n} \\sum_{i=1}^{n} x_i\n",
    "$$\n",
    "Where:\n",
    "- $n$ is the number of observations in the data\n",
    "- $x_i$ is the value of the $i$-th observation\n",
    "- $\\sum$ denotes the summation over all observations\n",
    "\n",
    "2. Standardize the data by subtracting the mean from each observation and dividing by the standard deviation:\n",
    "\n",
    "$$\n",
    "\\text{Data}_i = \\frac{x_i - \\mu}{\\sigma}\n",
    "$$\n",
    "Where:\n",
    "- $\\text{Data}_i$ is the standardized value of the $i$-th observation\n",
    "- $\\sigma$ is the standard deviation of the data\n",
    "- $x_i$ is the value of the $i$-th observation\n",
    "- $\\mu$ is the mean of the data\n",
    "\n",
    "The `StandardScaler` class from the `sklearn.preprocessing` module is used to perform this standardization. The `fit_transform` method is used to calculate the mean and standard deviation of the data and then perform the standardization.\n",
    "\n",
    "**Note:** By setting the explained variance to 0.95, we are saying that we want to choose the smallest number of principal components such that 95% of the variance in the original data is retained. This means that the transformed data will retain 95% of the information of the original data, while potentially having fewer dimensions.\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "2c13064e20601717"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Data Mining / Machine Learning\n",
    "\n",
    "### I. Supervised Learning\n",
    "- **Decision**: Supervised learning is used due to the labeled dataset.\n",
    "- **Algorithm**: Random Forest Classifier is preferred for its performance in classification tasks.\n",
    "\n",
    "### II. Training/Test Split Ratio\n",
    "- **Decision**: 70:30 split is chosen for training/test dataset.\n",
    "- **Reasoning**: This split ensures sufficient data for training and testing.\n",
    "\n",
    "### III. Performance Metrics\n",
    "- **Classification Accuracy**: Measures the proportion of correctly classified instances.\n",
    "- **Confusion Matrix**: Provides a summary of predicted and actual classes.\n",
    "- **Classification Report**: Provides detailed metrics such as precision, recall, F1-score, and support for each class.\n",
    "\n",
    "The Random Forest Classifier is trained on the training set and evaluated on the test set using accuracy and classification report metrics.\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "47d5cb383ce1f7ba"
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Split the data into training and testing sets\n",
    "\n",
    "The next step is to split the data into training and testing sets. This is a common practice in machine learning, where the training set is used to train the model, and the testing set is used to evaluate its performance.\n",
    "\n",
    "We will use the `train_test_split` function from the `sklearn.model_selection` module to split the data into training and testing sets. We will use 70% of the data for training and 30% for testing, which is a common split ratio."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "576a6a92fc7fdbfd"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15673    0\n",
      "2388     0\n",
      "40301    0\n",
      "5556     0\n",
      "31093    0\n",
      "        ..\n",
      "6265     0\n",
      "11284    1\n",
      "38158    0\n",
      "860      0\n",
      "15795    1\n",
      "Name: NLOS, Length: 29400, dtype: int64\n",
      "Y Test\n",
      "5457     1\n",
      "38509    1\n",
      "25536    1\n",
      "31803    1\n",
      "39863    1\n",
      "        ..\n",
      "20537    1\n",
      "16332    1\n",
      "15297    0\n",
      "41086    0\n",
      "6992     0\n",
      "Name: NLOS, Length: 12600, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "# Split the data into training and test sets\n",
    "X_train, X_test, y_train, y_test = train_test_split(data, data['NLOS'], test_size=0.3, random_state=42)\n",
    "\n",
    "print(f\"{y_train}\")\n",
    "print(\"Y Test\")\n",
    "print(f\"{y_test}\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:04:45.108139Z",
     "start_time": "2024-02-28T13:04:44.515796Z"
    }
   },
   "id": "7db852fafd187d5a",
   "execution_count": 5
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Train a Random Forest Classifier\n",
    "\n",
    "The next step is to train a machine learning model on the training data. We will use the `RandomForestClassifier` class from the `sklearn.ensemble` module to train a random forest classifier.\n",
    "\n",
    "The random forest classifier is an ensemble learning method that operates by constructing a multitude of decision trees at training time and outputting the class that is the mode of the classes (classification) or mean prediction (regression) of the individual trees.\n",
    "\n",
    "We will use the `fit` method of the `RandomForestClassifier` object to train the model on the training data."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "5753cc6db18bac73"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier\n",
    "\n",
    "# Initialize the classifier\n",
    "classifier = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "\n",
    "loaded_model = train_and_save_model(classifier, X_train, y_train, 'random_forest_classifier.pkl')\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:04:45.191273Z",
     "start_time": "2024-02-28T13:04:45.109303Z"
    }
   },
   "id": "b3617711d95450fb",
   "execution_count": 6
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Evaluate the Model\n",
    "\n",
    "To evaluate the performance of the trained model on the testing data, we will use the `predict` method of the `RandomForestClassifier` object to make predictions on the testing data. We will then use the `accuracy_score` and `classification_report` functions from the `sklearn.metrics` module to calculate the accuracy and generate a classification report.\n",
    "\n",
    "- **Accuracy:** The accuracy score function calculates the proportion of correctly classified instances.\n",
    "\n",
    "- **Precision:** The ratio of correctly predicted positive observations to the total predicted positive observations. It is calculated as:\n",
    "\n",
    "  $$\n",
    "  \\text{Precision} = \\frac{\\text{True Positives}}{\\text{True Positives} + \\text{False Positives}}\n",
    "  $$\n",
    "\n",
    "- **Recall:** The ratio of correctly predicted positive observations to all observations in the actual class. It is calculated as:\n",
    "\n",
    "  $$\n",
    "  \\text{Recall} = \\frac{\\text{True Positives}}{\\text{True Positives} + \\text{False Negatives}}\n",
    "  $$\n",
    "\n",
    "- **F1 Score:** The weighted average of precision and recall. It is calculated as:\n",
    "\n",
    "  $$\n",
    "  \\text{F1 Score} = 2 \\times \\frac{\\text{Precision} \\times \\text{Recall}}{\\text{Precision} + \\text{Recall}}\n",
    "  $$\n",
    "\n",
    "- **Support:** The number of actual occurrences of the class in the dataset.\n",
    "\n",
    "The classification report provides a summary of the precision, recall, F1-score, and support for each class in the testing data, giving insight into how well the model is performing for each class.\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "b63c56956f2f9620"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.9985714285714286\n",
      "Classification Report:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       1.00      1.00      1.00      6311\n",
      "           1       1.00      1.00      1.00      6289\n",
      "\n",
      "    accuracy                           1.00     12600\n",
      "   macro avg       1.00      1.00      1.00     12600\n",
      "weighted avg       1.00      1.00      1.00     12600\n",
      "\n",
      "Cross Validation Score: [0.9984127  0.99206349 0.9968254  0.99285714 0.99206349]\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score, classification_report\n",
    "from sklearn.model_selection import cross_val_score\n",
    "\n",
    "# Make predictions on the test set using the loaded model\n",
    "y_pred = loaded_model.predict(X_test)\n",
    "\n",
    "# Evaluate the loaded model\n",
    "accuracy = accuracy_score(y_test, y_pred)\n",
    "classification_rep = classification_report(y_test, y_pred)\n",
    "cross_val_score = cross_val_score(loaded_model, X_test, y_test, cv=5)\n",
    "\n",
    "print(f\"Accuracy: {accuracy}\")\n",
    "print(f\"Classification Report:\\n{classification_rep}\")\n",
    "print(f\"Cross Validation Score: {cross_val_score}\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:08:14.551608Z",
     "start_time": "2024-02-28T13:04:45.192819Z"
    }
   },
   "id": "1255f5a45a95e482",
   "execution_count": 7
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Visualize a Decision Tree from the Random Forest\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "3017b33cfb9a37df"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 2000x1000 with 1 Axes>",
      "image/png": "[encoded data, 662572 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.tree import plot_tree\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Select one tree from the forest\n",
    "estimator = loaded_model.estimators_[0]\n",
    "\n",
    "plt.figure(figsize=(20, 10))\n",
    "plot_tree(estimator,\n",
    "          filled=True,\n",
    "          rounded=True,\n",
    "          class_names=['NLOS', 'LOS'],\n",
    "          feature_names=data.columns)\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:05.398793Z",
     "start_time": "2024-02-28T13:08:14.552851Z"
    }
   },
   "id": "dbdf7b8e9d47e5d7",
   "execution_count": 8
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Support Vector Machine (SVM)"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "e1cb5279cf81744e"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of SVM: 1.0\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "from sklearn.svm import SVC\n",
    "import pickle\n",
    "\n",
    "svm = SVC(kernel='linear', random_state=42)\n",
    "loaded_model = train_and_save_model(svm, X_train, y_train, 'svm_classifier.pkl')\n",
    "\n",
    "# Predict the labels for the test set with each model\n",
    "y_pred_svm = loaded_model.predict(X_test)\n",
    "\n",
    "# Calculate the accuracy of each model\n",
    "accuracy_svm = accuracy_score(y_test, y_pred_svm)\n",
    "\n",
    "# Print the accuracy of each model\n",
    "print(f\"Accuracy of SVM: {accuracy_svm}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:41.428870Z",
     "start_time": "2024-02-28T13:09:05.399881Z"
    }
   },
   "id": "273bb5cbada1abde",
   "execution_count": 9
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Logistic Regression"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "a949d75ee11cb49f"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "\n",
    "# Logistic Regression\n",
    "log_reg = LogisticRegression(random_state=42)\n",
    "\n",
    "# Use the train_and_save_model function to train and save the model\n",
    "loaded_model = train_and_save_model(log_reg, X_train, y_train, 'logistic_regression_model.pkl')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:41.433486Z",
     "start_time": "2024-02-28T13:09:41.430161Z"
    }
   },
   "id": "c2c7f3004b9a19c3",
   "execution_count": 10
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of Logistic Regression: 1.0\n"
     ]
    }
   ],
   "source": [
    "y_pred_log_reg = loaded_model.predict(X_test)\n",
    "accuracy_log_reg = accuracy_score(y_test, y_pred_log_reg)\n",
    "print(f\"Accuracy of Logistic Regression: {accuracy_log_reg}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:41.532607Z",
     "start_time": "2024-02-28T13:09:41.434438Z"
    }
   },
   "id": "6881654084e029bf",
   "execution_count": 11
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Gradient Boosting Classifier"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "3f53342001156de3"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from sklearn.ensemble import GradientBoostingClassifier\n",
    "\n",
    "# Gradient Boosting Classifier\n",
    "gbc = GradientBoostingClassifier(random_state=42)\n",
    "\n",
    "# Use the train_and_save_model function to train and save the model\n",
    "loaded_model = train_and_save_model(gbc, X_train, y_train, 'gradient_boosting_classifier.pkl')\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:41.546322Z",
     "start_time": "2024-02-28T13:09:41.534776Z"
    }
   },
   "id": "b22ad2aa8c5bfadb",
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of Gradient Boosting Classifier: 1.0\n"
     ]
    }
   ],
   "source": [
    "y_pred_gbc = loaded_model.predict(X_test)\n",
    "accuracy_gbc = accuracy_score(y_test, y_pred_gbc)\n",
    "print(f\"Accuracy of Gradient Boosting Classifier: {accuracy_gbc}\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:41.722404Z",
     "start_time": "2024-02-28T13:09:41.548037Z"
    }
   },
   "id": "d115411c12fd5566",
   "execution_count": 13
  },
  {
   "cell_type": "markdown",
   "source": [
    "# K-Nearest Neighbors (KNN, K=3)"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "a71818e358518b6e"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "\n",
    "# K-Nearest Neighbors\n",
    "knn = KNeighborsClassifier(n_neighbors=3)\n",
    "loaded_model = train_and_save_model(knn, X_train, y_train, 'knn_classifier.pkl')\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:41.841869Z",
     "start_time": "2024-02-28T13:09:41.725405Z"
    }
   },
   "id": "7ec3197c11a1a20c",
   "execution_count": 14
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of K-Nearest Neighbors: 0.5292857142857142\n"
     ]
    }
   ],
   "source": [
    "y_pred_knn = loaded_model.predict(X_test)\n",
    "accuracy_knn = accuracy_score(y_test, y_pred_knn)\n",
    "print(f\"Accuracy of K-Nearest Neighbors: {accuracy_knn}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:46.879576Z",
     "start_time": "2024-02-28T13:09:41.843105Z"
    }
   },
   "id": "cf4df4ef7bbfd74",
   "execution_count": 15
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Naive Bayes"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "5b9b66f92968957c"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training the model and saving it to ./models/naive_bayes_classifier.pkl\n"
     ]
    }
   ],
   "source": [
    "from sklearn.naive_bayes import GaussianNB\n",
    "\n",
    "# Naive Bayes\n",
    "nb = GaussianNB()\n",
    "loaded_model = train_and_save_model(nb, X_train, y_train, 'naive_bayes_classifier.pkl')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:47.822616Z",
     "start_time": "2024-02-28T13:09:46.880737Z"
    }
   },
   "id": "3d984228fb1d3026",
   "execution_count": 16
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of Naive Bayes: 1.0\n"
     ]
    }
   ],
   "source": [
    "y_pred_nb = loaded_model.predict(X_test)\n",
    "accuracy_nb = accuracy_score(y_test, y_pred_nb)\n",
    "print(f\"Accuracy of Naive Bayes: {accuracy_nb}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:09:48.041382Z",
     "start_time": "2024-02-28T13:09:47.824289Z"
    }
   },
   "id": "98cd350871bc3201",
   "execution_count": 17
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Neural Network"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "862a9b7ee430a667"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2024-02-28 21:09:48.297789: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
      "2024-02-28 21:09:48.300559: I external/local_tsl/tsl/cuda/cudart_stub.cc:31] Could not find cuda drivers on your machine, GPU will not be used.\n",
      "2024-02-28 21:09:48.339610: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:9261] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
      "2024-02-28 21:09:48.339651: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:607] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
      "2024-02-28 21:09:48.340854: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1515] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
      "2024-02-28 21:09:48.347587: I external/local_tsl/tsl/cuda/cudart_stub.cc:31] Could not find cuda drivers on your machine, GPU will not be used.\n",
      "2024-02-28 21:09:48.348531: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
      "To enable the following instructions: AVX2 AVX512F AVX512_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
      "2024-02-28 21:09:49.398071: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT\n",
      "2024-02-28 21:09:50.109183: I external/local_xla/xla/stream_executor/cuda/cuda_executor.cc:901] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355\n",
      "2024-02-28 21:09:50.109641: W tensorflow/core/common_runtime/gpu/gpu_device.cc:2256] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.\n",
      "Skipping registering GPU devices...\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "919/919 [==============================] - 3s 2ms/step - loss: 0.2585 - accuracy: 0.8881 - val_loss: 0.0760 - val_accuracy: 0.9749\n",
      "Epoch 2/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 0.0224 - accuracy: 0.9935 - val_loss: 0.0367 - val_accuracy: 0.9879\n",
      "Epoch 3/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 0.0103 - accuracy: 0.9974 - val_loss: 0.0474 - val_accuracy: 0.9863\n",
      "Epoch 4/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 0.0102 - accuracy: 0.9973 - val_loss: 0.0212 - val_accuracy: 0.9930\n",
      "Epoch 5/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 7.9153e-04 - accuracy: 0.9998 - val_loss: 0.0157 - val_accuracy: 0.9948\n",
      "Epoch 6/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 0.0118 - accuracy: 0.9966 - val_loss: 0.0412 - val_accuracy: 0.9879\n",
      "Epoch 7/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 0.0054 - accuracy: 0.9980 - val_loss: 0.0106 - val_accuracy: 0.9972\n",
      "Epoch 8/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.6972e-04 - accuracy: 0.9999 - val_loss: 0.0093 - val_accuracy: 0.9978\n",
      "Epoch 9/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 7.1064e-05 - accuracy: 1.0000 - val_loss: 0.0074 - val_accuracy: 0.9982\n",
      "Epoch 10/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 2.4174e-05 - accuracy: 1.0000 - val_loss: 0.0073 - val_accuracy: 0.9983\n",
      "Epoch 11/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.4149e-05 - accuracy: 1.0000 - val_loss: 0.0071 - val_accuracy: 0.9983\n",
      "Epoch 12/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 8.8435e-06 - accuracy: 1.0000 - val_loss: 0.0069 - val_accuracy: 0.9983\n",
      "Epoch 13/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 5.5293e-06 - accuracy: 1.0000 - val_loss: 0.0068 - val_accuracy: 0.9983\n",
      "Epoch 14/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 3.4344e-06 - accuracy: 1.0000 - val_loss: 0.0066 - val_accuracy: 0.9983\n",
      "Epoch 15/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 2.1248e-06 - accuracy: 1.0000 - val_loss: 0.0065 - val_accuracy: 0.9983\n",
      "Epoch 16/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.3028e-06 - accuracy: 1.0000 - val_loss: 0.0064 - val_accuracy: 0.9983\n",
      "Epoch 17/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 7.9634e-07 - accuracy: 1.0000 - val_loss: 0.0063 - val_accuracy: 0.9983\n",
      "Epoch 18/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.8708e-07 - accuracy: 1.0000 - val_loss: 0.0062 - val_accuracy: 0.9983\n",
      "Epoch 19/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 2.9589e-07 - accuracy: 1.0000 - val_loss: 0.0062 - val_accuracy: 0.9984\n",
      "Epoch 20/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.7960e-07 - accuracy: 1.0000 - val_loss: 0.0061 - val_accuracy: 0.9985\n",
      "Epoch 21/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.0899e-07 - accuracy: 1.0000 - val_loss: 0.0060 - val_accuracy: 0.9987\n",
      "Epoch 22/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 6.6221e-08 - accuracy: 1.0000 - val_loss: 0.0059 - val_accuracy: 0.9987\n",
      "Epoch 23/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0393e-08 - accuracy: 1.0000 - val_loss: 0.0059 - val_accuracy: 0.9987\n",
      "Epoch 24/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 2.4722e-08 - accuracy: 1.0000 - val_loss: 0.0059 - val_accuracy: 0.9987\n",
      "Epoch 25/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.5220e-08 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9987\n",
      "Epoch 26/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 9.4746e-09 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9988\n",
      "Epoch 27/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 5.9841e-09 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9988\n",
      "Epoch 28/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 3.8579e-09 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9989\n",
      "Epoch 29/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 2.5531e-09 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9989\n",
      "Epoch 30/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.7377e-09 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9989\n",
      "Epoch 31/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 1.2435e-09 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9991\n",
      "Epoch 32/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 9.3591e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9991\n",
      "Epoch 33/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 7.6916e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9991\n",
      "Epoch 34/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 6.5892e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9991\n",
      "Epoch 35/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 5.9648e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 36/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 5.5771e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 37/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 5.3042e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 38/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 5.0945e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 39/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.9462e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 40/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.8185e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 41/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.6962e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9992\n",
      "Epoch 42/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.6606e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9993\n",
      "Epoch 43/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.5585e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 44/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.5607e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 45/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.5157e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 46/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.4747e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 47/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.4564e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 48/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.3868e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 49/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.3926e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 50/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.3541e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 51/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.3482e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 52/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.3250e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 53/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.3039e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 54/100\n",
      "919/919 [==============================] - 1s 2ms/step - loss: 4.2516e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 55/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2556e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 56/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2835e-10 - accuracy: 1.0000 - val_loss: 0.0056 - val_accuracy: 0.9994\n",
      "Epoch 57/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2752e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 58/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2564e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 59/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2665e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 60/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2899e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 61/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1864e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 62/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1494e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 63/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1904e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 64/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1719e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 65/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1763e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 66/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1278e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 67/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1636e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 68/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.2009e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 69/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1338e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 70/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1186e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 71/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1409e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 72/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1040e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 73/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1342e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 74/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1124e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 75/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0989e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 76/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0836e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 77/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1144e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 78/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1194e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 79/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1216e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 80/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.1059e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 81/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0818e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 82/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0291e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 83/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0815e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 84/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0646e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 85/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0420e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 86/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0515e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 87/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0538e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 88/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0687e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 89/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0333e-10 - accuracy: 1.0000 - val_loss: 0.0057 - val_accuracy: 0.9994\n",
      "Epoch 90/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0267e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 91/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0243e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 92/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0681e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 93/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0355e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 94/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0341e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 95/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0568e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 96/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0209e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 97/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0441e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 98/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0290e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 99/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 4.0662e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "Epoch 100/100\n",
      "919/919 [==============================] - 2s 2ms/step - loss: 3.9900e-10 - accuracy: 1.0000 - val_loss: 0.0058 - val_accuracy: 0.9994\n",
      "394/394 [==============================] - 0s 851us/step\n",
      "Accuracy: 0.9993650793650793\n"
     ]
    }
   ],
   "source": [
    "# Neural Network\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense\n",
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "# Define the model\n",
    "model = Sequential()\n",
    "model.add(Dense(32, input_dim=X_train.shape[1], activation='relu'))  # Input layer\n",
    "model.add(Dense(32, activation='relu'))  # Hidden layer\n",
    "model.add(Dense(1, activation='sigmoid'))  # Output layer\n",
    "\n",
    "# Compile the model\n",
    "model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
    "\n",
    "# Train the model\n",
    "model.fit(X_train, y_train, epochs=100, batch_size=32, validation_data=(X_test, y_test))\n",
    "\n",
    "# Make predictions on the test set\n",
    "y_pred_prob = model.predict(X_test)\n",
    "y_pred = (y_pred_prob > 0.5).astype(\"int32\")\n",
    "\n",
    "# Calculate the accuracy of the model\n",
    "accuracy = accuracy_score(y_test, y_pred)\n",
    "\n",
    "print(f\"Accuracy: {accuracy}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-02-28T13:12:31.036792Z",
     "start_time": "2024-02-28T13:09:48.042731Z"
    }
   },
   "id": "7b2464a3243d2114",
   "execution_count": 18
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
