907 lines
33 KiB
Plaintext
907 lines
33 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "21ce2b41",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"from sklearn.model_selection import train_test_split\n",
|
|
"from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\n",
|
|
"\n",
|
|
"import tensorflow as tf\n",
|
|
"from tensorflow.keras.models import Sequential\n",
|
|
"from tensorflow.keras.layers import (\n",
|
|
" LSTM,\n",
|
|
" Bidirectional,\n",
|
|
" Dense,\n",
|
|
" Dropout,\n",
|
|
" Masking\n",
|
|
")\n",
|
|
"\n",
|
|
"from tensorflow.keras.callbacks import (\n",
|
|
" EarlyStopping,\n",
|
|
" ReduceLROnPlateau\n",
|
|
")\n",
|
|
"\n",
|
|
"import matplotlib.pyplot as plt"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "7b5e2a73",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>match_id</th>\n",
|
|
" <th>delivery_number</th>\n",
|
|
" <th>legal_ball</th>\n",
|
|
" <th>over_ball</th>\n",
|
|
" <th>score</th>\n",
|
|
" <th>wickets</th>\n",
|
|
" <th>target_score</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>1001349</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>168</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>1001349</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>168</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>1001349</td>\n",
|
|
" <td>3</td>\n",
|
|
" <td>3</td>\n",
|
|
" <td>0.3</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>168</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>1001349</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>0.4</td>\n",
|
|
" <td>3</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>168</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>1001349</td>\n",
|
|
" <td>5</td>\n",
|
|
" <td>5</td>\n",
|
|
" <td>0.5</td>\n",
|
|
" <td>3</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>168</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"text/plain": [
|
|
" match_id delivery_number legal_ball over_ball score wickets \\\n",
|
|
"0 1001349 1 1 0.1 0 0 \n",
|
|
"1 1001349 2 2 0.2 0 0 \n",
|
|
"2 1001349 3 3 0.3 1 0 \n",
|
|
"3 1001349 4 4 0.4 3 0 \n",
|
|
"4 1001349 5 5 0.5 3 0 \n",
|
|
"\n",
|
|
" target_score \n",
|
|
"0 168 \n",
|
|
"1 168 \n",
|
|
"2 168 \n",
|
|
"3 168 \n",
|
|
"4 168 "
|
|
]
|
|
},
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"df = pd.read_csv(\n",
|
|
" \"data/run_prediction_dataset_raw.csv\"\n",
|
|
")\n",
|
|
"\n",
|
|
"df.head()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "4b258bec",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>match_id</th>\n",
|
|
" <th>delivery_number</th>\n",
|
|
" <th>legal_ball</th>\n",
|
|
" <th>over_ball</th>\n",
|
|
" <th>score</th>\n",
|
|
" <th>wickets</th>\n",
|
|
" <th>target_score</th>\n",
|
|
" <th>runs_this_ball</th>\n",
|
|
" <th>previous_score</th>\n",
|
|
" <th>last_6_runs</th>\n",
|
|
" <th>last_12_runs</th>\n",
|
|
" <th>boundaries</th>\n",
|
|
" <th>last_12_boundaries</th>\n",
|
|
" <th>dots</th>\n",
|
|
" <th>last_12_dots</th>\n",
|
|
" <th>balls_remaining</th>\n",
|
|
" <th>run_rate</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>514915</th>\n",
|
|
" <td>211028</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>179</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>119</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>514916</th>\n",
|
|
" <td>211028</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>2</td>\n",
|
|
" <td>0.2</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>179</td>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>118</td>\n",
|
|
" <td>3.0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>514917</th>\n",
|
|
" <td>211028</td>\n",
|
|
" <td>3</td>\n",
|
|
" <td>3</td>\n",
|
|
" <td>0.3</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>179</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>117</td>\n",
|
|
" <td>2.0</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>514918</th>\n",
|
|
" <td>211028</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>4</td>\n",
|
|
" <td>0.4</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>179</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>116</td>\n",
|
|
" <td>1.5</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>514919</th>\n",
|
|
" <td>211028</td>\n",
|
|
" <td>5</td>\n",
|
|
" <td>5</td>\n",
|
|
" <td>0.5</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>179</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>0</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.0</td>\n",
|
|
" <td>115</td>\n",
|
|
" <td>1.2</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"text/plain": [
|
|
" match_id delivery_number legal_ball over_ball score wickets \\\n",
|
|
"514915 211028 1 1 0.1 0 0 \n",
|
|
"514916 211028 2 2 0.2 1 0 \n",
|
|
"514917 211028 3 3 0.3 1 0 \n",
|
|
"514918 211028 4 4 0.4 1 0 \n",
|
|
"514919 211028 5 5 0.5 1 0 \n",
|
|
"\n",
|
|
" target_score runs_this_ball previous_score last_6_runs \\\n",
|
|
"514915 179 0.0 0.0 0.0 \n",
|
|
"514916 179 1.0 0.0 0.0 \n",
|
|
"514917 179 0.0 1.0 0.0 \n",
|
|
"514918 179 0.0 1.0 0.0 \n",
|
|
"514919 179 0.0 1.0 0.0 \n",
|
|
"\n",
|
|
" last_12_runs boundaries last_12_boundaries dots last_12_dots \\\n",
|
|
"514915 0.0 0 0.0 1 0.0 \n",
|
|
"514916 0.0 0 0.0 0 0.0 \n",
|
|
"514917 0.0 0 0.0 1 0.0 \n",
|
|
"514918 0.0 0 0.0 1 0.0 \n",
|
|
"514919 0.0 0 0.0 1 0.0 \n",
|
|
"\n",
|
|
" balls_remaining run_rate \n",
|
|
"514915 119 0.0 \n",
|
|
"514916 118 3.0 \n",
|
|
"514917 117 2.0 \n",
|
|
"514918 116 1.5 \n",
|
|
"514919 115 1.2 "
|
|
]
|
|
},
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"df = df.sort_values(\n",
|
|
" [\n",
|
|
" \"match_id\",\n",
|
|
" \"delivery_number\"\n",
|
|
" ]\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"# runs scored this ball\n",
|
|
"df[\"runs_this_ball\"] = (\n",
|
|
" df.groupby(\"match_id\")[\"score\"]\n",
|
|
" .diff()\n",
|
|
" .fillna(\n",
|
|
" df[\"score\"]\n",
|
|
" )\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"# previous score\n",
|
|
"df[\"previous_score\"] = (\n",
|
|
" df[\"score\"]\n",
|
|
" -\n",
|
|
" df[\"runs_this_ball\"]\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"# rolling scoring form\n",
|
|
"\n",
|
|
"df[\"last_6_runs\"] = (\n",
|
|
" df.groupby(\"match_id\")\n",
|
|
" [\"runs_this_ball\"]\n",
|
|
" .rolling(6)\n",
|
|
" .sum()\n",
|
|
" .reset_index(level=0,drop=True)\n",
|
|
" .fillna(0)\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"df[\"last_12_runs\"] = (\n",
|
|
" df.groupby(\"match_id\")\n",
|
|
" [\"runs_this_ball\"]\n",
|
|
" .rolling(12)\n",
|
|
" .sum()\n",
|
|
" .reset_index(level=0,drop=True)\n",
|
|
" .fillna(0)\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"df[\"boundaries\"] = (\n",
|
|
" df[\"runs_this_ball\"] >= 4\n",
|
|
").astype(int)\n",
|
|
"\n",
|
|
"\n",
|
|
"df[\"last_12_boundaries\"] = (\n",
|
|
" df.groupby(\"match_id\")\n",
|
|
" [\"boundaries\"]\n",
|
|
" .rolling(12)\n",
|
|
" .sum()\n",
|
|
" .reset_index(level=0,drop=True)\n",
|
|
" .fillna(0)\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"df[\"dots\"] = (\n",
|
|
" df[\"runs_this_ball\"] == 0\n",
|
|
").astype(int)\n",
|
|
"\n",
|
|
"\n",
|
|
"df[\"last_12_dots\"] = (\n",
|
|
" df.groupby(\"match_id\")\n",
|
|
" [\"dots\"]\n",
|
|
" .rolling(12)\n",
|
|
" .sum()\n",
|
|
" .reset_index(level=0,drop=True)\n",
|
|
" .fillna(0)\n",
|
|
")\n",
|
|
"\n",
|
|
"# Existing features above...\n",
|
|
"\n",
|
|
"\n",
|
|
"# New features\n",
|
|
"df[\"balls_remaining\"] = 120 - df[\"legal_ball\"]\n",
|
|
"\n",
|
|
"df[\"run_rate\"] = (\n",
|
|
" df[\"score\"] / (df[\"legal_ball\"] / 6)\n",
|
|
").replace(\n",
|
|
" [float(\"inf\"), -float(\"inf\")],\n",
|
|
" 0\n",
|
|
").fillna(0)\n",
|
|
"\n",
|
|
"df.head()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "1fc0e0b9",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"(440081, 17)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"df = df[\n",
|
|
" df[\"legal_ball\"] >= 30\n",
|
|
"]\n",
|
|
"\n",
|
|
"\n",
|
|
"print(\n",
|
|
" df.shape\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "370d0cfb",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"FEATURES = [\n",
|
|
" \"score\",\n",
|
|
" \"wickets\",\n",
|
|
" \"legal_ball\",\n",
|
|
" \"runs_this_ball\",\n",
|
|
" \"last_6_runs\",\n",
|
|
" \"last_12_runs\",\n",
|
|
" \"last_12_boundaries\",\n",
|
|
" \"last_12_dots\",\n",
|
|
" \"run_rate\",\n",
|
|
" \"balls_remaining\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "d43f7fc0",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Training matches: 3686\n",
|
|
"Testing matches : 922\n",
|
|
"Training rows: 352215\n",
|
|
"Testing rows : 87866\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from sklearn.model_selection import train_test_split\n",
|
|
"\n",
|
|
"\n",
|
|
"# ==========================================\n",
|
|
"# Split by MATCH, not by sequence\n",
|
|
"# ==========================================\n",
|
|
"\n",
|
|
"all_matches = df[\"match_id\"].unique()\n",
|
|
"\n",
|
|
"\n",
|
|
"train_matches, test_matches = train_test_split(\n",
|
|
" all_matches,\n",
|
|
" test_size=0.2,\n",
|
|
" random_state=42\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"train_df = df[\n",
|
|
" df[\"match_id\"].isin(train_matches)\n",
|
|
"].copy()\n",
|
|
"\n",
|
|
"\n",
|
|
"test_df = df[\n",
|
|
" df[\"match_id\"].isin(test_matches)\n",
|
|
"].copy()\n",
|
|
"\n",
|
|
"\n",
|
|
"print(\"Training matches:\", len(train_matches))\n",
|
|
"print(\"Testing matches :\", len(test_matches))\n",
|
|
"\n",
|
|
"print(\"Training rows:\", len(train_df))\n",
|
|
"print(\"Testing rows :\", len(test_df))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "55e46374",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(\n",
|
|
" len(\n",
|
|
" set(train_matches)\n",
|
|
" &\n",
|
|
" set(test_matches)\n",
|
|
" )\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "66f4ae4e",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Train sequences: 241635\n",
|
|
"Test sequences: 60206\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"def create_sequences(data):\n",
|
|
"\n",
|
|
" X = []\n",
|
|
" y = []\n",
|
|
"\n",
|
|
" for match_id, innings in data.groupby(\"match_id\"):\n",
|
|
"\n",
|
|
" innings = innings.sort_values(\n",
|
|
" \"legal_ball\"\n",
|
|
" )\n",
|
|
"\n",
|
|
" sequence = innings[FEATURES].values\n",
|
|
"\n",
|
|
" target = innings[\"target_score\"].iloc[0]\n",
|
|
"\n",
|
|
"\n",
|
|
" for i in range(30, len(sequence)):\n",
|
|
"\n",
|
|
" X.append(\n",
|
|
" sequence[:i+1]\n",
|
|
" )\n",
|
|
"\n",
|
|
" y.append(\n",
|
|
" target\n",
|
|
" )\n",
|
|
"\n",
|
|
" return X, y\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"X_train_sequences, y_train_targets = create_sequences(train_df)\n",
|
|
"\n",
|
|
"X_test_sequences, y_test_targets = create_sequences(test_df)\n",
|
|
"\n",
|
|
"\n",
|
|
"print(\n",
|
|
" \"Train sequences:\",\n",
|
|
" len(X_train_sequences)\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\n",
|
|
" \"Test sequences:\",\n",
|
|
" len(X_test_sequences)\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "1aa07812",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Train: (241635, 120, 10) (241635,)\n",
|
|
"Test : (60206, 120, 10) (60206,)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"\n",
|
|
"# X_train_sequences and X_test_sequences\n",
|
|
"# should already be created from separate match splits\n",
|
|
"\n",
|
|
"X_train = pad_sequences(\n",
|
|
" X_train_sequences,\n",
|
|
" maxlen=120,\n",
|
|
" dtype=\"float32\",\n",
|
|
" padding=\"pre\"\n",
|
|
")\n",
|
|
"\n",
|
|
"X_test = pad_sequences(\n",
|
|
" X_test_sequences,\n",
|
|
" maxlen=120,\n",
|
|
" dtype=\"float32\",\n",
|
|
" padding=\"pre\"\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"y_train = np.array(y_train_targets)\n",
|
|
"y_test = np.array(y_test_targets)\n",
|
|
"\n",
|
|
"\n",
|
|
"print(\"Train:\", X_train.shape, y_train.shape)\n",
|
|
"print(\"Test :\", X_test.shape, y_test.shape)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "e470e33f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"/Users/keshav/code/cricket-dls/.venv/lib/python3.12/site-packages/keras/src/layers/core/masking.py:48: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.\n",
|
|
" super().__init__(**kwargs)\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential\"</span>\n",
|
|
"</pre>\n"
|
|
],
|
|
"text/plain": [
|
|
"\u001b[1mModel: \"sequential\"\u001b[0m\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
|
|
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
|
|
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
|
|
"│ masking (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Masking</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">120</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ bidirectional (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Bidirectional</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">11,008</span> │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ dropout (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dropout</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ dense (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">2,080</span> │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ dense_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">1</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">33</span> │\n",
|
|
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
|
|
"</pre>\n"
|
|
],
|
|
"text/plain": [
|
|
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
|
|
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
|
|
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
|
|
"│ masking (\u001b[38;5;33mMasking\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m120\u001b[0m, \u001b[38;5;34m10\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ bidirectional (\u001b[38;5;33mBidirectional\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m11,008\u001b[0m │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ dropout (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m2,080\u001b[0m │\n",
|
|
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
|
"│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1\u001b[0m) │ \u001b[38;5;34m33\u001b[0m │\n",
|
|
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">13,121</span> (51.25 KB)\n",
|
|
"</pre>\n"
|
|
],
|
|
"text/plain": [
|
|
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m13,121\u001b[0m (51.25 KB)\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">13,121</span> (51.25 KB)\n",
|
|
"</pre>\n"
|
|
],
|
|
"text/plain": [
|
|
"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m13,121\u001b[0m (51.25 KB)\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
|
|
"</pre>\n"
|
|
],
|
|
"text/plain": [
|
|
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"model = Sequential([\n",
|
|
"\n",
|
|
" Masking(\n",
|
|
" mask_value=0.,\n",
|
|
" input_shape=(120,len(FEATURES))\n",
|
|
" ),\n",
|
|
"\n",
|
|
" Bidirectional(\n",
|
|
" LSTM(32)\n",
|
|
" ),\n",
|
|
"\n",
|
|
" Dropout(0.25),\n",
|
|
"\n",
|
|
" Dense(\n",
|
|
" 32,\n",
|
|
" activation=\"relu\"\n",
|
|
" ),\n",
|
|
"\n",
|
|
" Dense(1)\n",
|
|
"\n",
|
|
"])\n",
|
|
"\n",
|
|
"model.compile(\n",
|
|
" optimizer=tf.keras.optimizers.Adam(\n",
|
|
" learning_rate=0.001\n",
|
|
" ),\n",
|
|
"\n",
|
|
" loss=\"mse\",\n",
|
|
"\n",
|
|
" metrics=[\n",
|
|
" \"mae\"\n",
|
|
" ]\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"model.summary()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "495daca8",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch 1/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m32s\u001b[0m 254ms/step - loss: 19128.5391 - mae: 131.3299 - val_loss: 12421.8320 - val_mae: 103.6737 - learning_rate: 0.0010\n",
|
|
"Epoch 2/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 321ms/step - loss: 6210.3130 - mae: 65.5333 - val_loss: 1969.1512 - val_mae: 33.6969 - learning_rate: 0.0010\n",
|
|
"Epoch 3/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 321ms/step - loss: 1224.2498 - mae: 24.7959 - val_loss: 525.3225 - val_mae: 15.5029 - learning_rate: 0.0010\n",
|
|
"Epoch 4/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 322ms/step - loss: 610.5830 - mae: 17.7209 - val_loss: 320.0849 - val_mae: 12.2769 - learning_rate: 0.0010\n",
|
|
"Epoch 5/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 322ms/step - loss: 483.1981 - mae: 16.2305 - val_loss: 249.6277 - val_mae: 11.1048 - learning_rate: 0.0010\n",
|
|
"Epoch 6/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 345ms/step - loss: 434.6412 - mae: 15.6104 - val_loss: 226.9275 - val_mae: 10.6671 - learning_rate: 0.0010\n",
|
|
"Epoch 7/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m40s\u001b[0m 341ms/step - loss: 414.1877 - mae: 15.3427 - val_loss: 211.9790 - val_mae: 10.3182 - learning_rate: 0.0010\n",
|
|
"Epoch 8/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 331ms/step - loss: 395.6093 - mae: 15.0844 - val_loss: 207.4465 - val_mae: 10.3751 - learning_rate: 0.0010\n",
|
|
"Epoch 9/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m44s\u001b[0m 376ms/step - loss: 385.9764 - mae: 14.9372 - val_loss: 198.0012 - val_mae: 10.2073 - learning_rate: 0.0010\n",
|
|
"Epoch 10/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m47s\u001b[0m 395ms/step - loss: 374.2676 - mae: 14.7318 - val_loss: 194.2088 - val_mae: 10.1279 - learning_rate: 0.0010\n",
|
|
"Epoch 11/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m46s\u001b[0m 392ms/step - loss: 367.1200 - mae: 14.5911 - val_loss: 188.0659 - val_mae: 9.9135 - learning_rate: 0.0010\n",
|
|
"Epoch 12/100\n",
|
|
"\u001b[1m118/118\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m49s\u001b[0m 412ms/step - loss: 362.3481 - mae: 14.5265 - val_loss: 188.1493 - val_mae: 9.9198 - learning_rate: 0.0010\n",
|
|
"Epoch 13/100\n",
|
|
"\u001b[1m 27/118\u001b[0m \u001b[32m━━━━\u001b[0m\u001b[37m━━━━━━━━━━━━━━━━\u001b[0m \u001b[1m41s\u001b[0m 451ms/step - loss: 357.6455 - mae: 14.4617"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"callbacks = [\n",
|
|
"\n",
|
|
" EarlyStopping(\n",
|
|
" patience=10,\n",
|
|
" restore_best_weights=True\n",
|
|
" ),\n",
|
|
"\n",
|
|
" ReduceLROnPlateau(\n",
|
|
" patience=5,\n",
|
|
" factor=0.5\n",
|
|
" )\n",
|
|
"\n",
|
|
"]\n",
|
|
"\n",
|
|
"\n",
|
|
"history = model.fit(\n",
|
|
"\n",
|
|
" X_train,\n",
|
|
" y_train,\n",
|
|
"\n",
|
|
" validation_data=(\n",
|
|
" X_test,\n",
|
|
" y_test\n",
|
|
" ),\n",
|
|
"\n",
|
|
" epochs=100,\n",
|
|
"\n",
|
|
" batch_size=2048,\n",
|
|
"\n",
|
|
" callbacks=callbacks,\n",
|
|
"\n",
|
|
" verbose=1\n",
|
|
")"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".venv (3.14.6)",
|
|
"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.13"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|