Spaces:
Running
Running
Amol Kaushik commited on
Commit ·
cb9b728
1
Parent(s): 5122512
report
Browse files- .github/copilot-ignore +13 -0
- A9/A9.ipynb +2 -2
- A9/A9_Report.ipynb +649 -0
- A9/aggregate_results.py +271 -0
- A9/results_summary.csv +15 -0
- A9/results_summary.json +198 -0
.github/copilot-ignore
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ignore everything
|
| 2 |
+
*
|
| 3 |
+
|
| 4 |
+
# But not directories (so we can traverse into them)
|
| 5 |
+
!*/
|
| 6 |
+
|
| 7 |
+
# Allow Python files
|
| 8 |
+
!*.py
|
| 9 |
+
!**/*.py
|
| 10 |
+
|
| 11 |
+
# Allow Jupyter notebooks
|
| 12 |
+
!*.ipynb
|
| 13 |
+
!**/*.ipynb
|
A9/A9.ipynb
CHANGED
|
@@ -315,7 +315,7 @@
|
|
| 315 |
],
|
| 316 |
"metadata": {
|
| 317 |
"kernelspec": {
|
| 318 |
-
"display_name": "Python 3
|
| 319 |
"language": "python",
|
| 320 |
"name": "python3"
|
| 321 |
},
|
|
@@ -329,7 +329,7 @@
|
|
| 329 |
"name": "python",
|
| 330 |
"nbconvert_exporter": "python",
|
| 331 |
"pygments_lexer": "ipython3",
|
| 332 |
-
"version": "3.
|
| 333 |
}
|
| 334 |
},
|
| 335 |
"nbformat": 4,
|
|
|
|
| 315 |
],
|
| 316 |
"metadata": {
|
| 317 |
"kernelspec": {
|
| 318 |
+
"display_name": "Python 3",
|
| 319 |
"language": "python",
|
| 320 |
"name": "python3"
|
| 321 |
},
|
|
|
|
| 329 |
"name": "python",
|
| 330 |
"nbconvert_exporter": "python",
|
| 331 |
"pygments_lexer": "ipython3",
|
| 332 |
+
"version": "3.14.0"
|
| 333 |
}
|
| 334 |
},
|
| 335 |
"nbformat": 4,
|
A9/A9_Report.ipynb
ADDED
|
@@ -0,0 +1,649 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"id": "32dc1769",
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"source": [
|
| 8 |
+
"# A9 Report\n",
|
| 9 |
+
"\n",
|
| 10 |
+
"Predict 13 Z-coordinates from 26 input features (X, Y for each joint)"
|
| 11 |
+
]
|
| 12 |
+
},
|
| 13 |
+
{
|
| 14 |
+
"cell_type": "markdown",
|
| 15 |
+
"id": "fecdba5a",
|
| 16 |
+
"metadata": {},
|
| 17 |
+
"source": [
|
| 18 |
+
"## 1. Data\n",
|
| 19 |
+
"\n",
|
| 20 |
+
"| Column Range | Data |\n",
|
| 21 |
+
"|--------------|------|\n",
|
| 22 |
+
"| 0 | FrameNo |\n",
|
| 23 |
+
"| 1-3 | head_x, head_y, head_z |\n",
|
| 24 |
+
"| 4-6 | left_shoulder_x/y/z |\n",
|
| 25 |
+
"| 7-9 | left_elbow_x/y/z |\n",
|
| 26 |
+
"| 10-12 | right_shoulder_x/y/z |\n",
|
| 27 |
+
"| 13-15 | right_elbow_x/y/z |\n",
|
| 28 |
+
"| 16-18 | left_hand_x/y/z |\n",
|
| 29 |
+
"| 19-21 | right_hand_x/y/z |\n",
|
| 30 |
+
"| 22-24 | left_hip_x/y/z |\n",
|
| 31 |
+
"| 25-27 | right_hip_x/y/z |\n",
|
| 32 |
+
"| 28-30 | left_knee_x/y/z |\n",
|
| 33 |
+
"| 31-33 | right_knee_x/y/z |\n",
|
| 34 |
+
"| 34-36 | left_foot_x/y/z |\n",
|
| 35 |
+
"| 37-39 | right_foot_x/y/z |\n",
|
| 36 |
+
"\n",
|
| 37 |
+
"**Input**: 13 joints × 2 dimensions (x, y) = **26 features**\n",
|
| 38 |
+
"\n",
|
| 39 |
+
"**Output**: 13 joints × 1 dimension (z) = **13 targets**"
|
| 40 |
+
]
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"cell_type": "code",
|
| 44 |
+
"execution_count": 43,
|
| 45 |
+
"id": "e1ad3f43",
|
| 46 |
+
"metadata": {},
|
| 47 |
+
"outputs": [
|
| 48 |
+
{
|
| 49 |
+
"name": "stdout",
|
| 50 |
+
"output_type": "stream",
|
| 51 |
+
"text": [
|
| 52 |
+
"Loaded 14 experiment results\n"
|
| 53 |
+
]
|
| 54 |
+
}
|
| 55 |
+
],
|
| 56 |
+
"source": [
|
| 57 |
+
"import os\n",
|
| 58 |
+
"import json\n",
|
| 59 |
+
"import pandas as pd\n",
|
| 60 |
+
"import numpy as np\n",
|
| 61 |
+
"import matplotlib.pyplot as plt\n",
|
| 62 |
+
"from pathlib import Path\n",
|
| 63 |
+
"\n",
|
| 64 |
+
"# Load aggregated results\n",
|
| 65 |
+
"RESULTS_CSV = Path('results_summary.csv')\n",
|
| 66 |
+
"if RESULTS_CSV.exists():\n",
|
| 67 |
+
" df = pd.read_csv(RESULTS_CSV)\n",
|
| 68 |
+
" print(f\"Loaded {len(df)} experiment results\")\n",
|
| 69 |
+
"else:\n",
|
| 70 |
+
" print(\"Run aggregate_results.py first to generate results_summary.csv\")"
|
| 71 |
+
]
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"cell_type": "markdown",
|
| 75 |
+
"id": "8da8874c",
|
| 76 |
+
"metadata": {},
|
| 77 |
+
"source": [
|
| 78 |
+
"## 2. Deep Learning Steps Overview\n",
|
| 79 |
+
"\n",
|
| 80 |
+
"The 7-step Deep Learning workflow:\n",
|
| 81 |
+
"\n",
|
| 82 |
+
"| Step | Description | Implementation |\n",
|
| 83 |
+
"|------|-------------|----------------|\n",
|
| 84 |
+
"| 1 | Load Data | `load_all_sequences()` in models.py |\n",
|
| 85 |
+
"| 2 | Define Network | Dense, Conv1D, LSTM, GRU architectures |\n",
|
| 86 |
+
"| 3 | Compile Model | Optimizer (SGD/Adam/RMSprop), Loss (MSE/MAE) |\n",
|
| 87 |
+
"| 4 | Split Data | 5-fold cross-validation, 90/10 train/test |\n",
|
| 88 |
+
"| 5 | Train Model | Early stopping, 100 epochs max |\n",
|
| 89 |
+
"| 6 | Evaluate | MSE, MAE, R² on test set |\n",
|
| 90 |
+
"| 7 | Use Model | Load saved .h5 weights for inference |"
|
| 91 |
+
]
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"cell_type": "markdown",
|
| 95 |
+
"id": "d9f90334",
|
| 96 |
+
"metadata": {},
|
| 97 |
+
"source": [
|
| 98 |
+
"## 3. Model Architectures\n",
|
| 99 |
+
"\n",
|
| 100 |
+
"### Dense (MLP)\n",
|
| 101 |
+
"- Fully-connected layers\n",
|
| 102 |
+
"- Treats each frame independently\n",
|
| 103 |
+
"- Configuration: (256, 128, 64) hidden units, ReLU, dropout 0.3\n",
|
| 104 |
+
"\n",
|
| 105 |
+
"### Conv1D (CNN)\n",
|
| 106 |
+
"- 1D convolutional layers for temporal patterns\n",
|
| 107 |
+
"- Window size: 30 frames\n",
|
| 108 |
+
"- Best variant (v3): filters=(128, 256), kernel=3, pool=3, dense=(256, 128, 64)\n",
|
| 109 |
+
"\n",
|
| 110 |
+
"### LSTM\n",
|
| 111 |
+
"- Recurrent network for sequences\n",
|
| 112 |
+
"- Units: (64, 32), tanh activation\n",
|
| 113 |
+
"\n",
|
| 114 |
+
"### GRU\n",
|
| 115 |
+
"- Gated Recurrent Unit variant\n",
|
| 116 |
+
"- Units: (64, 32)"
|
| 117 |
+
]
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"cell_type": "markdown",
|
| 121 |
+
"id": "f04dfdfd",
|
| 122 |
+
"metadata": {},
|
| 123 |
+
"source": [
|
| 124 |
+
"## 4. Training & Hyperparameter Results"
|
| 125 |
+
]
|
| 126 |
+
},
|
| 127 |
+
{
|
| 128 |
+
"cell_type": "code",
|
| 129 |
+
"execution_count": 44,
|
| 130 |
+
"id": "1a49b682",
|
| 131 |
+
"metadata": {},
|
| 132 |
+
"outputs": [
|
| 133 |
+
{
|
| 134 |
+
"name": "stdout",
|
| 135 |
+
"output_type": "stream",
|
| 136 |
+
"text": [
|
| 137 |
+
"ARCHITECTURE COMPARISON\n",
|
| 138 |
+
"==================================================\n",
|
| 139 |
+
" model val_r2_mean val_rmse_mean val_mae_mean\n",
|
| 140 |
+
"conv1d 0.932681 0.037704 0.027598\n",
|
| 141 |
+
" dense 0.820046 0.058055 0.042731\n",
|
| 142 |
+
" lstm 0.768530 0.069834 0.052217\n"
|
| 143 |
+
]
|
| 144 |
+
}
|
| 145 |
+
],
|
| 146 |
+
"source": [
|
| 147 |
+
"# Architecture comparison\n",
|
| 148 |
+
"if 'df' in dir() and len(df) > 0:\n",
|
| 149 |
+
" arch_df = df[df['experiment'] == 'different_models'][['model', 'val_r2_mean', 'val_rmse_mean', 'val_mae_mean']]\n",
|
| 150 |
+
" arch_df = arch_df.sort_values('val_r2_mean', ascending=False)\n",
|
| 151 |
+
" print(\"ARCHITECTURE COMPARISON\")\n",
|
| 152 |
+
" print(\"=\"*50)\n",
|
| 153 |
+
" print(arch_df.to_string(index=False))"
|
| 154 |
+
]
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"cell_type": "code",
|
| 158 |
+
"execution_count": 45,
|
| 159 |
+
"id": "b5578e0e",
|
| 160 |
+
"metadata": {},
|
| 161 |
+
"outputs": [
|
| 162 |
+
{
|
| 163 |
+
"name": "stdout",
|
| 164 |
+
"output_type": "stream",
|
| 165 |
+
"text": [
|
| 166 |
+
"CONV1D VARIANTS\n",
|
| 167 |
+
"==================================================\n",
|
| 168 |
+
" model val_r2_mean val_rmse_mean test_r2 test_rmse\n",
|
| 169 |
+
" conv1d 0.922923 0.040316 0.928322 0.039097\n",
|
| 170 |
+
"conv1d_v2 0.799991 0.064831 0.826827 0.060770\n"
|
| 171 |
+
]
|
| 172 |
+
}
|
| 173 |
+
],
|
| 174 |
+
"source": [
|
| 175 |
+
"# Conv1D variants comparison\n",
|
| 176 |
+
"if 'df' in dir() and len(df) > 0:\n",
|
| 177 |
+
" conv_df = df[df['experiment'] == 'conv1d_variants'][['model', 'val_r2_mean', 'val_rmse_mean', 'test_r2', 'test_rmse']]\n",
|
| 178 |
+
" conv_df = conv_df.sort_values('test_r2', ascending=False)\n",
|
| 179 |
+
" print(\"CONV1D VARIANTS\")\n",
|
| 180 |
+
" print(\"=\"*50)\n",
|
| 181 |
+
" print(conv_df.to_string(index=False))"
|
| 182 |
+
]
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"cell_type": "code",
|
| 186 |
+
"execution_count": 46,
|
| 187 |
+
"id": "7b21485a",
|
| 188 |
+
"metadata": {},
|
| 189 |
+
"outputs": [
|
| 190 |
+
{
|
| 191 |
+
"name": "stdout",
|
| 192 |
+
"output_type": "stream",
|
| 193 |
+
"text": [
|
| 194 |
+
"OPTIMIZER COMPARISON\n",
|
| 195 |
+
"==================================================\n",
|
| 196 |
+
" model val_r2_mean val_rmse_mean test_r2 test_rmse\n",
|
| 197 |
+
"conv1d_v3_rmsprop_mse 0.946803 0.033498 0.954934 0.031001\n",
|
| 198 |
+
" conv1d_v3_adam_mse 0.949678 0.032558 0.953484 0.031496\n",
|
| 199 |
+
" conv1d_v3_sgd_mse 0.950863 0.032199 0.952354 0.031876\n"
|
| 200 |
+
]
|
| 201 |
+
}
|
| 202 |
+
],
|
| 203 |
+
"source": [
|
| 204 |
+
"# Optimizer comparison\n",
|
| 205 |
+
"if 'df' in dir() and len(df) > 0:\n",
|
| 206 |
+
" opt_df = df[df['experiment'] == 'optimizer'][['model', 'val_r2_mean', 'val_rmse_mean', 'test_r2', 'test_rmse']]\n",
|
| 207 |
+
" opt_df = opt_df.sort_values('test_r2', ascending=False)\n",
|
| 208 |
+
" print(\"OPTIMIZER COMPARISON\")\n",
|
| 209 |
+
" print(\"=\"*50)\n",
|
| 210 |
+
" print(opt_df.to_string(index=False))"
|
| 211 |
+
]
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"cell_type": "code",
|
| 215 |
+
"execution_count": 47,
|
| 216 |
+
"id": "6b55c089",
|
| 217 |
+
"metadata": {},
|
| 218 |
+
"outputs": [
|
| 219 |
+
{
|
| 220 |
+
"name": "stdout",
|
| 221 |
+
"output_type": "stream",
|
| 222 |
+
"text": [
|
| 223 |
+
"LOSS FUNCTION COMPARISON\n",
|
| 224 |
+
"==================================================\n",
|
| 225 |
+
" model val_r2_mean val_rmse_mean test_r2 test_rmse\n",
|
| 226 |
+
"conv1d_v3_rmsprop_mse 0.950038 0.032467 0.954592 0.031119\n",
|
| 227 |
+
" conv1d_v3_adam_mse 0.948571 0.032956 0.952860 0.031707\n",
|
| 228 |
+
" conv1d_v3_sgd_mse 0.950748 0.032241 0.952171 0.031937\n",
|
| 229 |
+
"conv1d_v3_rmsprop_mae 0.943196 0.034623 0.944302 0.034465\n",
|
| 230 |
+
" conv1d_v3_adam_mae 0.939982 0.035601 0.934766 0.037298\n",
|
| 231 |
+
" conv1d_v3_sgd_mae 0.939909 0.035625 0.934060 0.037500\n"
|
| 232 |
+
]
|
| 233 |
+
}
|
| 234 |
+
],
|
| 235 |
+
"source": [
|
| 236 |
+
"# Loss function comparison\n",
|
| 237 |
+
"if 'df' in dir() and len(df) > 0:\n",
|
| 238 |
+
" loss_df = df[df['experiment'] == 'loss_optimizer'][['model', 'val_r2_mean', 'val_rmse_mean', 'test_r2', 'test_rmse']]\n",
|
| 239 |
+
" loss_df = loss_df.sort_values('test_r2', ascending=False)\n",
|
| 240 |
+
" print(\"LOSS FUNCTION COMPARISON\")\n",
|
| 241 |
+
" print(\"=\"*50)\n",
|
| 242 |
+
" print(loss_df.to_string(index=False))"
|
| 243 |
+
]
|
| 244 |
+
},
|
| 245 |
+
{
|
| 246 |
+
"cell_type": "markdown",
|
| 247 |
+
"id": "e29b86d1",
|
| 248 |
+
"metadata": {},
|
| 249 |
+
"source": [
|
| 250 |
+
"## 5. Evaluation & Model Comparison"
|
| 251 |
+
]
|
| 252 |
+
},
|
| 253 |
+
{
|
| 254 |
+
"cell_type": "code",
|
| 255 |
+
"execution_count": 48,
|
| 256 |
+
"id": "5128b8be",
|
| 257 |
+
"metadata": {},
|
| 258 |
+
"outputs": [
|
| 259 |
+
{
|
| 260 |
+
"name": "stdout",
|
| 261 |
+
"output_type": "stream",
|
| 262 |
+
"text": [
|
| 263 |
+
"ALL EXPERIMENTS RANKED BY TEST R²\n",
|
| 264 |
+
"======================================================================\n",
|
| 265 |
+
" experiment model val_r2_mean test_r2 test_rmse\n",
|
| 266 |
+
" optimizer conv1d_v3_rmsprop_mse 0.946803 0.954934 0.031001\n",
|
| 267 |
+
" loss_optimizer conv1d_v3_rmsprop_mse 0.950038 0.954592 0.031119\n",
|
| 268 |
+
" optimizer conv1d_v3_adam_mse 0.949678 0.953484 0.031496\n",
|
| 269 |
+
" loss_optimizer conv1d_v3_adam_mse 0.948571 0.952860 0.031707\n",
|
| 270 |
+
" optimizer conv1d_v3_sgd_mse 0.950863 0.952354 0.031876\n",
|
| 271 |
+
" loss_optimizer conv1d_v3_sgd_mse 0.950748 0.952171 0.031937\n",
|
| 272 |
+
" loss_optimizer conv1d_v3_rmsprop_mae 0.943196 0.944302 0.034465\n",
|
| 273 |
+
" loss_optimizer conv1d_v3_adam_mae 0.939982 0.934766 0.037298\n",
|
| 274 |
+
" loss_optimizer conv1d_v3_sgd_mae 0.939909 0.934060 0.037500\n",
|
| 275 |
+
" conv1d_variants conv1d 0.922923 0.928322 0.039097\n",
|
| 276 |
+
" conv1d_variants conv1d_v2 0.799991 0.826827 0.060770\n",
|
| 277 |
+
"different_models conv1d 0.932681 NaN NaN\n",
|
| 278 |
+
"different_models dense 0.820046 NaN NaN\n",
|
| 279 |
+
"different_models lstm 0.768530 NaN NaN\n"
|
| 280 |
+
]
|
| 281 |
+
}
|
| 282 |
+
],
|
| 283 |
+
"source": [
|
| 284 |
+
"# All results ranked by test R²\n",
|
| 285 |
+
"if 'df' in dir() and len(df) > 0:\n",
|
| 286 |
+
" print(\"ALL EXPERIMENTS RANKED BY TEST R²\")\n",
|
| 287 |
+
" print(\"=\"*70)\n",
|
| 288 |
+
" ranked = df.sort_values('test_r2', ascending=False, na_position='last')\n",
|
| 289 |
+
" print(ranked[['experiment', 'model', 'val_r2_mean', 'test_r2', 'test_rmse']].to_string(index=False))"
|
| 290 |
+
]
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
"cell_type": "code",
|
| 294 |
+
"execution_count": 49,
|
| 295 |
+
"id": "38efd1c2",
|
| 296 |
+
"metadata": {},
|
| 297 |
+
"outputs": [
|
| 298 |
+
{
|
| 299 |
+
"data": {
|
| 300 |
+
"image/png": "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1ltvyf333y+RkZHmfaxbt052795tXktfu06dOrJnzx7Xc3T/gQceMOPVedXzsGLFimTHvXDhgjz33HNSvHhxcwydx1WrVqVrbAAAAJmBGJcYlxgXAAD4feJ28ODBMm7cOBk6dKhs375d5s2bZ5J5mizVatO8efPKxo0bZeHChSax9+STTyZ7/sqVK00SUP98//335b333jOb0oTlhg0bkiUM9bKxn3/+WTp16uTxGAcMGCCrV6+WJUuWyPLly03y8IcffvDouekdg2VZ8vXXX8vOnTvlzjvvvOrxN23aJE8//bRJAutzli1blux5zz77rKxdu1Y+++wz+eqrr2TNmjWXjV0T4AcPHjRz+PHHH5tEsCZz02P06NEmub1lyxZTOazv7bHHHjPnV8eo78v93GkC/r777jPv9ccff5RmzZqZ5PGBAwdcj9HHawJ4/vz5Zr60Kloft2vXrlTHoInekydPJtsAAEDaQoJCpGGZhmbTfXgPMW5yxLjEuAAAZHV+1ypBq0GnTp0q06ZNk27dupnbtOK0Xr16MmPGDDl//rzMnj3bVFsqfZwm915++WWT3FWa2NXbQ0JCTMKwefPmJhn46KOPSpUqVUxlqyaDNTGstJpUKze1wtcTmmCcOXOmfPDBB9K4cWNzmyaIS5Qo4dHzPR3DiRMnTGWpJh/1vWjy9O67777q8TXRqfOj1a65cuWS0qVLS40aNVzzq2PV17bHPmvWLClWrJjr+b/99pt8+eWXJrmsVa9K369WzaaHtnZo37692R80aJDccccd5v3arR60ilgfY9M50c098bt48WKTYNaErb4vHav+aY9Xq281Ma23jxkz5rIxjB07VkaOHJmucQMAkJWFBCclbuFdxLjEuDZiXAAA4LcVtzt27DCJSjupmPI+TezZSVtVt25dc9mZVpa6J0Y10WnTdgDu1aJa8aqJS/ub/g8//NDc5imtlI2Li0vW7kB70laqVMnjY3gyBk26arWqVhdrqwitlPWkLYAmdzVZq316u3TpYpLC2tNM7d2717SNuO2221yPz507d7Kx6zyHhobKrbfe6rpNE+C6UFp6aGsHm51Ur1q1arLbNBFvV8FqQlwTsZog1tfSS8l0LHbFrbbJSEhIkIoVK5r77E0rn92rl1NWtmgC3N60ihgAACCjEeNeQoxLjAsAAPy04lZ7ql6vsLCwy/qt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",
|
| 301 |
+
"text/plain": [
|
| 302 |
+
"<Figure size 1400x500 with 2 Axes>"
|
| 303 |
+
]
|
| 304 |
+
},
|
| 305 |
+
"metadata": {},
|
| 306 |
+
"output_type": "display_data"
|
| 307 |
+
}
|
| 308 |
+
],
|
| 309 |
+
"source": [
|
| 310 |
+
"# Visualization\n",
|
| 311 |
+
"if 'df' in dir() and len(df) > 0:\n",
|
| 312 |
+
" fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
|
| 313 |
+
" \n",
|
| 314 |
+
" # Plot 1: R² comparison\n",
|
| 315 |
+
" plot_df = df[df['test_r2'].notna()].sort_values('test_r2', ascending=True)\n",
|
| 316 |
+
" colors = ['green' if r > 0.95 else 'orange' if r > 0.90 else 'red' for r in plot_df['test_r2']]\n",
|
| 317 |
+
" axes[0].barh(plot_df['model'], plot_df['test_r2'], color=colors)\n",
|
| 318 |
+
" axes[0].set_xlabel('Test R²')\n",
|
| 319 |
+
" axes[0].set_title('Model Performance (Test R²)')\n",
|
| 320 |
+
" axes[0].axvline(0.95, color='green', linestyle='--', alpha=0.5, label='95%')\n",
|
| 321 |
+
" axes[0].axvline(0.90, color='orange', linestyle='--', alpha=0.5, label='90%')\n",
|
| 322 |
+
" axes[0].legend()\n",
|
| 323 |
+
" \n",
|
| 324 |
+
" # Plot 2: RMSE comparison\n",
|
| 325 |
+
" axes[1].barh(plot_df['model'], plot_df['test_rmse'], color='steelblue')\n",
|
| 326 |
+
" axes[1].set_xlabel('Test RMSE')\n",
|
| 327 |
+
" axes[1].set_title('Model Error (Test RMSE)')\n",
|
| 328 |
+
" \n",
|
| 329 |
+
" plt.tight_layout()\n",
|
| 330 |
+
" plt.show()"
|
| 331 |
+
]
|
| 332 |
+
},
|
| 333 |
+
{
|
| 334 |
+
"cell_type": "markdown",
|
| 335 |
+
"id": "be01d215",
|
| 336 |
+
"metadata": {},
|
| 337 |
+
"source": [
|
| 338 |
+
"## 6. Champion Model\n",
|
| 339 |
+
"\n",
|
| 340 |
+
"### Conv1D_v3 + RMSprop + MSE\n",
|
| 341 |
+
"\n",
|
| 342 |
+
"| Parameter | Value |\n",
|
| 343 |
+
"|-----------|-------|\n",
|
| 344 |
+
"| Architecture | Conv1D |\n",
|
| 345 |
+
"| Filters | (128, 256) |\n",
|
| 346 |
+
"| Kernel size | 3 |\n",
|
| 347 |
+
"| Pool size | 3 |\n",
|
| 348 |
+
"| Dense layers | (256, 128, 64) |\n",
|
| 349 |
+
"| Activation | ReLU |\n",
|
| 350 |
+
"| Dropout | 0.2 |\n",
|
| 351 |
+
"| Optimizer | RMSprop (lr=0.001) |\n",
|
| 352 |
+
"| Loss | MSE |\n",
|
| 353 |
+
"| Window size | 30 frames |\n",
|
| 354 |
+
"| Batch size | 32 |\n",
|
| 355 |
+
"| Epochs | 100 (early stopping) |\n",
|
| 356 |
+
"\n",
|
| 357 |
+
"### Performance\n",
|
| 358 |
+
"\n",
|
| 359 |
+
"| Metric | Validation | Test |\n",
|
| 360 |
+
"|--------|------------|------|\n",
|
| 361 |
+
"| R² | 0.9468 ± 0.0049 | **0.9549** |\n",
|
| 362 |
+
"| RMSE | 0.0335 ± 0.0018 | **0.0310** |\n",
|
| 363 |
+
"| MAE | 0.0241 ± 0.0013 | 0.0229 |\n",
|
| 364 |
+
"\n",
|
| 365 |
+
"1. **Conv1D captures temporal patterns** - The 30-frame windows allow the model to learn motion dynamics\n",
|
| 366 |
+
"2. **Deeper architecture (v3)** - More filters and dense layers provide sufficient capacity\n",
|
| 367 |
+
"3. **RMSprop optimizer** - Adaptive learning rate works well with this data distribution\n",
|
| 368 |
+
"4. **MSE loss** - Better than MAE for regression with continuous targets"
|
| 369 |
+
]
|
| 370 |
+
},
|
| 371 |
+
{
|
| 372 |
+
"cell_type": "markdown",
|
| 373 |
+
"id": "bbf697d8",
|
| 374 |
+
"metadata": {},
|
| 375 |
+
"source": [
|
| 376 |
+
"## 7. Dead Ends\n",
|
| 377 |
+
"\n",
|
| 378 |
+
"### What Did NOT Work\n",
|
| 379 |
+
"\n",
|
| 380 |
+
"| Configuration | R² | Issue |\n",
|
| 381 |
+
"|---------------|------|-------|\n",
|
| 382 |
+
"| LSTM | 0.77 | Overfitting, slow training |\n",
|
| 383 |
+
"| GRU | 0.74 | Similar to LSTM, underperformed |\n",
|
| 384 |
+
"| Dense MLP | 0.82 | Cannot capture temporal patterns |\n",
|
| 385 |
+
"| Conv1D_v2 (high dropout) | 0.83 | Too much regularization |\n",
|
| 386 |
+
"| MAE loss | ~0.93-0.94 | Lower R² than MSE |"
|
| 387 |
+
]
|
| 388 |
+
},
|
| 389 |
+
{
|
| 390 |
+
"cell_type": "markdown",
|
| 391 |
+
"id": "e68fd0e3",
|
| 392 |
+
"metadata": {},
|
| 393 |
+
"source": [
|
| 394 |
+
"## 8. Usage Guide\n",
|
| 395 |
+
"\n",
|
| 396 |
+
"### Loading the Best Model"
|
| 397 |
+
]
|
| 398 |
+
},
|
| 399 |
+
{
|
| 400 |
+
"cell_type": "code",
|
| 401 |
+
"execution_count": 50,
|
| 402 |
+
"id": "82cdb3ff",
|
| 403 |
+
"metadata": {},
|
| 404 |
+
"outputs": [
|
| 405 |
+
{
|
| 406 |
+
"name": "stdout",
|
| 407 |
+
"output_type": "stream",
|
| 408 |
+
"text": [
|
| 409 |
+
"Model loaded from cv_results_loss_optimizer/conv1d_v3_rmsprop_mse_fold4_best.h5\n"
|
| 410 |
+
]
|
| 411 |
+
},
|
| 412 |
+
{
|
| 413 |
+
"data": {
|
| 414 |
+
"text/html": [
|
| 415 |
+
"<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: \"Conv1DModel\"</span>\n",
|
| 416 |
+
"</pre>\n"
|
| 417 |
+
],
|
| 418 |
+
"text/plain": [
|
| 419 |
+
"\u001b[1mModel: \"Conv1DModel\"\u001b[0m\n"
|
| 420 |
+
]
|
| 421 |
+
},
|
| 422 |
+
"metadata": {},
|
| 423 |
+
"output_type": "display_data"
|
| 424 |
+
},
|
| 425 |
+
{
|
| 426 |
+
"data": {
|
| 427 |
+
"text/html": [
|
| 428 |
+
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
|
| 429 |
+
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
|
| 430 |
+
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
|
| 431 |
+
"│ xy_seq_input (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">30</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">26</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 432 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 433 |
+
"│ conv_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv1D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">30</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">10,112</span> │\n",
|
| 434 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 435 |
+
"│ pool_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">MaxPooling1D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 436 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 437 |
+
"│ drop_conv_1 (<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\">10</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 438 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 439 |
+
"│ conv_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv1D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">98,560</span> │\n",
|
| 440 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 441 |
+
"│ pool_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">MaxPooling1D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">4</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 442 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 443 |
+
"│ drop_conv_2 (<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\">4</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 444 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 445 |
+
"│ gap (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">GlobalAveragePooling1D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 446 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 447 |
+
"│ fc_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\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">65,792</span> │\n",
|
| 448 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 449 |
+
"│ drop_fc_1 (<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\">256</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 450 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 451 |
+
"│ fc_2 (<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\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">32,896</span> │\n",
|
| 452 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 453 |
+
"│ drop_fc_2 (<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\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
|
| 454 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 455 |
+
"│ fc_3 (<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\">64</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">8,256</span> │\n",
|
| 456 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 457 |
+
"│ drop_fc_3 (<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",
|
| 458 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 459 |
+
"│ z_output (<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\">13</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">845</span> │\n",
|
| 460 |
+
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
|
| 461 |
+
"</pre>\n"
|
| 462 |
+
],
|
| 463 |
+
"text/plain": [
|
| 464 |
+
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
|
| 465 |
+
"┃\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",
|
| 466 |
+
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
|
| 467 |
+
"│ xy_seq_input (\u001b[38;5;33mInputLayer\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m30\u001b[0m, \u001b[38;5;34m26\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 468 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 469 |
+
"│ conv_1 (\u001b[38;5;33mConv1D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m30\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m10,112\u001b[0m │\n",
|
| 470 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 471 |
+
"│ pool_1 (\u001b[38;5;33mMaxPooling1D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 472 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 473 |
+
"│ drop_conv_1 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 474 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 475 |
+
"│ conv_2 (\u001b[38;5;33mConv1D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m98,560\u001b[0m │\n",
|
| 476 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 477 |
+
"│ pool_2 (\u001b[38;5;33mMaxPooling1D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m4\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 478 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 479 |
+
"│ drop_conv_2 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m4\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 480 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 481 |
+
"│ gap (\u001b[38;5;33mGlobalAveragePooling1D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 482 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 483 |
+
"│ fc_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m65,792\u001b[0m │\n",
|
| 484 |
+
"├─────��───────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 485 |
+
"│ drop_fc_1 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 486 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 487 |
+
"│ fc_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m32,896\u001b[0m │\n",
|
| 488 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 489 |
+
"│ drop_fc_2 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
|
| 490 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 491 |
+
"│ fc_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m8,256\u001b[0m │\n",
|
| 492 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 493 |
+
"│ drop_fc_3 (\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",
|
| 494 |
+
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
|
| 495 |
+
"│ z_output (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m13\u001b[0m) │ \u001b[38;5;34m845\u001b[0m │\n",
|
| 496 |
+
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
|
| 497 |
+
]
|
| 498 |
+
},
|
| 499 |
+
"metadata": {},
|
| 500 |
+
"output_type": "display_data"
|
| 501 |
+
},
|
| 502 |
+
{
|
| 503 |
+
"data": {
|
| 504 |
+
"text/html": [
|
| 505 |
+
"<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\">216,461</span> (845.55 KB)\n",
|
| 506 |
+
"</pre>\n"
|
| 507 |
+
],
|
| 508 |
+
"text/plain": [
|
| 509 |
+
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m216,461\u001b[0m (845.55 KB)\n"
|
| 510 |
+
]
|
| 511 |
+
},
|
| 512 |
+
"metadata": {},
|
| 513 |
+
"output_type": "display_data"
|
| 514 |
+
},
|
| 515 |
+
{
|
| 516 |
+
"data": {
|
| 517 |
+
"text/html": [
|
| 518 |
+
"<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\">216,461</span> (845.55 KB)\n",
|
| 519 |
+
"</pre>\n"
|
| 520 |
+
],
|
| 521 |
+
"text/plain": [
|
| 522 |
+
"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m216,461\u001b[0m (845.55 KB)\n"
|
| 523 |
+
]
|
| 524 |
+
},
|
| 525 |
+
"metadata": {},
|
| 526 |
+
"output_type": "display_data"
|
| 527 |
+
},
|
| 528 |
+
{
|
| 529 |
+
"data": {
|
| 530 |
+
"text/html": [
|
| 531 |
+
"<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",
|
| 532 |
+
"</pre>\n"
|
| 533 |
+
],
|
| 534 |
+
"text/plain": [
|
| 535 |
+
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
|
| 536 |
+
]
|
| 537 |
+
},
|
| 538 |
+
"metadata": {},
|
| 539 |
+
"output_type": "display_data"
|
| 540 |
+
}
|
| 541 |
+
],
|
| 542 |
+
"source": [
|
| 543 |
+
"# Example: Load and use the best model\n",
|
| 544 |
+
"import tensorflow as tf\n",
|
| 545 |
+
"from tensorflow import keras\n",
|
| 546 |
+
"\n",
|
| 547 |
+
"# Best model path\n",
|
| 548 |
+
"BEST_MODEL_PATH = 'cv_results_loss_optimizer/conv1d_v3_rmsprop_mse_fold4_best.h5'\n",
|
| 549 |
+
"\n",
|
| 550 |
+
"if os.path.exists(BEST_MODEL_PATH):\n",
|
| 551 |
+
" # Rebuild the model architecture and load weights (avoids Keras version mismatch)\n",
|
| 552 |
+
" from models import build_conv1d_model\n",
|
| 553 |
+
" model = build_conv1d_model(\n",
|
| 554 |
+
" filters=(128, 256),\n",
|
| 555 |
+
" kernel_size=3,\n",
|
| 556 |
+
" pool_size=3,\n",
|
| 557 |
+
" dense_units=(256, 128, 64),\n",
|
| 558 |
+
" dropout_rate=0.2\n",
|
| 559 |
+
" )\n",
|
| 560 |
+
" model.load_weights(BEST_MODEL_PATH)\n",
|
| 561 |
+
" model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])\n",
|
| 562 |
+
" \n",
|
| 563 |
+
" print(f\"Model loaded from {BEST_MODEL_PATH}\")\n",
|
| 564 |
+
" model.summary()\n",
|
| 565 |
+
"else:\n",
|
| 566 |
+
" print(f\"Model not found at {BEST_MODEL_PATH}\")"
|
| 567 |
+
]
|
| 568 |
+
},
|
| 569 |
+
{
|
| 570 |
+
"cell_type": "code",
|
| 571 |
+
"execution_count": 51,
|
| 572 |
+
"id": "15765a85",
|
| 573 |
+
"metadata": {},
|
| 574 |
+
"outputs": [
|
| 575 |
+
{
|
| 576 |
+
"name": "stdout",
|
| 577 |
+
"output_type": "stream",
|
| 578 |
+
"text": [
|
| 579 |
+
"Input shape: (1, 30, 26)\n",
|
| 580 |
+
"Output shape: (1, 13)\n",
|
| 581 |
+
"Predicted Z values: [ 0.05649754 0.03968733 -0.03916807 0.05462698 0.00482728]...\n"
|
| 582 |
+
]
|
| 583 |
+
}
|
| 584 |
+
],
|
| 585 |
+
"source": [
|
| 586 |
+
"# Example inference\n",
|
| 587 |
+
"def predict_z_coordinates(model, xy_sequence):\n",
|
| 588 |
+
" \"\"\"\n",
|
| 589 |
+
" Predict Z coordinates from X/Y sequence.\n",
|
| 590 |
+
" \n",
|
| 591 |
+
" Args:\n",
|
| 592 |
+
" model: Loaded Keras model\n",
|
| 593 |
+
" xy_sequence: numpy array of shape (batch, 30, 26)\n",
|
| 594 |
+
" 30 = window size, 26 = 13 joints × 2 (x, y)\n",
|
| 595 |
+
" \n",
|
| 596 |
+
" Returns:\n",
|
| 597 |
+
" z_predictions: numpy array of shape (batch, 13)\n",
|
| 598 |
+
" 13 z-coordinates for each joint\n",
|
| 599 |
+
" \"\"\"\n",
|
| 600 |
+
" return model.predict(xy_sequence, verbose=0)\n",
|
| 601 |
+
"\n",
|
| 602 |
+
"# Example with dummy data\n",
|
| 603 |
+
"if 'model' in dir():\n",
|
| 604 |
+
" dummy_input = np.random.randn(1, 30, 26).astype(np.float32)\n",
|
| 605 |
+
" z_pred = predict_z_coordinates(model, dummy_input)\n",
|
| 606 |
+
" print(f\"Input shape: {dummy_input.shape}\")\n",
|
| 607 |
+
" print(f\"Output shape: {z_pred.shape}\")\n",
|
| 608 |
+
" print(f\"Predicted Z values: {z_pred[0][:5]}...\")"
|
| 609 |
+
]
|
| 610 |
+
},
|
| 611 |
+
{
|
| 612 |
+
"cell_type": "markdown",
|
| 613 |
+
"id": "6fb36696",
|
| 614 |
+
"metadata": {},
|
| 615 |
+
"source": [
|
| 616 |
+
"### Retraining the Model\n",
|
| 617 |
+
"\n",
|
| 618 |
+
"```bash\n",
|
| 619 |
+
"# Run the cross-validation training script\n",
|
| 620 |
+
"cd A9\n",
|
| 621 |
+
"python cv_training.py\n",
|
| 622 |
+
"```\n",
|
| 623 |
+
"\n",
|
| 624 |
+
"Or modify `all_models_config.py` to change architecture parameters."
|
| 625 |
+
]
|
| 626 |
+
}
|
| 627 |
+
],
|
| 628 |
+
"metadata": {
|
| 629 |
+
"kernelspec": {
|
| 630 |
+
"display_name": "Python 3",
|
| 631 |
+
"language": "python",
|
| 632 |
+
"name": "python3"
|
| 633 |
+
},
|
| 634 |
+
"language_info": {
|
| 635 |
+
"codemirror_mode": {
|
| 636 |
+
"name": "ipython",
|
| 637 |
+
"version": 3
|
| 638 |
+
},
|
| 639 |
+
"file_extension": ".py",
|
| 640 |
+
"mimetype": "text/x-python",
|
| 641 |
+
"name": "python",
|
| 642 |
+
"nbconvert_exporter": "python",
|
| 643 |
+
"pygments_lexer": "ipython3",
|
| 644 |
+
"version": "3.10.0"
|
| 645 |
+
}
|
| 646 |
+
},
|
| 647 |
+
"nbformat": 4,
|
| 648 |
+
"nbformat_minor": 5
|
| 649 |
+
}
|
A9/aggregate_results.py
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
A9 Results Aggregation Script
|
| 3 |
+
|
| 4 |
+
Aggregates all cross-validation results from the cv_results folders
|
| 5 |
+
and produces summary tables for the A9_Report.ipynb notebook.
|
| 6 |
+
|
| 7 |
+
Usage:
|
| 8 |
+
python aggregate_results.py
|
| 9 |
+
|
| 10 |
+
Output:
|
| 11 |
+
- results_summary.csv: All experiment results in one table
|
| 12 |
+
- results_summary.json: Same data in JSON format
|
| 13 |
+
- Prints summary to console
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
import os
|
| 17 |
+
import json
|
| 18 |
+
import re
|
| 19 |
+
import pandas as pd
|
| 20 |
+
from pathlib import Path
|
| 21 |
+
|
| 22 |
+
# Result directories
|
| 23 |
+
RESULT_DIRS = {
|
| 24 |
+
'different_models': 'cv_results_different_models',
|
| 25 |
+
'conv1d_variants': 'cv_results_conv1D_variants',
|
| 26 |
+
'optimizer': 'cv_results_optimizer',
|
| 27 |
+
'loss_optimizer': 'cv_results_loss_optimizer',
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def parse_summary_txt(filepath):
|
| 32 |
+
"""Parse summary.txt file to extract metrics."""
|
| 33 |
+
results = []
|
| 34 |
+
|
| 35 |
+
with open(filepath, 'r') as f:
|
| 36 |
+
content = f.read()
|
| 37 |
+
|
| 38 |
+
# Find all model sections with their metrics
|
| 39 |
+
# Pattern matches lines like " Optimizer: SGD, Loss: MSE" or just model names
|
| 40 |
+
sections = re.split(r'\n(?=[A-Z_]+(?:_[A-Z]+)*\n-{10,})', content)
|
| 41 |
+
|
| 42 |
+
for section in sections:
|
| 43 |
+
if 'Val RMSE:' in section or 'Test RMSE:' in section:
|
| 44 |
+
lines = section.strip().split('\n')
|
| 45 |
+
model_name = lines[0].strip() if lines else 'unknown'
|
| 46 |
+
|
| 47 |
+
# Skip separator lines
|
| 48 |
+
if model_name.startswith('-'):
|
| 49 |
+
continue
|
| 50 |
+
|
| 51 |
+
row = {'model': model_name.lower()}
|
| 52 |
+
|
| 53 |
+
# Extract metrics using regex
|
| 54 |
+
val_rmse = re.search(r'Val RMSE:\s*([\d.]+)\s*±\s*([\d.]+)', section)
|
| 55 |
+
val_mae = re.search(r'Val MAE:\s*([\d.]+)\s*±\s*([\d.]+)', section)
|
| 56 |
+
val_r2 = re.search(r'Val R²:\s*([\d.]+)\s*±\s*([\d.]+)', section)
|
| 57 |
+
test_rmse = re.search(r'Test RMSE:\s*([\d.]+)', section)
|
| 58 |
+
test_mae = re.search(r'Test MAE:\s*([\d.]+)', section)
|
| 59 |
+
test_r2 = re.search(r'Test R²:\s*([\d.]+)', section)
|
| 60 |
+
best_fold = re.search(r'Best Fold:\s*(\d+)', section)
|
| 61 |
+
|
| 62 |
+
if val_rmse:
|
| 63 |
+
row['val_rmse_mean'] = float(val_rmse.group(1))
|
| 64 |
+
row['val_rmse_std'] = float(val_rmse.group(2))
|
| 65 |
+
if val_mae:
|
| 66 |
+
row['val_mae_mean'] = float(val_mae.group(1))
|
| 67 |
+
row['val_mae_std'] = float(val_mae.group(2))
|
| 68 |
+
if val_r2:
|
| 69 |
+
row['val_r2_mean'] = float(val_r2.group(1))
|
| 70 |
+
row['val_r2_std'] = float(val_r2.group(2))
|
| 71 |
+
if test_rmse:
|
| 72 |
+
row['test_rmse'] = float(test_rmse.group(1))
|
| 73 |
+
if test_mae:
|
| 74 |
+
row['test_mae'] = float(test_mae.group(1))
|
| 75 |
+
if test_r2:
|
| 76 |
+
row['test_r2'] = float(test_r2.group(1))
|
| 77 |
+
if best_fold:
|
| 78 |
+
row['best_fold'] = int(best_fold.group(1))
|
| 79 |
+
|
| 80 |
+
# Only add if we found some metrics
|
| 81 |
+
if len(row) > 1:
|
| 82 |
+
results.append(row)
|
| 83 |
+
|
| 84 |
+
return results
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def parse_summary_header(filepath):
|
| 88 |
+
"""Parse the header summary section of summary.txt."""
|
| 89 |
+
results = []
|
| 90 |
+
|
| 91 |
+
with open(filepath, 'r') as f:
|
| 92 |
+
content = f.read()
|
| 93 |
+
|
| 94 |
+
# Pattern 1: Standard format (DENSE:, CONV1D:, CONV1D_V3: etc.)
|
| 95 |
+
# Fixed to properly capture model names with underscores and numbers
|
| 96 |
+
pattern1 = r'([A-Z][A-Z0-9_]*):\s*\n\s*Best Fold:\s*(\d+)\s*\n\s*Val RMSE:\s*([\d.]+)\s*±\s*([\d.]+)\s*\n\s*Val MAE:\s*([\d.]+)\s*±\s*([\d.]+)\s*\n\s*Val R²:\s*([\d.]+)\s*±\s*([\d.]+)(?:\s*\n\s*Test RMSE:\s*([\d.]+))?(?:\s*\n\s*Test MAE:\s*([\d.]+))?(?:\s*\n\s*Test R²:\s*([\d.]+))?'
|
| 97 |
+
|
| 98 |
+
# Pattern 2: Optimizer format (Optimizer: SGD, etc.)
|
| 99 |
+
pattern2 = r'Optimizer:\s*([A-Z]+)(?:,\s*Loss:\s*([A-Z]+))?\s*\n\s*Best Fold:\s*(\d+)\s*\n\s*Val RMSE:\s*([\d.]+)\s*±\s*([\d.]+)\s*\n\s*Val MAE:\s*([\d.]+)\s*±\s*([\d.]+)\s*\n\s*Val R²:\s*([\d.]+)\s*±\s*([\d.]+)(?:\s*\n\s*Test RMSE:\s*([\d.]+))?(?:\s*\n\s*Test MAE:\s*([\d.]+))?(?:\s*\n\s*Test R²:\s*([\d.]+))?'
|
| 100 |
+
|
| 101 |
+
seen_models = set()
|
| 102 |
+
|
| 103 |
+
# Try pattern 1
|
| 104 |
+
matches = re.finditer(pattern1, content, re.MULTILINE)
|
| 105 |
+
for match in matches:
|
| 106 |
+
model_name = match.group(1).lower()
|
| 107 |
+
|
| 108 |
+
# Skip detailed sections (those that start with model name and have "-----" after)
|
| 109 |
+
# We only want the summary sections at the top
|
| 110 |
+
pos = match.start()
|
| 111 |
+
next_line_start = content.find('\n', match.end()) + 1
|
| 112 |
+
if next_line_start < len(content):
|
| 113 |
+
next_line = content[next_line_start:next_line_start+50]
|
| 114 |
+
if '---' in next_line:
|
| 115 |
+
continue
|
| 116 |
+
|
| 117 |
+
# Skip duplicates
|
| 118 |
+
if model_name in seen_models:
|
| 119 |
+
continue
|
| 120 |
+
seen_models.add(model_name)
|
| 121 |
+
|
| 122 |
+
row = {
|
| 123 |
+
'model': model_name,
|
| 124 |
+
'best_fold': int(match.group(2)),
|
| 125 |
+
'val_rmse_mean': float(match.group(3)),
|
| 126 |
+
'val_rmse_std': float(match.group(4)),
|
| 127 |
+
'val_mae_mean': float(match.group(5)),
|
| 128 |
+
'val_mae_std': float(match.group(6)),
|
| 129 |
+
'val_r2_mean': float(match.group(7)),
|
| 130 |
+
'val_r2_std': float(match.group(8)),
|
| 131 |
+
}
|
| 132 |
+
if match.group(9):
|
| 133 |
+
row['test_rmse'] = float(match.group(9))
|
| 134 |
+
if match.group(10):
|
| 135 |
+
row['test_mae'] = float(match.group(10))
|
| 136 |
+
if match.group(11):
|
| 137 |
+
row['test_r2'] = float(match.group(11))
|
| 138 |
+
|
| 139 |
+
results.append(row)
|
| 140 |
+
|
| 141 |
+
# Try pattern 2 for optimizer/loss variants
|
| 142 |
+
matches = re.finditer(pattern2, content, re.MULTILINE)
|
| 143 |
+
for match in matches:
|
| 144 |
+
optimizer = match.group(1).lower()
|
| 145 |
+
loss = match.group(2).lower() if match.group(2) else 'mse'
|
| 146 |
+
model_name = f"conv1d_v3_{optimizer}_{loss}"
|
| 147 |
+
|
| 148 |
+
# Skip duplicates
|
| 149 |
+
if model_name in seen_models:
|
| 150 |
+
continue
|
| 151 |
+
seen_models.add(model_name)
|
| 152 |
+
|
| 153 |
+
row = {
|
| 154 |
+
'model': model_name,
|
| 155 |
+
'best_fold': int(match.group(3)),
|
| 156 |
+
'val_rmse_mean': float(match.group(4)),
|
| 157 |
+
'val_rmse_std': float(match.group(5)),
|
| 158 |
+
'val_mae_mean': float(match.group(6)),
|
| 159 |
+
'val_mae_std': float(match.group(7)),
|
| 160 |
+
'val_r2_mean': float(match.group(8)),
|
| 161 |
+
'val_r2_std': float(match.group(9)),
|
| 162 |
+
}
|
| 163 |
+
if match.group(10):
|
| 164 |
+
row['test_rmse'] = float(match.group(10))
|
| 165 |
+
if match.group(11):
|
| 166 |
+
row['test_mae'] = float(match.group(11))
|
| 167 |
+
if match.group(12):
|
| 168 |
+
row['test_r2'] = float(match.group(12))
|
| 169 |
+
|
| 170 |
+
results.append(row)
|
| 171 |
+
|
| 172 |
+
return results
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def main():
|
| 176 |
+
script_dir = Path(__file__).parent
|
| 177 |
+
os.chdir(script_dir)
|
| 178 |
+
|
| 179 |
+
all_results = []
|
| 180 |
+
|
| 181 |
+
print("=" * 60)
|
| 182 |
+
print("A9 Results Aggregation")
|
| 183 |
+
print("=" * 60)
|
| 184 |
+
|
| 185 |
+
# Load results from each experiment directory by parsing summary.txt
|
| 186 |
+
for exp_name, dir_name in RESULT_DIRS.items():
|
| 187 |
+
summary_path = Path(dir_name) / 'summary.txt'
|
| 188 |
+
print(f"\nLoading from {summary_path}...")
|
| 189 |
+
|
| 190 |
+
if not summary_path.exists():
|
| 191 |
+
print(f" Warning: {summary_path} not found")
|
| 192 |
+
continue
|
| 193 |
+
|
| 194 |
+
results = parse_summary_header(summary_path)
|
| 195 |
+
print(f" Found {len(results)} model results")
|
| 196 |
+
|
| 197 |
+
for row in results:
|
| 198 |
+
row['experiment'] = exp_name
|
| 199 |
+
all_results.append(row)
|
| 200 |
+
|
| 201 |
+
if not all_results:
|
| 202 |
+
print("\nNo results found!")
|
| 203 |
+
return
|
| 204 |
+
|
| 205 |
+
# Create DataFrame
|
| 206 |
+
df = pd.DataFrame(all_results)
|
| 207 |
+
|
| 208 |
+
# Reorder columns
|
| 209 |
+
cols = ['experiment', 'model', 'best_fold', 'val_r2_mean', 'val_r2_std',
|
| 210 |
+
'val_rmse_mean', 'val_rmse_std', 'val_mae_mean', 'val_mae_std',
|
| 211 |
+
'test_r2', 'test_rmse', 'test_mae']
|
| 212 |
+
df = df[[c for c in cols if c in df.columns]]
|
| 213 |
+
|
| 214 |
+
# Sort by test_r2 descending, then val_r2_mean
|
| 215 |
+
df['sort_key'] = df['test_r2'].fillna(df['val_r2_mean'])
|
| 216 |
+
df = df.sort_values('sort_key', ascending=False).drop('sort_key', axis=1)
|
| 217 |
+
|
| 218 |
+
# Save to CSV
|
| 219 |
+
df.to_csv('results_summary.csv', index=False)
|
| 220 |
+
print(f"\nSaved to results_summary.csv ({len(df)} rows)")
|
| 221 |
+
|
| 222 |
+
# Save to JSON
|
| 223 |
+
df.to_json('results_summary.json', orient='records', indent=2)
|
| 224 |
+
print(f"Saved to results_summary.json")
|
| 225 |
+
|
| 226 |
+
# Print summary tables
|
| 227 |
+
print("\n" + "=" * 60)
|
| 228 |
+
print("SUMMARY: All Experiments Ranked by R²")
|
| 229 |
+
print("=" * 60)
|
| 230 |
+
|
| 231 |
+
print(df.to_string(index=False, float_format=lambda x: f'{x:.4f}' if pd.notna(x) else 'N/A'))
|
| 232 |
+
|
| 233 |
+
# Best model
|
| 234 |
+
print("\n" + "=" * 60)
|
| 235 |
+
print("CHAMPION MODEL")
|
| 236 |
+
print("=" * 60)
|
| 237 |
+
best = df.iloc[0]
|
| 238 |
+
print(f"Model: {best['model']}")
|
| 239 |
+
print(f"Experiment: {best['experiment']}")
|
| 240 |
+
if pd.notna(best.get('val_r2_mean')):
|
| 241 |
+
print(f"Validation R²: {best['val_r2_mean']:.4f} ± {best['val_r2_std']:.4f}")
|
| 242 |
+
print(f"Validation RMSE: {best['val_rmse_mean']:.4f} ± {best['val_rmse_std']:.4f}")
|
| 243 |
+
if pd.notna(best.get('test_r2')):
|
| 244 |
+
print(f"Test R²: {best['test_r2']:.4f}")
|
| 245 |
+
print(f"Test RMSE: {best['test_rmse']:.4f}")
|
| 246 |
+
|
| 247 |
+
# Dead ends (R² < 0.85)
|
| 248 |
+
print("\n" + "=" * 60)
|
| 249 |
+
print("DEAD ENDS (R² < 0.85)")
|
| 250 |
+
print("=" * 60)
|
| 251 |
+
r2_col = 'test_r2' if 'test_r2' in df.columns else 'val_r2_mean'
|
| 252 |
+
dead_ends = df[df[r2_col] < 0.85]
|
| 253 |
+
if len(dead_ends) > 0:
|
| 254 |
+
print(dead_ends[['experiment', 'model', 'val_r2_mean', 'test_r2']].to_string(index=False))
|
| 255 |
+
else:
|
| 256 |
+
print("None found")
|
| 257 |
+
|
| 258 |
+
# Group summaries
|
| 259 |
+
print("\n" + "=" * 60)
|
| 260 |
+
print("EXPERIMENT SUMMARIES")
|
| 261 |
+
print("=" * 60)
|
| 262 |
+
|
| 263 |
+
for exp_name in RESULT_DIRS.keys():
|
| 264 |
+
exp_df = df[df['experiment'] == exp_name]
|
| 265 |
+
if len(exp_df) > 0:
|
| 266 |
+
print(f"\n{exp_name.upper()}:")
|
| 267 |
+
print(exp_df[['model', 'val_r2_mean', 'val_rmse_mean', 'test_r2', 'test_rmse']].to_string(index=False))
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
if __name__ == '__main__':
|
| 271 |
+
main()
|
A9/results_summary.csv
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
experiment,model,best_fold,val_r2_mean,val_r2_std,val_rmse_mean,val_rmse_std,val_mae_mean,val_mae_std,test_r2,test_rmse,test_mae
|
| 2 |
+
optimizer,conv1d_v3_rmsprop_mse,1,0.946803,0.004864,0.033498,0.001768,0.024131,0.001299,0.954934,0.031001,0.022902
|
| 3 |
+
loss_optimizer,conv1d_v3_rmsprop_mse,4,0.950038,0.002828,0.032467,0.000629,0.023508,0.000743,0.954592,0.031119,0.022788
|
| 4 |
+
optimizer,conv1d_v3_adam_mse,1,0.949678,0.004671,0.032558,0.001222,0.02349,0.000625,0.953484,0.031496,0.023255
|
| 5 |
+
loss_optimizer,conv1d_v3_adam_mse,1,0.948571,0.002204,0.032956,0.000841,0.02364,0.000489,0.95286,0.031707,0.023486
|
| 6 |
+
optimizer,conv1d_v3_sgd_mse,1,0.950863,0.002815,0.032199,0.000687,0.023269,0.000512,0.952354,0.031876,0.023561
|
| 7 |
+
loss_optimizer,conv1d_v3_sgd_mse,1,0.950748,0.003632,0.032241,0.001373,0.023373,0.00102,0.952171,0.031937,0.023461
|
| 8 |
+
loss_optimizer,conv1d_v3_rmsprop_mae,1,0.943196,0.003858,0.034623,0.00129,0.023639,0.000801,0.944302,0.034465,0.023634
|
| 9 |
+
loss_optimizer,conv1d_v3_adam_mae,1,0.939982,0.002526,0.035601,0.000889,0.02409,0.00052,0.934766,0.037298,0.0258
|
| 10 |
+
loss_optimizer,conv1d_v3_sgd_mae,1,0.939909,0.001839,0.035625,0.000619,0.023964,0.000383,0.93406,0.0375,0.024983
|
| 11 |
+
different_models,conv1d,2,0.932681,0.005506,0.037704,0.001386,0.027598,0.000905,,,
|
| 12 |
+
conv1d_variants,conv1d,1,0.922923,0.007843,0.040316,0.002366,0.029083,0.001559,0.928322,0.039097,0.028836
|
| 13 |
+
conv1d_variants,conv1d_v2,5,0.799991,0.031161,0.064831,0.005451,0.048145,0.003991,0.826827,0.06077,0.044539
|
| 14 |
+
different_models,dense,4,0.820046,0.002133,0.058055,0.000435,0.042731,0.000244,,,
|
| 15 |
+
different_models,lstm,4,0.76853,0.025836,0.069834,0.003102,0.052217,0.002199,,,
|
A9/results_summary.json
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"experiment":"optimizer",
|
| 4 |
+
"model":"conv1d_v3_rmsprop_mse",
|
| 5 |
+
"best_fold":1,
|
| 6 |
+
"val_r2_mean":0.946803,
|
| 7 |
+
"val_r2_std":0.004864,
|
| 8 |
+
"val_rmse_mean":0.033498,
|
| 9 |
+
"val_rmse_std":0.001768,
|
| 10 |
+
"val_mae_mean":0.024131,
|
| 11 |
+
"val_mae_std":0.001299,
|
| 12 |
+
"test_r2":0.954934,
|
| 13 |
+
"test_rmse":0.031001,
|
| 14 |
+
"test_mae":0.022902
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"experiment":"loss_optimizer",
|
| 18 |
+
"model":"conv1d_v3_rmsprop_mse",
|
| 19 |
+
"best_fold":4,
|
| 20 |
+
"val_r2_mean":0.950038,
|
| 21 |
+
"val_r2_std":0.002828,
|
| 22 |
+
"val_rmse_mean":0.032467,
|
| 23 |
+
"val_rmse_std":0.000629,
|
| 24 |
+
"val_mae_mean":0.023508,
|
| 25 |
+
"val_mae_std":0.000743,
|
| 26 |
+
"test_r2":0.954592,
|
| 27 |
+
"test_rmse":0.031119,
|
| 28 |
+
"test_mae":0.022788
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"experiment":"optimizer",
|
| 32 |
+
"model":"conv1d_v3_adam_mse",
|
| 33 |
+
"best_fold":1,
|
| 34 |
+
"val_r2_mean":0.949678,
|
| 35 |
+
"val_r2_std":0.004671,
|
| 36 |
+
"val_rmse_mean":0.032558,
|
| 37 |
+
"val_rmse_std":0.001222,
|
| 38 |
+
"val_mae_mean":0.02349,
|
| 39 |
+
"val_mae_std":0.000625,
|
| 40 |
+
"test_r2":0.953484,
|
| 41 |
+
"test_rmse":0.031496,
|
| 42 |
+
"test_mae":0.023255
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"experiment":"loss_optimizer",
|
| 46 |
+
"model":"conv1d_v3_adam_mse",
|
| 47 |
+
"best_fold":1,
|
| 48 |
+
"val_r2_mean":0.948571,
|
| 49 |
+
"val_r2_std":0.002204,
|
| 50 |
+
"val_rmse_mean":0.032956,
|
| 51 |
+
"val_rmse_std":0.000841,
|
| 52 |
+
"val_mae_mean":0.02364,
|
| 53 |
+
"val_mae_std":0.000489,
|
| 54 |
+
"test_r2":0.95286,
|
| 55 |
+
"test_rmse":0.031707,
|
| 56 |
+
"test_mae":0.023486
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"experiment":"optimizer",
|
| 60 |
+
"model":"conv1d_v3_sgd_mse",
|
| 61 |
+
"best_fold":1,
|
| 62 |
+
"val_r2_mean":0.950863,
|
| 63 |
+
"val_r2_std":0.002815,
|
| 64 |
+
"val_rmse_mean":0.032199,
|
| 65 |
+
"val_rmse_std":0.000687,
|
| 66 |
+
"val_mae_mean":0.023269,
|
| 67 |
+
"val_mae_std":0.000512,
|
| 68 |
+
"test_r2":0.952354,
|
| 69 |
+
"test_rmse":0.031876,
|
| 70 |
+
"test_mae":0.023561
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"experiment":"loss_optimizer",
|
| 74 |
+
"model":"conv1d_v3_sgd_mse",
|
| 75 |
+
"best_fold":1,
|
| 76 |
+
"val_r2_mean":0.950748,
|
| 77 |
+
"val_r2_std":0.003632,
|
| 78 |
+
"val_rmse_mean":0.032241,
|
| 79 |
+
"val_rmse_std":0.001373,
|
| 80 |
+
"val_mae_mean":0.023373,
|
| 81 |
+
"val_mae_std":0.00102,
|
| 82 |
+
"test_r2":0.952171,
|
| 83 |
+
"test_rmse":0.031937,
|
| 84 |
+
"test_mae":0.023461
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"experiment":"loss_optimizer",
|
| 88 |
+
"model":"conv1d_v3_rmsprop_mae",
|
| 89 |
+
"best_fold":1,
|
| 90 |
+
"val_r2_mean":0.943196,
|
| 91 |
+
"val_r2_std":0.003858,
|
| 92 |
+
"val_rmse_mean":0.034623,
|
| 93 |
+
"val_rmse_std":0.00129,
|
| 94 |
+
"val_mae_mean":0.023639,
|
| 95 |
+
"val_mae_std":0.000801,
|
| 96 |
+
"test_r2":0.944302,
|
| 97 |
+
"test_rmse":0.034465,
|
| 98 |
+
"test_mae":0.023634
|
| 99 |
+
},
|
| 100 |
+
{
|
| 101 |
+
"experiment":"loss_optimizer",
|
| 102 |
+
"model":"conv1d_v3_adam_mae",
|
| 103 |
+
"best_fold":1,
|
| 104 |
+
"val_r2_mean":0.939982,
|
| 105 |
+
"val_r2_std":0.002526,
|
| 106 |
+
"val_rmse_mean":0.035601,
|
| 107 |
+
"val_rmse_std":0.000889,
|
| 108 |
+
"val_mae_mean":0.02409,
|
| 109 |
+
"val_mae_std":0.00052,
|
| 110 |
+
"test_r2":0.934766,
|
| 111 |
+
"test_rmse":0.037298,
|
| 112 |
+
"test_mae":0.0258
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"experiment":"loss_optimizer",
|
| 116 |
+
"model":"conv1d_v3_sgd_mae",
|
| 117 |
+
"best_fold":1,
|
| 118 |
+
"val_r2_mean":0.939909,
|
| 119 |
+
"val_r2_std":0.001839,
|
| 120 |
+
"val_rmse_mean":0.035625,
|
| 121 |
+
"val_rmse_std":0.000619,
|
| 122 |
+
"val_mae_mean":0.023964,
|
| 123 |
+
"val_mae_std":0.000383,
|
| 124 |
+
"test_r2":0.93406,
|
| 125 |
+
"test_rmse":0.0375,
|
| 126 |
+
"test_mae":0.024983
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"experiment":"different_models",
|
| 130 |
+
"model":"conv1d",
|
| 131 |
+
"best_fold":2,
|
| 132 |
+
"val_r2_mean":0.932681,
|
| 133 |
+
"val_r2_std":0.005506,
|
| 134 |
+
"val_rmse_mean":0.037704,
|
| 135 |
+
"val_rmse_std":0.001386,
|
| 136 |
+
"val_mae_mean":0.027598,
|
| 137 |
+
"val_mae_std":0.000905,
|
| 138 |
+
"test_r2":null,
|
| 139 |
+
"test_rmse":null,
|
| 140 |
+
"test_mae":null
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"experiment":"conv1d_variants",
|
| 144 |
+
"model":"conv1d",
|
| 145 |
+
"best_fold":1,
|
| 146 |
+
"val_r2_mean":0.922923,
|
| 147 |
+
"val_r2_std":0.007843,
|
| 148 |
+
"val_rmse_mean":0.040316,
|
| 149 |
+
"val_rmse_std":0.002366,
|
| 150 |
+
"val_mae_mean":0.029083,
|
| 151 |
+
"val_mae_std":0.001559,
|
| 152 |
+
"test_r2":0.928322,
|
| 153 |
+
"test_rmse":0.039097,
|
| 154 |
+
"test_mae":0.028836
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"experiment":"conv1d_variants",
|
| 158 |
+
"model":"conv1d_v2",
|
| 159 |
+
"best_fold":5,
|
| 160 |
+
"val_r2_mean":0.799991,
|
| 161 |
+
"val_r2_std":0.031161,
|
| 162 |
+
"val_rmse_mean":0.064831,
|
| 163 |
+
"val_rmse_std":0.005451,
|
| 164 |
+
"val_mae_mean":0.048145,
|
| 165 |
+
"val_mae_std":0.003991,
|
| 166 |
+
"test_r2":0.826827,
|
| 167 |
+
"test_rmse":0.06077,
|
| 168 |
+
"test_mae":0.044539
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"experiment":"different_models",
|
| 172 |
+
"model":"dense",
|
| 173 |
+
"best_fold":4,
|
| 174 |
+
"val_r2_mean":0.820046,
|
| 175 |
+
"val_r2_std":0.002133,
|
| 176 |
+
"val_rmse_mean":0.058055,
|
| 177 |
+
"val_rmse_std":0.000435,
|
| 178 |
+
"val_mae_mean":0.042731,
|
| 179 |
+
"val_mae_std":0.000244,
|
| 180 |
+
"test_r2":null,
|
| 181 |
+
"test_rmse":null,
|
| 182 |
+
"test_mae":null
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"experiment":"different_models",
|
| 186 |
+
"model":"lstm",
|
| 187 |
+
"best_fold":4,
|
| 188 |
+
"val_r2_mean":0.76853,
|
| 189 |
+
"val_r2_std":0.025836,
|
| 190 |
+
"val_rmse_mean":0.069834,
|
| 191 |
+
"val_rmse_std":0.003102,
|
| 192 |
+
"val_mae_mean":0.052217,
|
| 193 |
+
"val_mae_std":0.002199,
|
| 194 |
+
"test_r2":null,
|
| 195 |
+
"test_rmse":null,
|
| 196 |
+
"test_mae":null
|
| 197 |
+
}
|
| 198 |
+
]
|