diff --git a/Analysis/Stinger_LSTM.ipynb b/Analysis/Stinger_LSTM.ipynb index ee01d9ec..fb6c0320 100644 --- a/Analysis/Stinger_LSTM.ipynb +++ b/Analysis/Stinger_LSTM.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 104, "id": "f0f09687eb0be6fa", "metadata": { "ExecuteTime": { @@ -24,7 +24,10 @@ "import tensorflow as tf\n", "import pandas as pd\n", "import numpy as np\n", - "from sklearn.preprocessing import MinMaxScaler" + "from sklearn.preprocessing import MinMaxScaler\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from sklearn.metrics import r2_score, mean_absolute_error" ] }, { @@ -41,14 +44,9 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "ac5ec41278b7be4e", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-01T22:58:20.940274Z", - "start_time": "2025-11-01T22:58:20.891444Z" - } - }, + "execution_count": 105, + "id": "2647c5e3", + "metadata": {}, "outputs": [ { "name": "stdout", @@ -79,7 +77,157 @@ " \n", " \n", " Distance Between Stations (km)\n", + " Weather Conditions\n", + " Day of the Week\n", + " Time of Day\n", + " Train Type\n", " Historical Delay (min)\n", + " Route Congestion\n", + " \n", + " \n", + " \n", + " \n", + " 0\n", + " 100\n", + " Clear\n", + " Monday\n", + " Morning\n", + " Express\n", + " 5\n", + " Low\n", + " \n", + " \n", + " 1\n", + " 150\n", + " Rainy\n", + " Tuesday\n", + " Afternoon\n", + " Superfast\n", + " 10\n", + " Medium\n", + " \n", + " \n", + " 2\n", + " 200\n", + " Foggy\n", + " Wednesday\n", + " Evening\n", + " Local\n", + " 15\n", + " High\n", + " \n", + " \n", + " 3\n", + " 50\n", + " Clear\n", + " Thursday\n", + " Night\n", + " Express\n", + " 2\n", + " Low\n", + " \n", + " \n", + " 4\n", + " 75\n", + " Rainy\n", + " Friday\n", + " Morning\n", + " Superfast\n", + " 8\n", + " Medium\n", + " \n", + " \n", + "\n", + "" + ], + "text/plain": [ + " Distance Between Stations (km) Weather Conditions Day of the Week \\\n", + "0 100 Clear Monday \n", + "1 150 Rainy Tuesday \n", + "2 200 Foggy Wednesday \n", + "3 50 Clear Thursday \n", + "4 75 Rainy Friday \n", + "\n", + " Time of Day Train Type Historical Delay (min) Route Congestion \n", + "0 Morning Express 5 Low \n", + "1 Afternoon Superfast 10 Medium \n", + "2 Evening Local 15 High \n", + "3 Night Express 2 Low \n", + "4 Morning Superfast 8 Medium " + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"train delay data.csv\")\n", + "print(df.shape)\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "id": "ac5ec41278b7be4e", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-01T22:58:20.940274Z", + "start_time": "2025-11-01T22:58:20.891444Z" + } + }, + "outputs": [], + "source": [ + "def preprocess_data(df, feature_cols: list, target_col: str, ordinal_vars= None): \n", + "\n", + " categorical_columns = df.select_dtypes(include=['object']).columns #gets columns that needs to be encoded\n", + "\n", + " if ordinal_vars is not None: #dict specifying order may not be inputted, especially if too many features \n", + " ordinal_vars = {key: value for key, value in ordinal_vars.items() if key in feature_cols} #filtering feature values from ordered dictionary \n", + "\n", + " for i in ordinal_vars.keys(): #specifically encodes for ordered categorical values \n", + " categorical_columns = categorical_columns.delete(categorical_columns.get_loc(i)) #preventing encoding twice\n", + " order = ordinal_vars[i] #getting the specififed order for encoding \n", + " df[f'{i}_Encoded'] = df[i].astype(pd.CategoricalDtype(categories = order, ordered = True)).cat.codes #establishes the order and encodes it \n", + " del df[i] \n", + "\n", + " df = pd.get_dummies(df, columns=categorical_columns) #encodes non-ordered categorical variables\n", + " scaler = MinMaxScaler()\n", + " df_scaled = scaler.fit_transform(df) #scales from range 0,1\n", + " df_scaled = pd.DataFrame(df_scaled, columns=df.columns) \n", + " df_scaled[target_col] = df_scaled.pop(target_col) #ensures that target col is in the last pos\n", + " return df_scaled\n" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "id": "d6fdf1db", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -98,13 +246,13 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -123,11 +271,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -146,11 +294,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -169,11 +317,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -192,11 +340,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -215,6 +363,7 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", @@ -242,7 +391,6 @@ " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -261,11 +409,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -284,11 +432,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -307,11 +455,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -330,11 +478,11 @@ " \n", " \n", " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", @@ -353,6 +501,7 @@ " \n", " \n", " \n", + " \n", " \n", " \n", "
Distance Between Stations (km)Route Congestion_EncodedWeather Conditions_ClearWeather Conditions_FoggyTrain Type_ExpressTrain Type_LocalTrain Type_SuperfastHistorical Delay (min)
00.1047120.0040650.01.00.01.00.00.00.004065
10.1570680.0081300.50.00.00.00.01.00.008130
20.2094240.0121951.00.01.00.01.00.00.012195
30.0523560.0016260.01.00.01.00.00.00.001626
40.0785340.0065040.50.00.00.00.01.00.006504
...
28730.9895290.9837400.51.00.00.01.00.00.983740
28740.9685860.9878051.00.00.01.00.00.00.987805
28750.9947640.9918700.00.01.00.00.01.00.991870
28760.9738220.9959350.51.00.00.01.00.00.995935
28771.0000001.0000001.00.00.01.00.00.01.000000
\n", @@ -360,161 +509,142 @@ "
" ], "text/plain": [ - " Distance Between Stations (km) Historical Delay (min) \\\n", - "0 0.104712 0.004065 \n", - "1 0.157068 0.008130 \n", - "2 0.209424 0.012195 \n", - "3 0.052356 0.001626 \n", - "4 0.078534 0.006504 \n", - "... ... ... \n", - "2873 0.989529 0.983740 \n", - "2874 0.968586 0.987805 \n", - "2875 0.994764 0.991870 \n", - "2876 0.973822 0.995935 \n", - "2877 1.000000 1.000000 \n", + " Distance Between Stations (km) Route Congestion_Encoded \\\n", + "0 0.104712 0.0 \n", + "1 0.157068 0.5 \n", + "2 0.209424 1.0 \n", + "3 0.052356 0.0 \n", + "4 0.078534 0.5 \n", + "... ... ... \n", + "2873 0.989529 0.5 \n", + "2874 0.968586 1.0 \n", + "2875 0.994764 0.0 \n", + "2876 0.973822 0.5 \n", + "2877 1.000000 1.0 \n", "\n", - " Route Congestion_Encoded Weather Conditions_Clear \\\n", - "0 0.0 1.0 \n", - "1 0.5 0.0 \n", - "2 1.0 0.0 \n", - "3 0.0 1.0 \n", - "4 0.5 0.0 \n", + " Weather Conditions_Clear Weather Conditions_Foggy \\\n", + "0 1.0 0.0 \n", + "1 0.0 0.0 \n", + "2 0.0 1.0 \n", + "3 1.0 0.0 \n", + "4 0.0 0.0 \n", "... ... ... \n", - "2873 0.5 1.0 \n", - "2874 1.0 0.0 \n", - "2875 0.0 0.0 \n", - "2876 0.5 1.0 \n", - "2877 1.0 0.0 \n", - "\n", - " Weather Conditions_Foggy Weather Conditions_Rainy \\\n", - "0 0.0 0.0 \n", - "1 0.0 1.0 \n", - "2 1.0 0.0 \n", - "3 0.0 0.0 \n", - "4 0.0 1.0 \n", - "... ... ... \n", - "2873 0.0 0.0 \n", - "2874 0.0 1.0 \n", - "2875 1.0 0.0 \n", - "2876 0.0 0.0 \n", - "2877 0.0 1.0 \n", - "\n", - " Day of the Week_Friday Day of the Week_Monday \\\n", - "0 0.0 1.0 \n", - "1 0.0 0.0 \n", - "2 0.0 0.0 \n", - "3 0.0 0.0 \n", - "4 1.0 0.0 \n", - "... ... ... \n", - "2873 0.0 0.0 \n", - "2874 0.0 0.0 \n", - "2875 0.0 0.0 \n", - "2876 1.0 0.0 \n", - "2877 0.0 0.0 \n", + "2873 1.0 0.0 \n", + "2874 0.0 0.0 \n", + "2875 0.0 1.0 \n", + "2876 1.0 0.0 \n", + "2877 0.0 0.0 \n", "\n", - " Day of the Week_Saturday Day of the Week_Sunday \\\n", + " Weather Conditions_Rainy Day of the Week_Friday \\\n", "0 0.0 0.0 \n", - "1 0.0 0.0 \n", + "1 1.0 0.0 \n", "2 0.0 0.0 \n", "3 0.0 0.0 \n", - "4 0.0 0.0 \n", + "4 1.0 1.0 \n", "... ... ... \n", "2873 0.0 0.0 \n", - "2874 0.0 0.0 \n", + "2874 1.0 0.0 \n", "2875 0.0 0.0 \n", - "2876 0.0 0.0 \n", + "2876 0.0 1.0 \n", "2877 1.0 0.0 \n", "\n", - " Day of the Week_Thursday Day of the Week_Tuesday \\\n", - "0 0.0 0.0 \n", - "1 0.0 1.0 \n", - "2 0.0 0.0 \n", - "3 1.0 0.0 \n", - "4 0.0 0.0 \n", - "... ... ... \n", - "2873 0.0 1.0 \n", - "2874 0.0 0.0 \n", - "2875 1.0 0.0 \n", - "2876 0.0 0.0 \n", - "2877 0.0 0.0 \n", + " Day of the Week_Monday Day of the Week_Saturday \\\n", + "0 1.0 0.0 \n", + "1 0.0 0.0 \n", + "2 0.0 0.0 \n", + "3 0.0 0.0 \n", + "4 0.0 0.0 \n", + "... ... ... \n", + "2873 0.0 0.0 \n", + "2874 0.0 0.0 \n", + "2875 0.0 0.0 \n", + "2876 0.0 0.0 \n", + "2877 0.0 1.0 \n", "\n", - " Day of the Week_Wednesday Time of Day_Afternoon Time of Day_Evening \\\n", - "0 0.0 0.0 0.0 \n", - "1 0.0 1.0 0.0 \n", - "2 1.0 0.0 1.0 \n", - "3 0.0 0.0 0.0 \n", - "4 0.0 0.0 0.0 \n", - "... ... ... ... \n", - "2873 0.0 0.0 0.0 \n", - "2874 1.0 0.0 0.0 \n", - "2875 0.0 1.0 0.0 \n", - "2876 0.0 0.0 1.0 \n", - "2877 0.0 0.0 0.0 \n", + " Day of the Week_Sunday Day of the Week_Thursday \\\n", + "0 0.0 0.0 \n", + "1 0.0 0.0 \n", + "2 0.0 0.0 \n", + "3 0.0 1.0 \n", + "4 0.0 0.0 \n", + "... ... ... \n", + "2873 0.0 0.0 \n", + "2874 0.0 0.0 \n", + "2875 0.0 1.0 \n", + "2876 0.0 0.0 \n", + "2877 0.0 0.0 \n", "\n", - " Time of Day_Morning Time of Day_Night Train Type_Express \\\n", - "0 1.0 0.0 1.0 \n", - "1 0.0 0.0 0.0 \n", - "2 0.0 0.0 0.0 \n", - "3 0.0 1.0 1.0 \n", - "4 1.0 0.0 0.0 \n", - "... ... ... ... \n", - "2873 0.0 1.0 0.0 \n", - "2874 1.0 0.0 1.0 \n", - "2875 0.0 0.0 0.0 \n", - "2876 0.0 0.0 0.0 \n", - "2877 0.0 1.0 1.0 \n", + " Day of the Week_Tuesday Day of the Week_Wednesday \\\n", + "0 0.0 0.0 \n", + "1 1.0 0.0 \n", + "2 0.0 1.0 \n", + "3 0.0 0.0 \n", + "4 0.0 0.0 \n", + "... ... ... \n", + "2873 1.0 0.0 \n", + "2874 0.0 1.0 \n", + "2875 0.0 0.0 \n", + "2876 0.0 0.0 \n", + "2877 0.0 0.0 \n", "\n", - " Train Type_Local Train Type_Superfast \n", - "0 0.0 0.0 \n", - "1 0.0 1.0 \n", - "2 1.0 0.0 \n", - "3 0.0 0.0 \n", - "4 0.0 1.0 \n", - "... ... ... \n", - "2873 1.0 0.0 \n", - "2874 0.0 0.0 \n", - "2875 0.0 1.0 \n", - "2876 1.0 0.0 \n", - "2877 0.0 0.0 \n", + " Time of Day_Afternoon Time of Day_Evening Time of Day_Morning \\\n", + "0 0.0 0.0 1.0 \n", + "1 1.0 0.0 0.0 \n", + "2 0.0 1.0 0.0 \n", + "3 0.0 0.0 0.0 \n", + "4 0.0 0.0 1.0 \n", + "... ... ... ... \n", + "2873 0.0 0.0 0.0 \n", + "2874 0.0 0.0 1.0 \n", + "2875 1.0 0.0 0.0 \n", + "2876 0.0 1.0 0.0 \n", + "2877 0.0 0.0 0.0 \n", + "\n", + " Time of Day_Night Train Type_Express Train Type_Local \\\n", + "0 0.0 1.0 0.0 \n", + "1 0.0 0.0 0.0 \n", + "2 0.0 0.0 1.0 \n", + "3 1.0 1.0 0.0 \n", + "4 0.0 0.0 0.0 \n", + "... ... ... ... \n", + "2873 1.0 0.0 1.0 \n", + "2874 0.0 1.0 0.0 \n", + "2875 0.0 0.0 0.0 \n", + "2876 0.0 0.0 1.0 \n", + "2877 1.0 1.0 0.0 \n", + "\n", + " Train Type_Superfast Historical Delay (min) \n", + "0 0.0 0.004065 \n", + "1 1.0 0.008130 \n", + "2 0.0 0.012195 \n", + "3 0.0 0.001626 \n", + "4 1.0 0.006504 \n", + "... ... ... \n", + "2873 0.0 0.983740 \n", + "2874 0.0 0.987805 \n", + "2875 1.0 0.991870 \n", + "2876 0.0 0.995935 \n", + "2877 0.0 1.000000 \n", "\n", "[2878 rows x 20 columns]" ] }, + "execution_count": 107, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" } ], "source": [ - "df = pd.read_csv(\"train delay data.csv\")\n", - "print(df.shape)\n", - "df.head()\n", - "\n", - "ordinal_vars_order = {'Route Congestion': ['Low', 'Medium', 'High']}\n", - "#ordinal columns dictionary\n", + "ordinal_vars = {'Route Congestion': ['Low', 'Medium', 'High']}\n", + " #ordinal columns dictionary\n", " #keys: column names\n", " #values: order of values from small to large\n", - " \n", - "def preprocess(df, ordinal_vars_order = None): \n", - " #categorical data \n", - " categorical_columns = df.select_dtypes(include=['object']).columns\n", - "\n", - " if ordinal_vars_order is not None: \n", - " for i in ordinal_vars_order.keys():\n", - " categorical_columns = categorical_columns.delete(categorical_columns.get_loc(i)) \n", - " order = ordinal_vars_order[i]\n", - " df[f'{i}_ordered'] = df[i].astype(pd.CategoricalDtype(categories = order, ordered = True))\n", - " df[f'{i}_Encoded'] = df[f'{i}_ordered'].cat.codes\n", - " del df[f'{i}_ordered']\n", - " del df[i]\n", "\n", - " df = pd.get_dummies(df, columns=categorical_columns)\n", - " scaler = MinMaxScaler()\n", - " df_scaled = scaler.fit_transform(df.drop(columns=[]))\n", - " df_scaled = pd.DataFrame(df_scaled, columns=df.columns)\n", - " return df_scaled\n", + "target_cols = 'Historical Delay (min)'\n", + "feature_cols = df.drop(columns = [target_cols], axis = 1).columns.tolist()\n", "\n", - "df_new = preprocess(df, ordinal_vars_order)\n", - "display(df_new)" + "df_scaled = preprocess_data(df, feature_cols, target_cols, ordinal_vars)\n", + "df_scaled" ] }, { @@ -527,14 +657,6 @@ " - Initialize model, optimizer, and loss function\n" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "c6e20ffcba1ebc7c", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "40be92eea5ae33e9", @@ -546,14 +668,6 @@ " - Save best model (optional)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "85429d2f7577e9b5", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "4f0e8f82bc3d5508", @@ -564,6 +678,56 @@ " - Plot training/validation loss curves\n", " - Visualize predicted vs actual delays\n" ] + }, + { + "cell_type": "code", + "execution_count": 110, + "id": "1fe66961", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'y_test' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[110]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# Convert test predictions back to original scale if normalized\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m y_test_actual = \u001b[43my_test\u001b[49m \n\u001b[32m 3\u001b[39m y_pred_actual = y_pred.squeeze() \n\u001b[32m 5\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mscores\u001b[39m(y_test_actual, y_pred_actual): \n", + "\u001b[31mNameError\u001b[39m: name 'y_test' is not defined" + ] + } + ], + "source": [ + "# Convert test predictions back to original scale if normalized\n", + "y_test_actual = y_test \n", + "y_pred_actual = y_pred.squeeze() \n", + "\n", + "def scores(y_test_actual, y_pred_actual): \n", + " mae = mean_absolute_error(y_test_actual, y_pred_actual)\n", + " r2 = r2_score(y_test_actual, y_pred_actual)\n", + " return f\"Test Mean Absolute Error: {mae}, Test R^2: {r2}\"\n", + "\n", + "def visualizing (y_test_actual, y_pred_actual):\n", + " plt.figure(figsize=(10, 6))\n", + " sns.scatterplot(x=y_test_actual, y=y_pred_actual, alpha=0.5)\n", + " plt.plot([min(y_test_actual), max(y_test_actual)], [min(y_test_actual), max(y_test_actual)],\n", + " color='red', linestyle='--', label=\"Perfect Prediction\")\n", + "\n", + " # Labels and title\n", + " plt.xlabel(\"Actual Delay\")\n", + " plt.ylabel(\"Predicted Delay\")\n", + " plt.title(\"Actual vs. Predicted Train Delays\")\n", + " plt.legend()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e329fa3", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": {