diff --git "a/notebooks/01b_Classification models on incident category_ML Models.ipynb" "b/notebooks/01b_Classification models on incident category_ML Models.ipynb"
new file mode 100644--- /dev/null
+++ "b/notebooks/01b_Classification models on incident category_ML Models.ipynb"
@@ -0,0 +1,3668 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "feaf77ab",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "workding dir: /Users/inflaton/code/engd/papers/maritime/global-incidents\n",
+ "loading env vars from: /Users/inflaton/code/engd/papers/maritime/global-incidents/.env\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 1,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import os\n",
+ "import sys\n",
+ "from pathlib import Path\n",
+ "\n",
+ "workding_dir = str(Path.cwd().parent)\n",
+ "os.chdir(workding_dir)\n",
+ "sys.path.append(workding_dir)\n",
+ "print(\"workding dir:\", workding_dir)\n",
+ "\n",
+ "from dotenv import find_dotenv, load_dotenv\n",
+ "\n",
+ "found_dotenv = find_dotenv(\".env\")\n",
+ "\n",
+ "if len(found_dotenv) == 0:\n",
+ " found_dotenv = find_dotenv(\".env.example\")\n",
+ "print(f\"loading env vars from: {found_dotenv}\")\n",
+ "load_dotenv(found_dotenv, override=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3a7dd7d8",
+ "metadata": {},
+ "source": [
+ "## Import Statement"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "86fc25e6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fac53e88",
+ "metadata": {},
+ "source": [
+ "### read the data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "dc33b13b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result_df = pd.read_csv(\"data/processed_data.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "31f58fd1",
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " Details \n",
+ " Category \n",
+ " Details_cleaned \n",
+ " Category_cleaned \n",
+ " Category_single \n",
+ " Summarized_label \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 \n",
+ " Media sources indicate that workers at the Gra... \n",
+ " Mine Workers Strike \n",
+ " medium source indicate worker grasberg mine ex... \n",
+ " Mine Workers Strike \n",
+ " Mine Workers Strike \n",
+ " Worker Strike \n",
+ " \n",
+ " \n",
+ " 1 \n",
+ " News sources are stating that recent typhoons ... \n",
+ " Travel Warning \n",
+ " news source stating recent typhoon impact hong... \n",
+ " Travel Warning \n",
+ " Travel Warning \n",
+ " Administrative Issue \n",
+ " \n",
+ " \n",
+ " 2 \n",
+ " The persisting port congestion at Shanghai’s Y... \n",
+ " Port Congestion \n",
+ " persisting port congestion shanghai ’ yangshan... \n",
+ " Port Congestion \n",
+ " Port Congestion \n",
+ " Administrative Issue \n",
+ " \n",
+ " \n",
+ " 3 \n",
+ " Updated local media sources from Jakarta indic... \n",
+ " Bombing, Police Operations \n",
+ " updated local medium source jakarta indicate e... \n",
+ " Bombing, Police Operations \n",
+ " Bombing \n",
+ " Terrorism \n",
+ " \n",
+ " \n",
+ " 4 \n",
+ " According to local police in Jakarta, two expl... \n",
+ " Bombing, Police Operations \n",
+ " according local police jakarta two explosion c... \n",
+ " Bombing, Police Operations \n",
+ " Bombing \n",
+ " Terrorism \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Details \\\n",
+ "0 Media sources indicate that workers at the Gra... \n",
+ "1 News sources are stating that recent typhoons ... \n",
+ "2 The persisting port congestion at Shanghai’s Y... \n",
+ "3 Updated local media sources from Jakarta indic... \n",
+ "4 According to local police in Jakarta, two expl... \n",
+ "\n",
+ " Category \\\n",
+ "0 Mine Workers Strike \n",
+ "1 Travel Warning \n",
+ "2 Port Congestion \n",
+ "3 Bombing, Police Operations \n",
+ "4 Bombing, Police Operations \n",
+ "\n",
+ " Details_cleaned \\\n",
+ "0 medium source indicate worker grasberg mine ex... \n",
+ "1 news source stating recent typhoon impact hong... \n",
+ "2 persisting port congestion shanghai ’ yangshan... \n",
+ "3 updated local medium source jakarta indicate e... \n",
+ "4 according local police jakarta two explosion c... \n",
+ "\n",
+ " Category_cleaned Category_single Summarized_label \n",
+ "0 Mine Workers Strike Mine Workers Strike Worker Strike \n",
+ "1 Travel Warning Travel Warning Administrative Issue \n",
+ "2 Port Congestion Port Congestion Administrative Issue \n",
+ "3 Bombing, Police Operations Bombing Terrorism \n",
+ "4 Bombing, Police Operations Bombing Terrorism "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "result_df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "607a0996",
+ "metadata": {},
+ "source": [
+ "## Naive Bayes Model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "b8c331bd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.feature_extraction.text import TfidfVectorizer\n",
+ "\n",
+ "# from sklearn.feature_extraction.text import CountVectorizer\n",
+ "from sklearn.naive_bayes import MultinomialNB\n",
+ "from sklearn.metrics import accuracy_score, classification_report"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "ca8d53af",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X = result_df[\"Details_cleaned\"]\n",
+ "y = result_df[\"Summarized_label\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "432e793e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "119b6c46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# vectorizer = CountVectorizer()\n",
+ "# X_train_vec = vectorizer.fit_transform(X_train)\n",
+ "# X_test_vec = vectorizer.transform(X_test)\n",
+ "\n",
+ "tfidf_vectorizer = TfidfVectorizer(max_features=1000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "18cf6e8e",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "MultinomialNB() In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org. "
+ ],
+ "text/plain": [
+ "MultinomialNB()"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "naive_bayes = MultinomialNB()\n",
+ "naive_bayes.fit(X_train_tfidf, y_train)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "4e4d6e2e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "predictions = naive_bayes.predict(X_test_tfidf)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "abd1d4a6",
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of Naive Bayes model: 0.763840830449827\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.71 0.74 0.72 129\n",
+ "Administrative Issue 0.83 0.89 0.86 662\n",
+ " Cyber Attack 0.00 0.00 0.00 4\n",
+ " Human Error 0.00 0.00 0.00 18\n",
+ " Others 0.41 0.24 0.30 79\n",
+ " Terrorism 0.42 0.15 0.23 52\n",
+ " Weather 0.77 0.92 0.84 92\n",
+ " Worker Strike 0.61 0.69 0.65 120\n",
+ "\n",
+ " accuracy 0.76 1156\n",
+ " macro avg 0.47 0.46 0.45 1156\n",
+ " weighted avg 0.73 0.76 0.74 1156\n",
+ "\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1517: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
+ " _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1517: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
+ " _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1517: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
+ " _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n"
+ ]
+ }
+ ],
+ "source": [
+ "accuracy = accuracy_score(y_test, predictions)\n",
+ "print(\"Accuracy of Naive Bayes model:\", accuracy)\n",
+ "print(classification_report(y_test, predictions))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0bb9d98b",
+ "metadata": {},
+ "source": [
+ "Find the optimal Alpha parameter"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "f4eead05",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best Alpha: 0.1\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "MultinomialNB(alpha=0.1) In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org. "
+ ],
+ "text/plain": [
+ "MultinomialNB(alpha=0.1)"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from sklearn.model_selection import GridSearchCV\n",
+ "\n",
+ "param_grid = {\"alpha\": [0.1, 0.5, 1.0, 2.0]}\n",
+ "\n",
+ "# Initialize the grid search\n",
+ "grid_search = GridSearchCV(MultinomialNB(), param_grid, cv=5, scoring=\"accuracy\")\n",
+ "\n",
+ "# Perform the grid search\n",
+ "grid_search.fit(X_train_tfidf, y_train)\n",
+ "\n",
+ "# Get the best hyperparameters\n",
+ "best_alpha = grid_search.best_params_[\"alpha\"]\n",
+ "print(\"Best Alpha:\", best_alpha)\n",
+ "\n",
+ "# Train the model with the best alpha\n",
+ "naive_bayes_tuned = MultinomialNB(alpha=best_alpha)\n",
+ "naive_bayes_tuned.fit(X_train_tfidf, y_train)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5c747eab",
+ "metadata": {},
+ "source": [
+ "Change the Alpha to 0.1 and max_features to 4000 for better performance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "71d0742f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import time"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "b22c1073",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of Naive Bayes model: 0.7923875432525952\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.74 0.84 0.79 129\n",
+ "Administrative Issue 0.89 0.87 0.88 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.67 0.22 0.33 18\n",
+ " Others 0.45 0.35 0.40 79\n",
+ " Terrorism 0.54 0.40 0.46 52\n",
+ " Weather 0.77 0.93 0.85 92\n",
+ " Worker Strike 0.65 0.75 0.69 120\n",
+ "\n",
+ " accuracy 0.79 1156\n",
+ " macro avg 0.71 0.58 0.60 1156\n",
+ " weighted avg 0.79 0.79 0.79 1156\n",
+ "\n",
+ "Total Runtime: 0.11176609992980957\n"
+ ]
+ }
+ ],
+ "source": [
+ "X = result_df[\"Details_cleaned\"]\n",
+ "y = result_df[\"Summarized_label\"]\n",
+ "\n",
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "start_time = time.time()\n",
+ "tfidf_vectorizer = TfidfVectorizer(max_features=4000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)\n",
+ "\n",
+ "naive_bayes = MultinomialNB(alpha=0.1)\n",
+ "naive_bayes.fit(X_train_tfidf, y_train)\n",
+ "\n",
+ "predictions = naive_bayes.predict(X_test_tfidf)\n",
+ "\n",
+ "end_time = time.time()\n",
+ "total_runtime = end_time - start_time\n",
+ "\n",
+ "accuracy = accuracy_score(y_test, predictions)\n",
+ "print(\"Accuracy of Naive Bayes model:\", accuracy)\n",
+ "print(classification_report(y_test, predictions))\n",
+ "\n",
+ "print(\"Total Runtime:\", total_runtime)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "aa011ad5",
+ "metadata": {},
+ "source": [
+ "## Logistic Regression model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "6e735f18",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.feature_extraction.text import TfidfVectorizer\n",
+ "from sklearn.linear_model import LogisticRegression\n",
+ "from sklearn.metrics import accuracy_score"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "e266616c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "b1314e98",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tfidf_vectorizer = TfidfVectorizer(max_features=1000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "87905c28",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "LogisticRegression() In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org. "
+ ],
+ "text/plain": [
+ "LogisticRegression()"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "model = LogisticRegression()\n",
+ "model.fit(X_train_tfidf, y_train)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "c4bf008a",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of Logistic Regression Model: 0.7975778546712803\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.79 0.81 0.80 129\n",
+ "Administrative Issue 0.83 0.93 0.88 662\n",
+ " Cyber Attack 0.00 0.00 0.00 4\n",
+ " Human Error 0.00 0.00 0.00 18\n",
+ " Others 0.64 0.34 0.45 79\n",
+ " Terrorism 0.46 0.21 0.29 52\n",
+ " Weather 0.83 0.87 0.85 92\n",
+ " Worker Strike 0.69 0.71 0.70 120\n",
+ "\n",
+ " accuracy 0.80 1156\n",
+ " macro avg 0.53 0.48 0.50 1156\n",
+ " weighted avg 0.77 0.80 0.78 1156\n",
+ "\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1517: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
+ " _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1517: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
+ " _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1517: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
+ " _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n"
+ ]
+ }
+ ],
+ "source": [
+ "y_pred = model.predict(X_test_tfidf)\n",
+ "\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of Logistic Regression Model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "69b1b25a",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/linear_model/_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n",
+ "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n",
+ "\n",
+ "Increase the number of iterations (max_iter) or scale the data as shown in:\n",
+ " https://scikit-learn.org/stable/modules/preprocessing.html\n",
+ "Please also refer to the documentation for alternative solver options:\n",
+ " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n",
+ " n_iter_i = _check_optimize_result(\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best Parameters: {'model__C': 10.0, 'tfidf__max_features': 2000}\n",
+ "Accuracy of Tuned Logistic Regression Model: 0.8200692041522492\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.81 0.86 0.83 129\n",
+ "Administrative Issue 0.86 0.91 0.88 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.60 0.17 0.26 18\n",
+ " Others 0.61 0.43 0.50 79\n",
+ " Terrorism 0.61 0.44 0.51 52\n",
+ " Weather 0.87 0.90 0.89 92\n",
+ " Worker Strike 0.73 0.75 0.74 120\n",
+ "\n",
+ " accuracy 0.82 1156\n",
+ " macro avg 0.76 0.59 0.63 1156\n",
+ " weighted avg 0.81 0.82 0.81 1156\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "from sklearn.pipeline import Pipeline\n",
+ "\n",
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "param_grid = {\n",
+ " \"tfidf__max_features\": [500, 1000, 2000, 3000, 4000],\n",
+ " \"model__C\": [0.1, 1.0, 10.0],\n",
+ "}\n",
+ "\n",
+ "pipeline = Pipeline([(\"tfidf\", TfidfVectorizer()), (\"model\", LogisticRegression())])\n",
+ "\n",
+ "grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring=\"accuracy\")\n",
+ "\n",
+ "grid_search.fit(X_train, y_train)\n",
+ "\n",
+ "best_params = grid_search.best_params_\n",
+ "print(\"Best Parameters:\", best_params)\n",
+ "\n",
+ "best_model = grid_search.best_estimator_\n",
+ "best_model.fit(X_train, y_train)\n",
+ "\n",
+ "y_pred = best_model.predict(X_test)\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of Tuned Logistic Regression Model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c74436a2",
+ "metadata": {},
+ "source": [
+ "The best parameters are 'model__C': 10.0, 'tfidf__max_features': 2000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "7d7e7e31",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of Logistic Regression Model: 0.8200692041522492\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.81 0.86 0.83 129\n",
+ "Administrative Issue 0.86 0.91 0.88 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.60 0.17 0.26 18\n",
+ " Others 0.61 0.43 0.50 79\n",
+ " Terrorism 0.61 0.44 0.51 52\n",
+ " Weather 0.87 0.90 0.89 92\n",
+ " Worker Strike 0.73 0.75 0.74 120\n",
+ "\n",
+ " accuracy 0.82 1156\n",
+ " macro avg 0.76 0.59 0.63 1156\n",
+ " weighted avg 0.81 0.82 0.81 1156\n",
+ "\n",
+ "Total Runtime: 0.3430769443511963\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "start_time = time.time()\n",
+ "tfidf_vectorizer = TfidfVectorizer(max_features=2000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)\n",
+ "\n",
+ "model = LogisticRegression(C=10.0)\n",
+ "model.fit(X_train_tfidf, y_train)\n",
+ "\n",
+ "y_pred = model.predict(X_test_tfidf)\n",
+ "\n",
+ "end_time = time.time()\n",
+ "total_runtime = end_time - start_time\n",
+ "\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of Logistic Regression Model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))\n",
+ "\n",
+ "print(\"Total Runtime:\", total_runtime)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "482d0503",
+ "metadata": {},
+ "source": [
+ "## Support Vector Machine (SVM) model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "9a2b2117",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.feature_extraction.text import TfidfVectorizer\n",
+ "from sklearn.svm import SVC\n",
+ "from sklearn.metrics import accuracy_score"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "f8e29f39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "id": "246cca7a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tfidf_vectorizer = TfidfVectorizer(max_features=1000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "id": "393b87b3",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "SVC(kernel='linear') In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org. "
+ ],
+ "text/plain": [
+ "SVC(kernel='linear')"
+ ]
+ },
+ "execution_count": 26,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "svm_model = SVC(kernel=\"linear\")\n",
+ "svm_model.fit(X_train_tfidf, y_train)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "fc25cdcf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_pred = svm_model.predict(X_test_tfidf)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "id": "2960279a",
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of SVM model: 0.8183391003460208\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.78 0.82 0.80 129\n",
+ "Administrative Issue 0.87 0.92 0.89 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.67 0.11 0.19 18\n",
+ " Others 0.62 0.42 0.50 79\n",
+ " Terrorism 0.55 0.31 0.40 52\n",
+ " Weather 0.82 0.90 0.86 92\n",
+ " Worker Strike 0.72 0.80 0.76 120\n",
+ "\n",
+ " accuracy 0.82 1156\n",
+ " macro avg 0.75 0.57 0.60 1156\n",
+ " weighted avg 0.81 0.82 0.80 1156\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of SVM model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "id": "4e9fee70",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best C: 10\n"
+ ]
+ }
+ ],
+ "source": [
+ "from sklearn.model_selection import GridSearchCV\n",
+ "\n",
+ "param_grid = {\"C\": [0.1, 1, 10]}\n",
+ "svm = SVC()\n",
+ "grid_search = GridSearchCV(svm, param_grid, cv=5, scoring=\"accuracy\")\n",
+ "grid_search.fit(X_train_tfidf, y_train)\n",
+ "best_c = grid_search.best_params_[\"C\"]\n",
+ "print(\"Best C:\", best_c)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "id": "65fd932b-63e8-4041-b7aa-0fae14e48efe",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of SVM model: 0.782871972318339\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.72 0.84 0.77 129\n",
+ "Administrative Issue 0.86 0.86 0.86 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.62 0.28 0.38 18\n",
+ " Others 0.51 0.46 0.48 79\n",
+ " Terrorism 0.49 0.38 0.43 52\n",
+ " Weather 0.81 0.87 0.84 92\n",
+ " Worker Strike 0.69 0.69 0.69 120\n",
+ "\n",
+ " accuracy 0.78 1156\n",
+ " macro avg 0.71 0.58 0.61 1156\n",
+ " weighted avg 0.78 0.78 0.78 1156\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "tfidf_vectorizer = TfidfVectorizer(max_features=1000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)\n",
+ "\n",
+ "svm_model = SVC(kernel=\"linear\", C=10)\n",
+ "svm_model.fit(X_train_tfidf, y_train)\n",
+ "\n",
+ "y_pred = svm_model.predict(X_test_tfidf)\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of SVM model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a2843fa9",
+ "metadata": {},
+ "source": [
+ "But when C is set to 10, the accuracy drops, it may be due to overfitting. We will still use the defaul value C=1.0"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "id": "afffe960",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of SVM model: 0.8217993079584776\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.82 0.86 0.84 129\n",
+ "Administrative Issue 0.86 0.93 0.89 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.00 0.00 0.00 18\n",
+ " Others 0.64 0.41 0.50 79\n",
+ " Terrorism 0.61 0.33 0.42 52\n",
+ " Weather 0.83 0.90 0.86 92\n",
+ " Worker Strike 0.71 0.77 0.74 120\n",
+ "\n",
+ " accuracy 0.82 1156\n",
+ " macro avg 0.68 0.55 0.58 1156\n",
+ " weighted avg 0.80 0.82 0.81 1156\n",
+ "\n",
+ "Total Runtime: 3.328857660293579\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "start_time = time.time()\n",
+ "tfidf_vectorizer = TfidfVectorizer(max_features=2000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)\n",
+ "\n",
+ "svm_model = SVC(kernel=\"linear\")\n",
+ "svm_model.fit(X_train_tfidf, y_train)\n",
+ "\n",
+ "y_pred = svm_model.predict(X_test_tfidf)\n",
+ "\n",
+ "end_time = time.time()\n",
+ "total_runtime = end_time - start_time\n",
+ "\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of SVM model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))\n",
+ "\n",
+ "print(\"Total Runtime:\", total_runtime)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "deac9dd7",
+ "metadata": {},
+ "source": [
+ "## Random Forest Model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "id": "fba3d3c4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.feature_extraction.text import TfidfVectorizer\n",
+ "from sklearn.ensemble import RandomForestClassifier\n",
+ "from sklearn.metrics import accuracy_score"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "id": "390399c2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "id": "74d99fe7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tfidf_vectorizer = TfidfVectorizer(max_features=1000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "id": "f37ceeae",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "RandomForestClassifier(random_state=42) In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org. "
+ ],
+ "text/plain": [
+ "RandomForestClassifier(random_state=42)"
+ ]
+ },
+ "execution_count": 35,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "rf_model = RandomForestClassifier(n_estimators=100, random_state=42)\n",
+ "rf_model.fit(X_train_tfidf, y_train)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "id": "51cbc1c4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_pred = rf_model.predict(X_test_tfidf)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 37,
+ "id": "688925b0",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of Random Forest Model: 0.801038062283737\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.77 0.80 0.79 129\n",
+ "Administrative Issue 0.84 0.92 0.88 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.50 0.06 0.10 18\n",
+ " Others 0.72 0.39 0.51 79\n",
+ " Terrorism 0.67 0.19 0.30 52\n",
+ " Weather 0.79 0.86 0.82 92\n",
+ " Worker Strike 0.66 0.77 0.71 120\n",
+ "\n",
+ " accuracy 0.80 1156\n",
+ " macro avg 0.74 0.53 0.56 1156\n",
+ " weighted avg 0.79 0.80 0.78 1156\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of Random Forest Model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4b919b55",
+ "metadata": {},
+ "source": [
+ "Fine tuning by adjusting the hyperparamters. After testing on the hyperparameters, below are the best parameters for this model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 38,
+ "id": "6b4868ef",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy of Random Forest Model: 0.8070934256055363\n",
+ " precision recall f1-score support\n",
+ "\n",
+ " Accident 0.80 0.79 0.80 129\n",
+ "Administrative Issue 0.83 0.94 0.88 662\n",
+ " Cyber Attack 1.00 0.25 0.40 4\n",
+ " Human Error 0.50 0.06 0.10 18\n",
+ " Others 0.74 0.41 0.52 79\n",
+ " Terrorism 0.86 0.12 0.20 52\n",
+ " Weather 0.82 0.85 0.83 92\n",
+ " Worker Strike 0.67 0.78 0.72 120\n",
+ "\n",
+ " accuracy 0.81 1156\n",
+ " macro avg 0.78 0.52 0.56 1156\n",
+ " weighted avg 0.80 0.81 0.78 1156\n",
+ "\n",
+ "Total Runtime: 2.476357936859131\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "start_time = time.time()\n",
+ "tfidf_vectorizer = TfidfVectorizer(max_features=2000)\n",
+ "X_train_tfidf = tfidf_vectorizer.fit_transform(X_train)\n",
+ "X_test_tfidf = tfidf_vectorizer.transform(X_test)\n",
+ "\n",
+ "rf_model = RandomForestClassifier(\n",
+ " n_estimators=300, min_samples_split=5, random_state=42\n",
+ ")\n",
+ "rf_model.fit(X_train_tfidf, y_train)\n",
+ "\n",
+ "y_pred = rf_model.predict(X_test_tfidf)\n",
+ "end_time = time.time()\n",
+ "total_runtime = end_time - start_time\n",
+ "\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy of Random Forest Model:\", accuracy)\n",
+ "print(classification_report(y_test, y_pred))\n",
+ "\n",
+ "print(\"Total Runtime:\", total_runtime)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7df52b09",
+ "metadata": {},
+ "source": [
+ "### KNN"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 39,
+ "id": "b8822f38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sklearn.feature_extraction.text import TfidfVectorizer\n",
+ "from sklearn.neighbors import KNeighborsClassifier\n",
+ "from sklearn.metrics import accuracy_score\n",
+ "from sklearn.model_selection import train_test_split"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 40,
+ "id": "368a2dd1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "vectorizer = TfidfVectorizer(max_features=2000)\n",
+ "X = vectorizer.fit_transform(X)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "id": "ae8bae0b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "id": "3ef3809f",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy: 0.7889273356401384\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Step 4: Apply KNN Algorithm\n",
+ "k = 5 # Number of neighbors\n",
+ "knn_model = KNeighborsClassifier(n_neighbors=k)\n",
+ "knn_model.fit(X_train, y_train)\n",
+ "\n",
+ "# Step 5: Make Predictions and Evaluate Performance\n",
+ "y_pred = knn_model.predict(X_test)\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy:\", accuracy)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cca13522-7877-4f1f-9b15-d8fb6fd55d12",
+ "metadata": {},
+ "source": [
+ "Plot the model's performance against values of k to find the optimal k"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "id": "67102a37-2286-442f-b270-d3c00614dd9c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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uCIiIiIisjiGq2asg25aYFohtFp2DCQiIiIisiSGq2YsyMMBtjYylKg1uJlTYulyiIiIiIhaNYarZsxGLkN7b2lqINddERERERFZFsNVM6e7mPBlhisiIiIiIotiuGrmOvhKI1cMV0RERERElsVw1czprnV1ide6IiIiIiKyKIarZk53ratrGUUo12gtXA0RERERUevFcNXMBbrZw8FWjjKNFtezii1dDhERERFRq8Vw1czJZEKV611xaiARERERkaUwXLUA4RVNLbjuioiIiIjIchiuWoCOHLkiIiIiIrI4hqsWgOGKiIiIiMjyGK5aAN2FhK9nFUOl1li4GiIiIiKi1onhqgXwcbaDq70CGq2IaxlFli6HiIiIiKhVYrhqAQRB0F9MmFMDiYiIiIgsg+GqhehQ0TGQ4YqIiIiIyDIYrloI3borhisiIiIiIstguGohdB0DLzFcERERERFZBMNVC6ELVzeyS1BUWm7haoiIiIiIWh+GqxbCw9EWXk52AID49EILV0NERERE1PowXLUg4X5SUwtODSQiIiIianoMVy2Ibmrg5VSGKyIiIiKipsZw1YKEs6kFEREREZHFMFy1IB0qwtWVNK65IiIiIiJqagxXLUjHigsJp+arkFestnA1REREREStC8NVC+KsVCDQzR4AcDmdUwOJiIiIiJoSw1ULoxu9usSmFkRERERETYrhqoXpqF93xXBFRERERNSUGK5amI7sGEhEREREZBEMVy1MuF9FuEotgCiKFq6GiIiIiKj1YLhqYdr7OEEQgJxiNTILyyxdDhERERFRq8Fw1cIoFXIEeTgA4LorIiIiIqKmxHDVAnHdFRERERFR02O4aoF0664uM1wRERERETUZhqsWSD9yxWtdERERERE1GYarFqjyWleF7BhIRERERNREGK5aoBAvR9jIBBSUliMlT2XpcoiIiIiIWgWLh6uPPvoIwcHBUCqViIqKwrFjx2o8Vq1WY9myZQgLC4NSqUSPHj2wZ88eg2OWLFkCQRAMtk6dOjX2y7AqtjYyhHo7AmBTCyIiIiKipmLRcLVlyxbMmzcPMTExOHXqFHr06IGRI0ciPT3d6PELFy7EJ598gg8//BBxcXF4+umnMX78eJw+fdrguC5duiAlJUW//fnnn03xcqxKh4qpgZe57oqIiIiIqElYNFytWrUKs2fPxowZMxAREYG1a9fCwcEB69atM3r8hg0b8Oqrr2L06NEIDQ3FnDlzMHr0aKxcudLgOBsbG/j5+ek3Ly+vpng5ViVcF67SCi1cCRERERFR62BjqScuKyvDyZMn8corr+j3yWQy3HfffThy5IjRx5SWlkKpVBrss7e3rzYydeXKFQQEBECpVKJ///5Yvnw52rVrV2MtpaWlKC0t1d/Oz88HIE1DVKvV9X5t5qR7/vrWEeZlDwC4lJpv9tfQ0JoaE2synTXWxZpMw5pMw5pMw5pMw5pMY401AdZZF2syjTXVVJ8aBNFC7eRu3bqFwMBAHD58GP3799fvf+mll/D777/j6NGj1R4zefJk/P3339i+fTvCwsKwb98+PPjgg9BoNPpwtHv3bhQWFiI8PBwpKSlYunQpkpOTce7cOTg7OxutZcmSJVi6dGm1/Zs2bYKDg4OZXnHTSi8B3oy1gUImYkU/DWSCpSsiIiIiImp+iouLMXnyZOTl5cHFxaXWYy02ctUQ77//PmbPno1OnTpBEASEhYVhxowZBtMIR40apf+8e/fuiIqKQlBQEL777jvMmjXL6HlfeeUVzJs3T387Pz8fbdu2xYgRI+r8AjY2tVqNvXv3Yvjw4VAoFCY/TqMV8e65fSgt16LbXUMR5Gm+kNjQmhoTazKdNdbFmkzDmkzDmkzDmkzDmkxjjTUB1lkXazKNNdWkm9VmCouFKy8vL8jlcqSlpRnsT0tLg5+fn9HHeHt7Y/v27VCpVMjKykJAQAAWLFiA0NDQGp/Hzc0NHTt2RHx8fI3H2NnZwc7Ortp+hUJh8W+mTn1rUQBo7+OE87fycS2rBO39XC1eU1NgTaazxrpYk2lYk2lYk2lYk2lYk2mssSbAOutiTaaxhprq8/wWa2hha2uL3r17Y9++ffp9Wq0W+/btM5gmaIxSqURgYCDKy8vx448/4sEHH6zx2MLCQly9ehX+/v5mq725qGxqwY6BRERERESNzaLdAufNm4fPPvsMX331FS5cuIA5c+agqKgIM2bMAABMnTrVoOHF0aNHsXXrVly7dg1//PEHoqOjodVq8dJLL+mPmT9/Pn7//Xdcv34dhw8fxvjx4yGXyzFp0qQmf32W1tFPCleX2DGQiIiIiKjRWXTN1WOPPYaMjAwsXrwYqampiIyMxJ49e+Dr6wsASEpKgkxWmf9UKhUWLlyIa9euwcnJCaNHj8aGDRvg5uamP+bmzZuYNGkSsrKy4O3tjYEDB+Kvv/6Ct7d3U788i+vo6wSA17oiIiIiImoKFm9oMXfuXMydO9fofQcOHDC4PWTIEMTFxdV6vs2bN5urtGavY8W0wGuZhVBrtFDILTpQSURERETUovHddgsW6GYPR1s51BoR1zOLLF0OEREREVGLxnDVggmCUGXdFacGEhERERE1JoarFq6jT0XHQK67IiIiIiJqVAxXLZxu5OoyOwYSERERETUqhqsWjte6IiIiIiJqGgxXLVxHP6kd+/WsIqjUGgtXQ0RERETUcjFctXDeTnZwc1BAKwLx6ZwaSERERETUWBiuWjhBEPTXu7qSzqmBRERERESNheGqFdCtu7qUypErIiIiIqLGwnDVClR2DOTIFRERERFRY2G4agU6+khNLS7xWldERERERI2G4aoV0K25Ss4tQWFpuYWrISIiIiJqmRiuWgF3R1v4ONsBAK5waiARERERUaNguGolwrnuioiIiIioUTFctRIdfHThih0DiYiIiIgaA8NVKxHuJzW14MgVEREREVHjYLhqJTrqr3XFcEVERERE1BgYrlqJDhXhKr2gFLnFZRauhoiIiIio5WG4aiWc7GwQ6GYPgOuuiIiIiIgaA8NVK6LrGHiJ666IiIiIiMyO4aoV0a27usx1V0REREREZsdw1Yp09JU6BnLkioiIiIjI/BiuWhHdyNWVtAKIomjhaoiIiIiIWhaGq1akvY8TZAKQU6xGRmGppcshIiIiImpRGK5aEaVCjmBPRwDA5VR2DCQiIiIiMieGq1amA9ddERERERE1CoarVia8yrorIiIiIiIyH4arVqYjr3VFRERERNQoGK5amfAq17pix0AiIiIiIvNhuGplgr0coZALKCrTIDm3xNLlEBERERG1GAxXrYxCLkOol9TU4koaOwYSEREREZkLw1UrxHVXRERERETmx3DVCoVXtGO/nMpwRURERERkLgxXrVAHX45cERERERGZG8NVK6TrGBifXgiNlh0DiYiIiIjMgeGqFWrr4QClQobSci2SsostXQ4RERERUYvAcNUKyWUCOvhUTA3kuisiIiIiIrNguGqlOuiaWnDdFRERERGRWTBctVK6dVcMV0RERERE5sFw1UrprnXFcEVEREREZB4MV62UbuTqWkYRysq1Fq6GiIiIiKj5Y7hqpfxdlXC2s0G5VkRCZpGlyyEiIiIiavYYrlopQRDY1IKIiIiIyIwYrlqxcK67IiIiIiIyG4arVqyjL691RURERERkLgxXrVhHtmMnIiIiIjIbhqtWTBeuErOLoVJrLFwNEREREVHzxnDVink52cLD0RaiCMSnF1q6HCIiIiKiZo3hqhUTBAEdKzoGct0VEREREdGdYbhq5bjuioiIiIjIPBiuWjmGKyIiIiIi82C4auUqr3XFNVdERERERHeC4aqV6+gjhavk3BIUqNQWroaIiIiIqPliuGrlXB0U8HWxA8DRKyIiIiKiO8FwRfp1V1e47oqIiIiIqMEYrgjhFeHqEsMVEREREVGDMVwROwYSEREREZkBwxWhY0XHwEupXHNFRERERNRQDFeEDj5OAIDMwlJkF5VZuBoiIiIiouaJ4YrgaGeDth72ADg1kIiIiIiooRiuCEDl9a4YroiIiIiIGobhigBUXXfFcEVERERE1BAMVwSgsh37FV5ImIiIiIioQRiuCEBlO/ZLaQUQRdHC1RARERERNT8MVwQACPV2hEwA8krUSC8otXQ5RERERETNDsMVAQCUCjmCvRwBcN0VEREREVFDMFyRnm7dFTsGEhERERHVH8MV6XVkuCIiIiIiajCGK9KrbGrBjoFERERERPXFcEV64X5OAIAraQXQatkxkIiIiIioPhiuSC/I0xG2chmKyzRIzi2xdDlERERERM0KwxXpKeQyhHpLHQO57oqIiIiIqH4YrshA1YsJExERERGR6RiuyEC4X0XHQF7rioiIiIioXiwerj766CMEBwdDqVQiKioKx44dq/FYtVqNZcuWISwsDEqlEj169MCePXvu6JxkqLIdOzsGEhERERHVh0XD1ZYtWzBv3jzExMTg1KlT6NGjB0aOHIn09HSjxy9cuBCffPIJPvzwQ8TFxeHpp5/G+PHjcfr06QafkwzpLiQcn1GIco3WwtUQERERETUfFg1Xq1atwuzZszFjxgxERERg7dq1cHBwwLp164wev2HDBrz66qsYPXo0QkNDMWfOHIwePRorV65s8DnJUBt3e9gr5Cgr1yIxu9jS5RARERERNRs2lnrisrIynDx5Eq+88op+n0wmw3333YcjR44YfUxpaSmUSqXBPnt7e/z5558NPqfuvKWlpfrb+fn5AKRpiGq1uv4vzox0z9+UdbT3ccTZ5HzEJeeinZudVdRUF9ZkOmusizWZhjWZhjWZhjWZhjWZxhprAqyzLtZkGmuqqT41CKIoWuRqsbdu3UJgYCAOHz6M/v376/e/9NJL+P3333H06NFqj5k8eTL+/vtvbN++HWFhYdi3bx8efPBBaDQalJaWNuicALBkyRIsXbq02v5NmzbBwcHBDK+2efkmXoZjGTKMaqNBdFteTJiIiIiIWq/i4mJMnjwZeXl5cHFxqfVYi41cNcT777+P2bNno1OnThAEAWFhYZgxY8YdT/l75ZVXMG/ePP3t/Px8tG3bFiNGjKjzC9jY1Go19u7di+HDh0OhUDTJc6Ycuo5jey4DrgEYPbqHVdRUF9ZkOmusizWZhjWZhjWZhjWZhjWZxhprAqyzLtZkGmuqSTerzRQWC1deXl6Qy+VIS0sz2J+WlgY/Pz+jj/H29sb27duhUqmQlZWFgIAALFiwAKGhoQ0+JwDY2dnBzq769DeFQmHxb6ZOU9bSyd8VAHAlo6jW57Smr48OazKdNdbFmkzDmkzDmkzDmkzDmkxjjTUB1lkXazKNNdRUn+e3WEMLW1tb9O7dG/v27dPv02q12Ldvn8GUPmOUSiUCAwNRXl6OH3/8EQ8++OAdn5Mq6a51lZBZhNJyjYWrISIiIiJqHiw6LXDevHmYNm0a+vTpg379+mH16tUoKirCjBkzAABTp05FYGAgli9fDgA4evQokpOTERkZieTkZCxZsgRarRYvvfSSyeekuvm5KOGstEGBqhwJmUXo5GfZqZFERERERM2BRcPVY489hoyMDCxevBipqamIjIzEnj174OvrCwBISkqCTFY5uKZSqbBw4UJcu3YNTk5OGD16NDZs2AA3NzeTz0l1EwQB4b7OOJGYg0upBQxXREREREQmsHhDi7lz52Lu3LlG7ztw4IDB7SFDhiAuLu6Ozkmm6VARri6nFVi6FCIiIiKiZsGiFxEm6xXu6wQAuJRaaOFKiIiIiIiaB4YrMqpjRVOLK+kcuSIiIiIiMgXDFRnV0VcKV0nZxSguK7dwNURERERE1o/hiozycrKDp6MtRBGIT+fUQCIiIiKiutQ7XAUHB2PZsmVISkpqjHrIiuhGry6lcmogEREREVFd6h2unn/+eWzduhWhoaEYPnw4Nm/ejNLS0saojSwsXL/uiiNXRERERER1aVC4io2NxbFjx9C5c2f83//9H/z9/TF37lycOnWqMWokC+mg7xjIkSsiIiIioro0eM1Vr1698MEHH+DWrVuIiYnB559/jr59+yIyMhLr1q2DKIrmrJMsILxiWiCvdUVEREREVLcGX0RYrVZj27ZtWL9+Pfbu3Yu77roLs2bNws2bN/Hqq6/i119/xaZNm8xZKzWxDhXhKiVPhbwSNVztFRauiIiIiIjIetU7XJ06dQrr16/Ht99+C5lMhqlTp+K9995Dp06d9MeMHz8effv2NWuh1PRc7RXwd1UiJU+F+PQC9A7ysHRJRERERERWq97hqm/fvhg+fDjWrFmDcePGQaGoPpoREhKCiRMnmqVAsqwOvs5IyVPhUmohwxURERERUS3qHa6uXbuGoKCgWo9xdHTE+vXrG1wUWY9wXyccvJzBdVdERERERHWod0OL9PR0HD16tNr+o0eP4sSJE2YpiqwHr3VFRERERGSaeoerf/7zn7hx40a1/cnJyfjnP/9plqLIelRe64rhioiIiIioNvUOV3FxcejVq1e1/T179kRcXJxZiiLr0d5HutZVZmEZMgt5sWgiIiIioprUO1zZ2dkhLS2t2v6UlBTY2DS4sztZKQdbG7TzcADA610REREREdWm3uFqxIgReOWVV5CXl6ffl5ubi1dffRXDhw83a3FkHXTrri5z3RURERERUY3qPdT07rvvYvDgwQgKCkLPnj0BALGxsfD19cWGDRvMXiBZXrifE369kIbL6YWWLoWIiIiIyGrVO1wFBgbizJkz+Oabb/D333/D3t4eM2bMwKRJk4xe84qaP45cERERERHVrUGLpBwdHfGPf/zD3LWQldK3Y08rgCiKFq6GiIiIiMg6NbgDRVxcHJKSklBWVmaw/4EHHrjjosi6hHo7Qi4TUKAqR2q+Cl4ObFxCRERERHS7er9LvnbtGsaPH4+zZ89CEAT9SIYgCAAAjUZj3grJ4uxs5AjxckR8eiEupxXCK8TN0iUREREREVmdencLfO655xASEoL09HQ4ODjg/PnzOHjwIPr06YMDBw40QolkDTr6Ste74rorIiIiIiLj6h2ujhw5gmXLlsHLywsymQwymQwDBw7E8uXL8eyzzzZGjWQFqq67IiIiIiKi6uodrjQaDZydpTfaXl5euHXrFgAgKCgIly5dMm91ZDXCK8LVFYYrIiIiIiKj6r3mqmvXrvj7778R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5d62rVu31nlCi0GDBsHe3h4hISE4efIk9u/fj88++wwAnvn7s3R0dPDhhx8iMzMTWVlZCA0NRa9evZSHGUZHR2PNmjWIj49Hfn4+Fi1ahC1btjx1LxQAzJw5E1u3bkVBQQFOnz6NHTt2KCdstfHz88Pp06fr3Hu1YMECBAcHY+DAgTh79qxyeUVFBbKysuDr6/tMz5uI6EXCyRUR0Utu9uzZNQ4v69SpE/79739j+fLlcHd3x+HDh+t9Ef4sYmNjERsbC3d3d2RkZGDbtm3KM9BV722qqqqCr68vXF1dERUVhZYtW6p8vksdEydOxOTJkzFlyhS4uroiOTkZ27Ztg6Oj43M/h9q2m5ubG9LT03Hu3Dn07dsXHh4emDlzJuRyea33oaWlhaSkJJSXl6NHjx54++23lWcLrOtzS3UxNDTE1KlT8cYbb8DLywvGxsbYtGmT8vqgoCAsXboUCxYsgIuLC7799lusXr0aAwYMeOr96urqYtq0aXBzc0O/fv2gpaWFjRs31rm+q6srunbtip9//rnOdRYvXoyRI0di4MCBOHfuHABg69atsLW1Rd++fZ/peRMRvUhk4smD7omIiKjR7N+/H3369EFBQcFzf05LKr/88guio6ORk5Oj9oS4V69emDhxIt54441GriMiko621AFEREQvs8TERBgbG8PR0REFBQWIjIyEl5fXCzuxAh6duCI/Px9XrlxB27Zt613/+vXrGD58OMaMGdMEdURE0uGeKyIioka0bt06fPHFF7h48SLMzMzg4+ODhQsXwtTUVOo0IiJqYJxcERERERERNQCe0IKIiIiIiKgBcHJFRERERETUADi5IiIiIiIiagCcXBERERERETUATq6IiIiIiIgaACdXREREREREDYCTKyIiIiIiogbAyRUREREREVED+D+qtJ+yTpRZ5gAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from sklearn.datasets import load_iris\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.neighbors import KNeighborsClassifier\n",
+ "\n",
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "k_values = range(1, 21)\n",
+ "\n",
+ "train_scores = []\n",
+ "test_scores = []\n",
+ "\n",
+ "# Iterate over each k value\n",
+ "for k in k_values:\n",
+ " # Train KNN classifier\n",
+ " knn = KNeighborsClassifier(n_neighbors=k)\n",
+ " knn.fit(X_train, y_train)\n",
+ "\n",
+ " # Calculate training and testing accuracy\n",
+ " train_score = knn.score(X_train, y_train)\n",
+ " test_score = knn.score(X_test, y_test)\n",
+ "\n",
+ " train_scores.append(train_score)\n",
+ " test_scores.append(test_score)\n",
+ "\n",
+ "# Plot the performance scores\n",
+ "plt.figure(figsize=(10, 6))\n",
+ "plt.plot(k_values, train_scores, label=\"Train Accuracy\", marker=\"o\")\n",
+ "plt.plot(k_values, test_scores, label=\"Test Accuracy\", marker=\"o\")\n",
+ "plt.xlabel(\"Number of Neighbors (k)\")\n",
+ "plt.ylabel(\"Accuracy\")\n",
+ "plt.title(\"KNN Classifier Performance\")\n",
+ "plt.xticks(np.arange(1, 21, step=1))\n",
+ "plt.legend()\n",
+ "plt.grid(True)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "38fbfc18-9f0f-405f-952e-74725d3fb6ed",
+ "metadata": {},
+ "source": [
+ "k=5 is an optimal value"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f2e34a7b-6c6b-4308-874e-f74899336c61",
+ "metadata": {},
+ "source": [
+ "Find other optimal hyperparameters by using grid search"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "id": "5725954c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py:982: UserWarning: Scoring failed. The score on this train-test partition for these parameters will be set to nan. Details: \n",
+ "Traceback (most recent call last):\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py\", line 971, in _score\n",
+ " scores = scorer(estimator, X_test, y_test, **score_params)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 279, in __call__\n",
+ " return self._score(partial(_cached_call, None), estimator, X, y_true, **_kwargs)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 371, in _score\n",
+ " y_pred = method_caller(\n",
+ " ^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 89, in _cached_call\n",
+ " result, _ = _get_response_values(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/utils/_response.py\", line 211, in _get_response_values\n",
+ " y_pred = prediction_method(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 259, in predict\n",
+ " probabilities = self.predict_proba(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 343, in predict_proba\n",
+ " probabilities = ArgKminClassMode.compute(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_pairwise_distances_reduction/_dispatcher.py\", line 590, in compute\n",
+ " unique_Y_labels=np.array(unique_Y_labels, dtype=np.intp),\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ "ValueError: invalid literal for int() with base 10: 'Accident'\n",
+ "\n",
+ " warnings.warn(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py:982: UserWarning: Scoring failed. The score on this train-test partition for these parameters will be set to nan. Details: \n",
+ "Traceback (most recent call last):\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py\", line 971, in _score\n",
+ " scores = scorer(estimator, X_test, y_test, **score_params)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 279, in __call__\n",
+ " return self._score(partial(_cached_call, None), estimator, X, y_true, **_kwargs)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 371, in _score\n",
+ " y_pred = method_caller(\n",
+ " ^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 89, in _cached_call\n",
+ " result, _ = _get_response_values(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/utils/_response.py\", line 211, in _get_response_values\n",
+ " y_pred = prediction_method(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 259, in predict\n",
+ " probabilities = self.predict_proba(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 343, in predict_proba\n",
+ " probabilities = ArgKminClassMode.compute(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_pairwise_distances_reduction/_dispatcher.py\", line 590, in compute\n",
+ " unique_Y_labels=np.array(unique_Y_labels, dtype=np.intp),\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ "ValueError: invalid literal for int() with base 10: 'Accident'\n",
+ "\n",
+ " warnings.warn(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py:982: UserWarning: Scoring failed. The score on this train-test partition for these parameters will be set to nan. Details: \n",
+ "Traceback (most recent call last):\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py\", line 971, in _score\n",
+ " scores = scorer(estimator, X_test, y_test, **score_params)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 279, in __call__\n",
+ " return self._score(partial(_cached_call, None), estimator, X, y_true, **_kwargs)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 371, in _score\n",
+ " y_pred = method_caller(\n",
+ " ^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 89, in _cached_call\n",
+ " result, _ = _get_response_values(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/utils/_response.py\", line 211, in _get_response_values\n",
+ " y_pred = prediction_method(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 259, in predict\n",
+ " probabilities = self.predict_proba(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 343, in predict_proba\n",
+ " probabilities = ArgKminClassMode.compute(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_pairwise_distances_reduction/_dispatcher.py\", line 590, in compute\n",
+ " unique_Y_labels=np.array(unique_Y_labels, dtype=np.intp),\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ "ValueError: invalid literal for int() with base 10: 'Accident'\n",
+ "\n",
+ " warnings.warn(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py:982: UserWarning: Scoring failed. The score on this train-test partition for these parameters will be set to nan. Details: \n",
+ "Traceback (most recent call last):\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py\", line 971, in _score\n",
+ " scores = scorer(estimator, X_test, y_test, **score_params)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 279, in __call__\n",
+ " return self._score(partial(_cached_call, None), estimator, X, y_true, **_kwargs)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 371, in _score\n",
+ " y_pred = method_caller(\n",
+ " ^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 89, in _cached_call\n",
+ " result, _ = _get_response_values(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/utils/_response.py\", line 211, in _get_response_values\n",
+ " y_pred = prediction_method(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 259, in predict\n",
+ " probabilities = self.predict_proba(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 343, in predict_proba\n",
+ " probabilities = ArgKminClassMode.compute(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_pairwise_distances_reduction/_dispatcher.py\", line 590, in compute\n",
+ " unique_Y_labels=np.array(unique_Y_labels, dtype=np.intp),\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ "ValueError: invalid literal for int() with base 10: 'Accident'\n",
+ "\n",
+ " warnings.warn(\n",
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py:982: UserWarning: Scoring failed. The score on this train-test partition for these parameters will be set to nan. Details: \n",
+ "Traceback (most recent call last):\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_validation.py\", line 971, in _score\n",
+ " scores = scorer(estimator, X_test, y_test, **score_params)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 279, in __call__\n",
+ " return self._score(partial(_cached_call, None), estimator, X, y_true, **_kwargs)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 371, in _score\n",
+ " y_pred = method_caller(\n",
+ " ^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_scorer.py\", line 89, in _cached_call\n",
+ " result, _ = _get_response_values(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/utils/_response.py\", line 211, in _get_response_values\n",
+ " y_pred = prediction_method(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 259, in predict\n",
+ " probabilities = self.predict_proba(X)\n",
+ " ^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/neighbors/_classification.py\", line 343, in predict_proba\n",
+ " probabilities = ArgKminClassMode.compute(\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ " File \"/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/metrics/_pairwise_distances_reduction/_dispatcher.py\", line 590, in compute\n",
+ " unique_Y_labels=np.array(unique_Y_labels, dtype=np.intp),\n",
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
+ "ValueError: invalid literal for int() with base 10: 'Accident'\n",
+ "\n",
+ " warnings.warn(\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best Parameters: {'p': 2, 'weights': 'distance'}\n",
+ "Test Accuracy: 0.7993079584775087\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/Users/inflaton/anaconda3/envs/maritime/lib/python3.12/site-packages/sklearn/model_selection/_search.py:1052: UserWarning: One or more of the test scores are non-finite: [ nan 0.58348075 0.77465707 0.78136118]\n",
+ " warnings.warn(\n"
+ ]
+ }
+ ],
+ "source": [
+ "knn = KNeighborsClassifier()\n",
+ "\n",
+ "param_grid = {\"weights\": [\"uniform\", \"distance\"], \"p\": [1, 2]}\n",
+ "\n",
+ "grid_search = GridSearchCV(\n",
+ " estimator=knn, param_grid=param_grid, cv=5, scoring=\"accuracy\"\n",
+ ")\n",
+ "\n",
+ "grid_search.fit(X_train, y_train)\n",
+ "\n",
+ "best_params = grid_search.best_params_\n",
+ "\n",
+ "best_model = grid_search.best_estimator_\n",
+ "\n",
+ "test_accuracy = best_model.score(X_test, y_test)\n",
+ "print(\"Best Parameters:\", best_params)\n",
+ "print(\"Test Accuracy:\", test_accuracy)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6b7449ea-16e7-4660-89c6-24fe635f2880",
+ "metadata": {},
+ "source": [
+ "Lastly, run the model with optimal hyperparameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "id": "50fb3195-fe1c-499a-9157-0be8dc7be3e1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import time"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "id": "dbd33ce9-ebc7-42d8-a190-013c1d889286",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Accuracy: 0.7993079584775087\n",
+ "Total Runtime: 0.09849786758422852\n"
+ ]
+ }
+ ],
+ "source": [
+ "X_train, X_test, y_train, y_test = train_test_split(\n",
+ " X, y, test_size=0.2, random_state=42\n",
+ ")\n",
+ "\n",
+ "start_time = time.time()\n",
+ "\n",
+ "k = 5\n",
+ "knn_model = KNeighborsClassifier(n_neighbors=k, weights=\"distance\")\n",
+ "knn_model.fit(X_train, y_train)\n",
+ "\n",
+ "y_pred = knn_model.predict(X_test)\n",
+ "\n",
+ "end_time = time.time()\n",
+ "total_runtime = end_time - start_time\n",
+ "\n",
+ "accuracy = accuracy_score(y_test, y_pred)\n",
+ "print(\"Accuracy:\", accuracy)\n",
+ "print(\"Total Runtime:\", total_runtime)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}