changeset 2:186424a7eca7 draft

planemo upload for repository https://github.com/goeckslab/gleam.git commit 91fa4aba245520fc0680088a07cead66bcfd4ed2
author goeckslab
date Thu, 03 Jul 2025 20:43:24 +0000
parents 39202fe5cf97
children 2c3a3dfaf1a9
files constants.py image_learner.xml image_learner_cli.py test-data/age_regression.zip test-data/expected_regression.html test-data/utkface_labels.csv utils.py
diffstat 7 files changed, 900 insertions(+), 391 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/constants.py	Thu Jul 03 20:43:24 2025 +0000
@@ -0,0 +1,119 @@
+from typing import Any, Dict
+
+# --- Constants ---
+SPLIT_COLUMN_NAME = "split"
+LABEL_COLUMN_NAME = "label"
+IMAGE_PATH_COLUMN_NAME = "image_path"
+DEFAULT_SPLIT_PROBABILITIES = [0.7, 0.1, 0.2]
+TEMP_CSV_FILENAME = "processed_data_for_ludwig.csv"
+TEMP_CONFIG_FILENAME = "ludwig_config.yaml"
+TEMP_DIR_PREFIX = "ludwig_api_work_"
+MODEL_ENCODER_TEMPLATES: Dict[str, Any] = {
+    "stacked_cnn": "stacked_cnn",
+    "resnet18": {"type": "resnet", "model_variant": 18},
+    "resnet34": {"type": "resnet", "model_variant": 34},
+    "resnet50": {"type": "resnet", "model_variant": 50},
+    "resnet101": {"type": "resnet", "model_variant": 101},
+    "resnet152": {"type": "resnet", "model_variant": 152},
+    "resnext50_32x4d": {"type": "resnext", "model_variant": "50_32x4d"},
+    "resnext101_32x8d": {"type": "resnext", "model_variant": "101_32x8d"},
+    "resnext101_64x4d": {"type": "resnext", "model_variant": "101_64x4d"},
+    "resnext152_32x8d": {"type": "resnext", "model_variant": "152_32x8d"},
+    "wide_resnet50_2": {"type": "wide_resnet", "model_variant": "50_2"},
+    "wide_resnet101_2": {"type": "wide_resnet", "model_variant": "101_2"},
+    "wide_resnet103_2": {"type": "wide_resnet", "model_variant": "103_2"},
+    "efficientnet_b0": {"type": "efficientnet", "model_variant": "b0"},
+    "efficientnet_b1": {"type": "efficientnet", "model_variant": "b1"},
+    "efficientnet_b2": {"type": "efficientnet", "model_variant": "b2"},
+    "efficientnet_b3": {"type": "efficientnet", "model_variant": "b3"},
+    "efficientnet_b4": {"type": "efficientnet", "model_variant": "b4"},
+    "efficientnet_b5": {"type": "efficientnet", "model_variant": "b5"},
+    "efficientnet_b6": {"type": "efficientnet", "model_variant": "b6"},
+    "efficientnet_b7": {"type": "efficientnet", "model_variant": "b7"},
+    "efficientnet_v2_s": {"type": "efficientnet", "model_variant": "v2_s"},
+    "efficientnet_v2_m": {"type": "efficientnet", "model_variant": "v2_m"},
+    "efficientnet_v2_l": {"type": "efficientnet", "model_variant": "v2_l"},
+    "regnet_y_400mf": {"type": "regnet", "model_variant": "y_400mf"},
+    "regnet_y_800mf": {"type": "regnet", "model_variant": "y_800mf"},
+    "regnet_y_1_6gf": {"type": "regnet", "model_variant": "y_1_6gf"},
+    "regnet_y_3_2gf": {"type": "regnet", "model_variant": "y_3_2gf"},
+    "regnet_y_8gf": {"type": "regnet", "model_variant": "y_8gf"},
+    "regnet_y_16gf": {"type": "regnet", "model_variant": "y_16gf"},
+    "regnet_y_32gf": {"type": "regnet", "model_variant": "y_32gf"},
+    "regnet_y_128gf": {"type": "regnet", "model_variant": "y_128gf"},
+    "regnet_x_400mf": {"type": "regnet", "model_variant": "x_400mf"},
+    "regnet_x_800mf": {"type": "regnet", "model_variant": "x_800mf"},
+    "regnet_x_1_6gf": {"type": "regnet", "model_variant": "x_1_6gf"},
+    "regnet_x_3_2gf": {"type": "regnet", "model_variant": "x_3_2gf"},
+    "regnet_x_8gf": {"type": "regnet", "model_variant": "x_8gf"},
+    "regnet_x_16gf": {"type": "regnet", "model_variant": "x_16gf"},
+    "regnet_x_32gf": {"type": "regnet", "model_variant": "x_32gf"},
+    "vgg11": {"type": "vgg", "model_variant": 11},
+    "vgg11_bn": {"type": "vgg", "model_variant": "11_bn"},
+    "vgg13": {"type": "vgg", "model_variant": 13},
+    "vgg13_bn": {"type": "vgg", "model_variant": "13_bn"},
+    "vgg16": {"type": "vgg", "model_variant": 16},
+    "vgg16_bn": {"type": "vgg", "model_variant": "16_bn"},
+    "vgg19": {"type": "vgg", "model_variant": 19},
+    "vgg19_bn": {"type": "vgg", "model_variant": "19_bn"},
+    "shufflenet_v2_x0_5": {"type": "shufflenet_v2", "model_variant": "x0_5"},
+    "shufflenet_v2_x1_0": {"type": "shufflenet_v2", "model_variant": "x1_0"},
+    "shufflenet_v2_x1_5": {"type": "shufflenet_v2", "model_variant": "x1_5"},
+    "shufflenet_v2_x2_0": {"type": "shufflenet_v2", "model_variant": "x2_0"},
+    "squeezenet1_0": {"type": "squeezenet", "model_variant": "1_0"},
+    "squeezenet1_1": {"type": "squeezenet", "model_variant": "1_1"},
+    "swin_t": {"type": "swin_transformer", "model_variant": "t"},
+    "swin_s": {"type": "swin_transformer", "model_variant": "s"},
+    "swin_b": {"type": "swin_transformer", "model_variant": "b"},
+    "swin_v2_t": {"type": "swin_transformer", "model_variant": "v2_t"},
+    "swin_v2_s": {"type": "swin_transformer", "model_variant": "v2_s"},
+    "swin_v2_b": {"type": "swin_transformer", "model_variant": "v2_b"},
+    "vit_b_16": {"type": "vision_transformer", "model_variant": "b_16"},
+    "vit_b_32": {"type": "vision_transformer", "model_variant": "b_32"},
+    "vit_l_16": {"type": "vision_transformer", "model_variant": "l_16"},
+    "vit_l_32": {"type": "vision_transformer", "model_variant": "l_32"},
+    "vit_h_14": {"type": "vision_transformer", "model_variant": "h_14"},
+    "convnext_tiny": {"type": "convnext", "model_variant": "tiny"},
+    "convnext_small": {"type": "convnext", "model_variant": "small"},
+    "convnext_base": {"type": "convnext", "model_variant": "base"},
+    "convnext_large": {"type": "convnext", "model_variant": "large"},
+    "maxvit_t": {"type": "maxvit", "model_variant": "t"},
+    "alexnet": {"type": "alexnet"},
+    "googlenet": {"type": "googlenet"},
+    "inception_v3": {"type": "inception_v3"},
+    "mobilenet_v2": {"type": "mobilenet_v2"},
+    "mobilenet_v3_large": {"type": "mobilenet_v3_large"},
+    "mobilenet_v3_small": {"type": "mobilenet_v3_small"},
+}
+METRIC_DISPLAY_NAMES = {
+    "accuracy": "Accuracy",
+    "accuracy_micro": "Accuracy-Micro",
+    "loss": "Loss",
+    "roc_auc": "ROC-AUC",
+    "roc_auc_macro": "ROC-AUC-Macro",
+    "roc_auc_micro": "ROC-AUC-Micro",
+    "hits_at_k": "Hits at K",
+    "precision": "Precision",
+    "recall": "Recall",
+    "specificity": "Specificity",
+    "kappa_score": "Cohen's Kappa",
+    "token_accuracy": "Token Accuracy",
+    "avg_precision_macro": "Precision-Macro",
+    "avg_recall_macro": "Recall-Macro",
+    "avg_f1_score_macro": "F1-score-Macro",
+    "avg_precision_micro": "Precision-Micro",
+    "avg_recall_micro": "Recall-Micro",
+    "avg_f1_score_micro": "F1-score-Micro",
+    "avg_precision_weighted": "Precision-Weighted",
+    "avg_recall_weighted": "Recall-Weighted",
+    "avg_f1_score_weighted": "F1-score-Weighted",
+    "average_precision_macro": "Precision-Average-Macro",
+    "average_precision_micro": "Precision-Average-Micro",
+    "average_precision_samples": "Precision-Average-Samples",
+    "mean_squared_error": "Mean Squared Error",
+    "mean_absolute_error": "Mean Absolute Error",
+    "r2": "R² Score",
+    "root_mean_squared_error": "Root Mean Squared Error",
+    "mean_absolute_percentage_error": "Mean Absolute % Error",
+    "root_mean_squared_percentage_error": "Root Mean Squared % Error",
+}
--- a/image_learner.xml	Wed Jul 02 18:59:10 2025 +0000
+++ b/image_learner.xml	Thu Jul 03 20:43:24 2025 +0000
@@ -44,23 +44,26 @@
                     #if $batch_size_define == "true"
                         --batch-size "$batch_size"
                     #end if
-                    --split-probabilities "$train_split" "$val_split" "$test_split"   
+                    --split-probabilities "$train_split" "$val_split" "$test_split"
                 #end if
-                --random-seed "$random_seed" 
+                #if $augmentation
+                    --augmentation "$augmentation"
+                #end if
+                --random-seed "$random_seed"
                 --output-dir "." &&
 
             mkdir -p '$output_model.extra_files_path' &&
             cp -r experiment_run/model/*.json experiment_run/model/model_weights '$output_model.extra_files_path' &&
 
-            echo "Image Learner Classification Experiment is Done!"        
+            echo "Image Learner Classification Experiment is Done!"
         ]]>
     </command>
-    
+
     <inputs>
         <param argument="input_csv" type="data" format="csv" optional="false" label="the metadata csv containing image_path column, label column and optional split column" />
         <param name="image_zip" type="data" format="zip" optional="false" label="Image zip" help="Image zip file containing your image data"/>
         <param name="model_name" type="select" optional="false" label="Select a model for your experiment" >
-           
+
             <option value="resnet18">Resnet18</option>
             <option value="resnet34">Resnet34</option>
             <option value="resnet50">Resnet50</option>
@@ -140,8 +143,7 @@
         <conditional name="scratch_fine_tune">
             <param name="use_pretrained" type="select"
                 label="Use pretrained weights?"
-                help="If select no, the encoder, combiner, and decoder will all be initialized and trained from scratch.  
-               (e.g. when your images are very different from ImageNet or no suitable pretrained model exists.)">
+                help="If select no, the encoder, combiner, and decoder will all be initialized and trained from scratch. (e.g. when your images are very different from ImageNet or no suitable pretrained model exists.)">
                 <option value="false">No</option>
                 <option value="true" selected="true">Yes</option>
             </param>
@@ -156,6 +158,20 @@
                 <!-- No additional parameters to show if the user selects 'No' -->
             </when>
         </conditional>
+        <param argument="augmentation"
+               name="augmentation"
+               type="select"
+               multiple="true"
+               display="checkboxes"
+               label="Image Augmentation"
+               help="Pick any combination of augmentations to apply">
+            <option value="random_horizontal_flip">Random Horizontal Flip</option>
+            <option value="random_vertical_flip">Random Vertical Flip</option>
+            <option value="random_rotate">Random Rotate</option>
+            <option value="random_blur">Random Blur</option>
+            <option value="random_brightness">Random Brightness</option>
+            <option value="random_contrast">Random Contrast</option>
+        </param>
         <param argument="random_seed" type="integer" value="42" optional="true" label="Random seed (set for reproducibility)" min="0" max="999999"/>
         <conditional name="advanced_settings">
             <param name="customize_defaults" type="select" label="Customize Default Settings?" help="Select yes if you want to customize the default settings of the experiment.">
@@ -205,8 +221,8 @@
             <when value="false">
                 <!-- No additional parameters to show if the user selects 'No' -->
             </when>
-        </conditional>    
-    </inputs>       
+        </conditional>
+    </inputs>
     <outputs>
         <data format="ludwig_model" name="output_model" label="${tool.name} trained model on ${on_string}" />
         <data format="html" name="output_report" from_work_dir="image_classification_results_report.html" label="${tool.name} report on ${on_string}" />
@@ -238,6 +254,48 @@
                 </element>
             </output_collection>
         </test>
+        <test expect_num_outputs="3">
+            <param name="input_csv" value="mnist_subset.csv" ftype="csv" />
+            <param name="image_zip" value="mnist_subset.zip" ftype="zip" />
+            <param name="model_name" value="resnet18" />
+            <param name="augmentation" value="random_horizontal_flip,random_vertical_flip,random_rotate" />
+            <output name="output_report">
+                <assert_contents>
+                    <has_text text="Results Summary" />
+                    <has_text text="Train/Validation Results" />
+                    <has_text text="Test Results" />
+                </assert_contents>
+            </output>
+
+            <output_collection name="output_pred_csv" type="list" >
+                <element name="predictions.csv" >
+                    <assert_contents>
+                        <has_n_columns n="1" />
+                    </assert_contents>
+                </element>
+            </output_collection>
+        </test>
+        <test expect_num_outputs="3">
+            <param name="input_csv" value="utkface_labels.csv" ftype="csv" />
+            <param name="image_zip" value="age_regression.zip" ftype="zip" />
+            <param name="model_name" value="resnet18" />
+            <output name="output_report">
+                <assert_contents>
+                    <has_text text="Results Summary" />
+                    <has_text text="Train/Validation Results" />
+                    <has_text text="Test Results" />
+                </assert_contents>
+            </output>
+            <output name="output_report" file="expected_regression.html" compare="sim_size"/>
+
+            <output_collection name="output_pred_csv" type="list" >
+                <element name="predictions.csv" >
+                    <assert_contents>
+                        <has_n_columns n="1" />
+                    </assert_contents>
+                </element>
+            </output_collection>
+        </test>
     </tests>
     <help>
         <![CDATA[
@@ -248,6 +306,8 @@
 Optionally, you can also add a column with the name 'split' to specify which split each row belongs to (train, val, test). 
 If you do not provide a split column, the tool will automatically split the data into train, val, and test sets based on the proportions you specify or [0.7, 0.1, 0.2] by default.
 
+**If the selected label column has more than 10 unique values, the tool will automatically treat the task as a regression problem and apply appropriate metrics (e.g., MSE, RMSE, R²).**
+
 
 **Outputs**
 The tool will output a trained model in the form of a ludwig_model file,
--- a/image_learner_cli.py	Wed Jul 02 18:59:10 2025 +0000
+++ b/image_learner_cli.py	Thu Jul 03 20:43:24 2025 +0000
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
 import argparse
 import json
 import logging
@@ -11,7 +10,18 @@
 from typing import Any, Dict, Optional, Protocol, Tuple
 
 import pandas as pd
+import pandas.api.types as ptypes
 import yaml
+from constants import (
+    IMAGE_PATH_COLUMN_NAME,
+    LABEL_COLUMN_NAME,
+    METRIC_DISPLAY_NAMES,
+    MODEL_ENCODER_TEMPLATES,
+    SPLIT_COLUMN_NAME,
+    TEMP_CONFIG_FILENAME,
+    TEMP_CSV_FILENAME,
+    TEMP_DIR_PREFIX
+)
 from ludwig.globals import (
     DESCRIPTION_FILE_NAME,
     PREDICTIONS_PARQUET_FILE_NAME,
@@ -21,258 +31,29 @@
 from ludwig.utils.data_utils import get_split_path
 from ludwig.visualize import get_visualizations_registry
 from sklearn.model_selection import train_test_split
-from utils import encode_image_to_base64, get_html_closing, get_html_template
-
-# --- Constants ---
-SPLIT_COLUMN_NAME = "split"
-LABEL_COLUMN_NAME = "label"
-IMAGE_PATH_COLUMN_NAME = "image_path"
-DEFAULT_SPLIT_PROBABILITIES = [0.7, 0.1, 0.2]
-TEMP_CSV_FILENAME = "processed_data_for_ludwig.csv"
-TEMP_CONFIG_FILENAME = "ludwig_config.yaml"
-TEMP_DIR_PREFIX = "ludwig_api_work_"
-MODEL_ENCODER_TEMPLATES: Dict[str, Any] = {
-    "stacked_cnn": "stacked_cnn",
-    "resnet18": {"type": "resnet", "model_variant": 18},
-    "resnet34": {"type": "resnet", "model_variant": 34},
-    "resnet50": {"type": "resnet", "model_variant": 50},
-    "resnet101": {"type": "resnet", "model_variant": 101},
-    "resnet152": {"type": "resnet", "model_variant": 152},
-    "resnext50_32x4d": {"type": "resnext", "model_variant": "50_32x4d"},
-    "resnext101_32x8d": {"type": "resnext", "model_variant": "101_32x8d"},
-    "resnext101_64x4d": {"type": "resnext", "model_variant": "101_64x4d"},
-    "resnext152_32x8d": {"type": "resnext", "model_variant": "152_32x8d"},
-    "wide_resnet50_2": {"type": "wide_resnet", "model_variant": "50_2"},
-    "wide_resnet101_2": {"type": "wide_resnet", "model_variant": "101_2"},
-    "wide_resnet103_2": {"type": "wide_resnet", "model_variant": "103_2"},
-    "efficientnet_b0": {"type": "efficientnet", "model_variant": "b0"},
-    "efficientnet_b1": {"type": "efficientnet", "model_variant": "b1"},
-    "efficientnet_b2": {"type": "efficientnet", "model_variant": "b2"},
-    "efficientnet_b3": {"type": "efficientnet", "model_variant": "b3"},
-    "efficientnet_b4": {"type": "efficientnet", "model_variant": "b4"},
-    "efficientnet_b5": {"type": "efficientnet", "model_variant": "b5"},
-    "efficientnet_b6": {"type": "efficientnet", "model_variant": "b6"},
-    "efficientnet_b7": {"type": "efficientnet", "model_variant": "b7"},
-    "efficientnet_v2_s": {"type": "efficientnet", "model_variant": "v2_s"},
-    "efficientnet_v2_m": {"type": "efficientnet", "model_variant": "v2_m"},
-    "efficientnet_v2_l": {"type": "efficientnet", "model_variant": "v2_l"},
-    "regnet_y_400mf": {"type": "regnet", "model_variant": "y_400mf"},
-    "regnet_y_800mf": {"type": "regnet", "model_variant": "y_800mf"},
-    "regnet_y_1_6gf": {"type": "regnet", "model_variant": "y_1_6gf"},
-    "regnet_y_3_2gf": {"type": "regnet", "model_variant": "y_3_2gf"},
-    "regnet_y_8gf": {"type": "regnet", "model_variant": "y_8gf"},
-    "regnet_y_16gf": {"type": "regnet", "model_variant": "y_16gf"},
-    "regnet_y_32gf": {"type": "regnet", "model_variant": "y_32gf"},
-    "regnet_y_128gf": {"type": "regnet", "model_variant": "y_128gf"},
-    "regnet_x_400mf": {"type": "regnet", "model_variant": "x_400mf"},
-    "regnet_x_800mf": {"type": "regnet", "model_variant": "x_800mf"},
-    "regnet_x_1_6gf": {"type": "regnet", "model_variant": "x_1_6gf"},
-    "regnet_x_3_2gf": {"type": "regnet", "model_variant": "x_3_2gf"},
-    "regnet_x_8gf": {"type": "regnet", "model_variant": "x_8gf"},
-    "regnet_x_16gf": {"type": "regnet", "model_variant": "x_16gf"},
-    "regnet_x_32gf": {"type": "regnet", "model_variant": "x_32gf"},
-    "vgg11": {"type": "vgg", "model_variant": 11},
-    "vgg11_bn": {"type": "vgg", "model_variant": "11_bn"},
-    "vgg13": {"type": "vgg", "model_variant": 13},
-    "vgg13_bn": {"type": "vgg", "model_variant": "13_bn"},
-    "vgg16": {"type": "vgg", "model_variant": 16},
-    "vgg16_bn": {"type": "vgg", "model_variant": "16_bn"},
-    "vgg19": {"type": "vgg", "model_variant": 19},
-    "vgg19_bn": {"type": "vgg", "model_variant": "19_bn"},
-    "shufflenet_v2_x0_5": {"type": "shufflenet_v2", "model_variant": "x0_5"},
-    "shufflenet_v2_x1_0": {"type": "shufflenet_v2", "model_variant": "x1_0"},
-    "shufflenet_v2_x1_5": {"type": "shufflenet_v2", "model_variant": "x1_5"},
-    "shufflenet_v2_x2_0": {"type": "shufflenet_v2", "model_variant": "x2_0"},
-    "squeezenet1_0": {"type": "squeezenet", "model_variant": "1_0"},
-    "squeezenet1_1": {"type": "squeezenet", "model_variant": "1_1"},
-    "swin_t": {"type": "swin_transformer", "model_variant": "t"},
-    "swin_s": {"type": "swin_transformer", "model_variant": "s"},
-    "swin_b": {"type": "swin_transformer", "model_variant": "b"},
-    "swin_v2_t": {"type": "swin_transformer", "model_variant": "v2_t"},
-    "swin_v2_s": {"type": "swin_transformer", "model_variant": "v2_s"},
-    "swin_v2_b": {"type": "swin_transformer", "model_variant": "v2_b"},
-    "vit_b_16": {"type": "vision_transformer", "model_variant": "b_16"},
-    "vit_b_32": {"type": "vision_transformer", "model_variant": "b_32"},
-    "vit_l_16": {"type": "vision_transformer", "model_variant": "l_16"},
-    "vit_l_32": {"type": "vision_transformer", "model_variant": "l_32"},
-    "vit_h_14": {"type": "vision_transformer", "model_variant": "h_14"},
-    "convnext_tiny": {"type": "convnext", "model_variant": "tiny"},
-    "convnext_small": {"type": "convnext", "model_variant": "small"},
-    "convnext_base": {"type": "convnext", "model_variant": "base"},
-    "convnext_large": {"type": "convnext", "model_variant": "large"},
-    "maxvit_t": {"type": "maxvit", "model_variant": "t"},
-    "alexnet": {"type": "alexnet"},
-    "googlenet": {"type": "googlenet"},
-    "inception_v3": {"type": "inception_v3"},
-    "mobilenet_v2": {"type": "mobilenet_v2"},
-    "mobilenet_v3_large": {"type": "mobilenet_v3_large"},
-    "mobilenet_v3_small": {"type": "mobilenet_v3_small"},
-}
-METRIC_DISPLAY_NAMES = {
-    "accuracy": "Accuracy",
-    "accuracy_micro": "Accuracy-Micro",
-    "loss": "Loss",
-    "roc_auc": "ROC-AUC",
-    "roc_auc_macro": "ROC-AUC-Macro",
-    "roc_auc_micro": "ROC-AUC-Micro",
-    "hits_at_k": "Hits at K",
-    "precision": "Precision",
-    "recall": "Recall",
-    "specificity": "Specificity",
-    "kappa_score": "Cohen's Kappa",
-    "token_accuracy": "Token Accuracy",
-    "avg_precision_macro": "Precision-Macro",
-    "avg_recall_macro": "Recall-Macro",
-    "avg_f1_score_macro": "F1-score-Macro",
-    "avg_precision_micro": "Precision-Micro",
-    "avg_recall_micro": "Recall-Micro",
-    "avg_f1_score_micro": "F1-score-Micro",
-    "avg_precision_weighted": "Precision-Weighted",
-    "avg_recall_weighted": "Recall-Weighted",
-    "avg_f1_score_weighted": "F1-score-Weighted",
-    "average_precision_macro": " Precision-Average-Macro",
-    "average_precision_micro": "Precision-Average-Micro",
-    "average_precision_samples": "Precision-Average-Samples",
-}
+from utils import (
+    build_tabbed_html,
+    encode_image_to_base64,
+    get_html_closing,
+    get_html_template,
+    get_metrics_help_modal
+)
 
 # --- Logging Setup ---
 logging.basicConfig(
     level=logging.INFO,
-    format="%(asctime)s %(levelname)s %(name)s: %(message)s",
+    format='%(asctime)s %(levelname)s %(name)s: %(message)s',
 )
 logger = logging.getLogger("ImageLearner")
 
 
-def get_metrics_help_modal() -> str:
-    modal_html = """
-<div id="metricsHelpModal" class="modal">
-  <div class="modal-content">
-    <span class="close">×</span>
-    <h2>Model Evaluation Metrics — Help Guide</h2>
-    <div class="metrics-guide">
-      <h3>1) General Metrics</h3>
-      <p><strong>Loss:</strong> Measures the difference between predicted and actual values. Lower is better. Often used for optimization during training.</p>
-      <p><strong>Accuracy:</strong> Proportion of correct predictions among all predictions. Simple but can be misleading for imbalanced datasets.</p>
-      <p><strong>Micro Accuracy:</strong> Calculates accuracy by summing up all individual true positives and true negatives across all classes, making it suitable for multiclass or multilabel problems.</p>
-      <p><strong>Token Accuracy:</strong> Measures how often the predicted tokens (e.g., in sequences) match the true tokens. Useful in sequence prediction tasks like NLP.</p>
-      <h3>2) Precision, Recall & Specificity</h3>
-      <p><strong>Precision:</strong> Out of all positive predictions, how many were correct. Precision = TP / (TP + FP). Helps when false positives are costly.</p>
-      <p><strong>Recall (Sensitivity):</strong> Out of all actual positives, how many were predicted correctly. Recall = TP / (TP + FN). Important when missing positives is risky.</p>
-      <p><strong>Specificity:</strong> True negative rate. Measures how well the model identifies negatives. Specificity = TN / (TN + FP). Useful in medical testing to avoid false alarms.</p>
-      <h3>3) Macro, Micro, and Weighted Averages</h3>
-      <p><strong>Macro Precision / Recall / F1:</strong> Averages the metric across all classes, treating each class equally, regardless of class frequency. Best when class sizes are balanced.</p>
-      <p><strong>Micro Precision / Recall / F1:</strong> Aggregates TP, FP, FN across all classes before computing the metric. Gives a global view and is ideal for class-imbalanced problems.</p>
-      <p><strong>Weighted Precision / Recall / F1:</strong> Averages each metric across classes, weighted by the number of true instances per class. Balances importance of classes based on frequency.</p>
-      <h3>4) Average Precision (PR-AUC Variants)</h3>
-      <p><strong>Average Precision Macro:</strong> Precision-Recall AUC averaged across all classes equally. Useful for balanced multi-class problems.</p>
-      <p><strong>Average Precision Micro:</strong> Global Precision-Recall AUC using all instances. Best for imbalanced data or multi-label classification.</p>
-      <p><strong>Average Precision Samples:</strong> Precision-Recall AUC averaged across individual samples (not classes). Ideal for multi-label problems where each sample can belong to multiple classes.</p>
-      <h3>5) ROC-AUC Variants</h3>
-      <p><strong>ROC-AUC:</strong> Measures model's ability to distinguish between classes. AUC = 1 is perfect; 0.5 is random guessing. Use for binary classification.</p>
-      <p><strong>Macro ROC-AUC:</strong> Averages the AUC across all classes equally. Suitable when classes are balanced and of equal importance.</p>
-      <p><strong>Micro ROC-AUC:</strong> Computes AUC from aggregated predictions across all classes. Useful in multiclass or multilabel settings with imbalance.</p>
-      <h3>6) Ranking Metrics</h3>
-      <p><strong>Hits at K:</strong> Measures whether the true label is among the top-K predictions. Common in recommendation systems and retrieval tasks.</p>
-      <h3>7) Confusion Matrix Stats (Per Class)</h3>
-      <p><strong>True Positives / Negatives (TP / TN):</strong> Correct predictions for positives and negatives respectively.</p>
-      <p><strong>False Positives / Negatives (FP / FN):</strong> Incorrect predictions — false alarms and missed detections.</p>
-      <h3>8) Other Useful Metrics</h3>
-      <p><strong>Cohen's Kappa:</strong> Measures agreement between predicted and actual values adjusted for chance. Useful for multiclass classification with imbalanced labels.</p>
-      <p><strong>Matthews Correlation Coefficient (MCC):</strong> Balanced measure of prediction quality that takes into account TP, TN, FP, and FN. Particularly effective for imbalanced datasets.</p>
-      <h3>9) Metric Recommendations</h3>
-      <ul>
-        <li>Use <strong>Accuracy + F1</strong> for balanced data.</li>
-        <li>Use <strong>Precision, Recall, ROC-AUC</strong> for imbalanced datasets.</li>
-        <li>Use <strong>Average Precision Micro</strong> for multilabel or class-imbalanced problems.</li>
-        <li>Use <strong>Macro scores</strong> when all classes should be treated equally.</li>
-        <li>Use <strong>Weighted scores</strong> when class imbalance should be accounted for without ignoring small classes.</li>
-        <li>Use <strong>Confusion Matrix stats</strong> to analyze class-wise performance.</li>
-        <li>Use <strong>Hits at K</strong> for recommendation or ranking-based tasks.</li>
-      </ul>
-    </div>
-  </div>
-</div>
-"""
-    modal_css = """
-<style>
-.modal {
-  display: none;
-  position: fixed;
-  z-index: 1;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  overflow: auto;
-  background-color: rgba(0,0,0,0.4);
-}
-.modal-content {
-  background-color: #fefefe;
-  margin: 15% auto;
-  padding: 20px;
-  border: 1px solid #888;
-  width: 80%;
-  max-width: 800px;
-}
-.close {
-  color: #aaa;
-  float: right;
-  font-size: 28px;
-  font-weight: bold;
-}
-.close:hover,
-.close:focus {
-  color: black;
-  text-decoration: none;
-  cursor: pointer;
-}
-.metrics-guide h3 {
-  margin-top: 20px;
-}
-.metrics-guide p {
-  margin: 5px 0;
-}
-.metrics-guide ul {
-  margin: 10px 0;
-  padding-left: 20px;
-}
-</style>
-"""
-    modal_js = """
-<script>
-document.addEventListener("DOMContentLoaded", function() {
-  var modal = document.getElementById("metricsHelpModal");
-  var closeBtn = document.getElementsByClassName("close")[0];
-
-  document.querySelectorAll(".openMetricsHelp").forEach(btn => {
-    btn.onclick = function() {
-      modal.style.display = "block";
-    };
-  });
-
-  if (closeBtn) {
-    closeBtn.onclick = function() {
-      modal.style.display = "none";
-    };
-  }
-
-  window.onclick = function(event) {
-    if (event.target == modal) {
-      modal.style.display = "none";
-    }
-  }
-});
-</script>
-"""
-    return modal_css + modal_html + modal_js
-
-
 def format_config_table_html(
     config: dict,
     split_info: Optional[str] = None,
     training_progress: dict = None,
 ) -> str:
     display_keys = [
+        "task_type",
         "model_name",
         "epochs",
         "batch_size",
@@ -287,6 +68,8 @@
 
     for key in display_keys:
         val = config.get(key, "N/A")
+        if key == "task_type":
+            val = val.title() if isinstance(val, str) else val
         if key == "batch_size":
             if val is not None:
                 val = int(val)
@@ -348,6 +131,18 @@
             f"</tr>"
         )
 
+    aug_cfg = config.get("augmentation")
+    if aug_cfg:
+        types = [str(a.get("type", "")) for a in aug_cfg]
+        aug_val = ", ".join(types)
+        rows.append(
+            "<tr>"
+            "<td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Augmentation</td>"
+            "<td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>"
+            f"{aug_val}</td>"
+            "</tr>"
+        )
+
     if split_info:
         rows.append(
             f"<tr>"
@@ -371,7 +166,7 @@
         "<p style='text-align: center; font-size: 0.9em;'>"
         "Model trained using Ludwig.<br>"
         "If want to learn more about Ludwig default settings,"
-        "please check the their <a href='https://ludwig.ai' target='_blank'>"
+        "please check their <a href='https://ludwig.ai' target='_blank'>"
         "website(ludwig.ai)</a>."
         "</p><hr>"
     )
@@ -380,6 +175,8 @@
 def detect_output_type(test_stats):
     """Detects if the output type is 'binary' or 'category' based on test statistics."""
     label_stats = test_stats.get("label", {})
+    if "mean_squared_error" in label_stats:
+        return "regression"
     per_class = label_stats.get("per_class_stats", {})
     if len(per_class) == 2:
         return "binary"
@@ -420,6 +217,24 @@
                 "specificity": get_last_value(label_stats, "specificity"),
                 "roc_auc": get_last_value(label_stats, "roc_auc"),
             }
+        elif output_type == "regression":
+            metrics[split] = {
+                "loss": get_last_value(label_stats, "loss"),
+                "mean_absolute_error": get_last_value(
+                    label_stats, "mean_absolute_error"
+                ),
+                "mean_absolute_percentage_error": get_last_value(
+                    label_stats, "mean_absolute_percentage_error"
+                ),
+                "mean_squared_error": get_last_value(label_stats, "mean_squared_error"),
+                "root_mean_squared_error": get_last_value(
+                    label_stats, "root_mean_squared_error"
+                ),
+                "root_mean_squared_percentage_error": get_last_value(
+                    label_stats, "root_mean_squared_percentage_error"
+                ),
+                "r2": get_last_value(label_stats, "r2"),
+            }
         else:
             metrics[split] = {
                 "accuracy": get_last_value(label_stats, "accuracy"),
@@ -565,7 +380,9 @@
     return html
 
 
-def format_test_merged_stats_table_html(test_metrics: Dict[str, Optional[float]]) -> str:
+def format_test_merged_stats_table_html(
+    test_metrics: Dict[str, Optional[float]],
+) -> str:
     """Formats an HTML table for test metrics."""
     rows = []
     for key in sorted(test_metrics.keys()):
@@ -598,63 +415,6 @@
     return html
 
 
-def build_tabbed_html(metrics_html: str, train_val_html: str, test_html: str) -> str:
-    return f"""
-<style>
-.tabs {{
-  display: flex;
-  border-bottom: 2px solid #ccc;
-  margin-bottom: 1rem;
-}}
-.tab {{
-  padding: 10px 20px;
-  cursor: pointer;
-  border: 1px solid #ccc;
-  border-bottom: none;
-  background: #f9f9f9;
-  margin-right: 5px;
-  border-top-left-radius: 8px;
-  border-top-right-radius: 8px;
-}}
-.tab.active {{
-  background: white;
-  font-weight: bold;
-}}
-.tab-content {{
-  display: none;
-  padding: 20px;
-  border: 1px solid #ccc;
-  border-top: none;
-}}
-.tab-content.active {{
-  display: block;
-}}
-</style>
-<div class="tabs">
-  <div class="tab active" onclick="showTab('metrics')"> Config & Results Summary</div>
-  <div class="tab" onclick="showTab('trainval')"> Train/Validation Results</div>
-  <div class="tab" onclick="showTab('test')"> Test Results</div>
-</div>
-<div id="metrics" class="tab-content active">
-  {metrics_html}
-</div>
-<div id="trainval" class="tab-content">
-  {train_val_html}
-</div>
-<div id="test" class="tab-content">
-  {test_html}
-</div>
-<script>
-function showTab(id) {{
-  document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
-  document.querySelectorAll('.tab').forEach(el => el.classList.remove('active'));
-  document.getElementById(id).classList.add('active');
-  document.querySelector(`.tab[onclick*="${{id}}"]`).classList.add('active');
-}}
-</script>
-"""
-
-
 def split_data_0_2(
     df: pd.DataFrame,
     split_column: str,
@@ -727,16 +487,15 @@
     ) -> None:
         ...
 
-    def generate_plots(
-        self,
-        output_dir: Path
-    ) -> None:
+    def generate_plots(self, output_dir: Path) -> None:
         ...
 
     def generate_html_report(
         self,
         title: str,
-        output_dir: str
+        output_dir: str,
+        config: Dict[str, Any],
+        split_info: str,
     ) -> Path:
         ...
 
@@ -749,23 +508,21 @@
         config_params: Dict[str, Any],
         split_config: Dict[str, Any],
     ) -> str:
-        """Build and serialize the Ludwig YAML configuration."""
         logger.info("LudwigDirectBackend: Preparing YAML configuration.")
 
         model_name = config_params.get("model_name", "resnet18")
         use_pretrained = config_params.get("use_pretrained", False)
         fine_tune = config_params.get("fine_tune", False)
+        if use_pretrained:
+            trainable = bool(fine_tune)
+        else:
+            trainable = True
         epochs = config_params.get("epochs", 10)
         batch_size = config_params.get("batch_size")
         num_processes = config_params.get("preprocessing_num_processes", 1)
         early_stop = config_params.get("early_stop", None)
         learning_rate = config_params.get("learning_rate")
         learning_rate = "auto" if learning_rate is None else float(learning_rate)
-        trainable = fine_tune or (not use_pretrained)
-        if not use_pretrained and not trainable:
-            logger.warning("trainable=False; use_pretrained=False is ignored.")
-            logger.warning("Setting trainable=True to train the model from scratch.")
-            trainable = True
         raw_encoder = MODEL_ENCODER_TEMPLATES.get(model_name, model_name)
         if isinstance(raw_encoder, dict):
             encoder_config = {
@@ -779,39 +536,68 @@
         batch_size_cfg = batch_size or "auto"
 
         label_column_path = config_params.get("label_column_data_path")
+        label_series = None
         if label_column_path is not None and Path(label_column_path).exists():
             try:
                 label_series = pd.read_csv(label_column_path)[LABEL_COLUMN_NAME]
-                num_unique_labels = label_series.nunique()
             except Exception as e:
-                logger.warning(
-                    f"Could not determine label cardinality, defaulting to 'binary': {e}"
-                )
-                num_unique_labels = 2
+                logger.warning(f"Could not read label column for task detection: {e}")
+
+        if (
+            label_series is not None
+            and ptypes.is_numeric_dtype(label_series.dtype)
+            and label_series.nunique() > 10
+        ):
+            task_type = "regression"
         else:
-            logger.warning(
-                "label_column_data_path not provided, defaulting to 'binary'"
+            task_type = "classification"
+
+        config_params["task_type"] = task_type
+
+        image_feat: Dict[str, Any] = {
+            "name": IMAGE_PATH_COLUMN_NAME,
+            "type": "image",
+            "encoder": encoder_config,
+        }
+        if config_params.get("augmentation") is not None:
+            image_feat["augmentation"] = config_params["augmentation"]
+
+        if task_type == "regression":
+            output_feat = {
+                "name": LABEL_COLUMN_NAME,
+                "type": "number",
+                "decoder": {"type": "regressor"},
+                "loss": {"type": "mean_squared_error"},
+                "evaluation": {
+                    "metrics": [
+                        "mean_squared_error",
+                        "mean_absolute_error",
+                        "r2",
+                    ]
+                },
+            }
+            val_metric = config_params.get("validation_metric", "mean_squared_error")
+
+        else:
+            num_unique_labels = (
+                label_series.nunique() if label_series is not None else 2
             )
-            num_unique_labels = 2
-
-        output_type = "binary" if num_unique_labels == 2 else "category"
+            output_type = "binary" if num_unique_labels == 2 else "category"
+            output_feat = {"name": LABEL_COLUMN_NAME, "type": output_type}
+            val_metric = None
 
         conf: Dict[str, Any] = {
             "model_type": "ecd",
-            "input_features": [
-                {
-                    "name": IMAGE_PATH_COLUMN_NAME,
-                    "type": "image",
-                    "encoder": encoder_config,
-                }
-            ],
-            "output_features": [{"name": LABEL_COLUMN_NAME, "type": output_type}],
+            "input_features": [image_feat],
+            "output_features": [output_feat],
             "combiner": {"type": "concat"},
             "trainer": {
                 "epochs": epochs,
                 "early_stop": early_stop,
                 "batch_size": batch_size_cfg,
                 "learning_rate": learning_rate,
+                # only set validation_metric for regression
+                **({"validation_metric": val_metric} if val_metric else {}),
             },
             "preprocessing": {
                 "split": split_config,
@@ -876,7 +662,7 @@
             )
             raise
 
-    def get_training_process(self, output_dir) -> float:
+    def get_training_process(self, output_dir) -> Optional[Dict[str, Any]]:
         """Retrieve the learning rate used in the most recent Ludwig run."""
         output_dir = Path(output_dir)
         exp_dirs = sorted(
@@ -1000,11 +786,12 @@
 
         viz_registry = get_visualizations_registry()
         for viz_name, viz_func in viz_registry.items():
-            viz_dir_plot = None
             if viz_name in train_plots:
                 viz_dir_plot = train_viz
             elif viz_name in test_plots:
                 viz_dir_plot = test_viz
+            else:
+                continue
 
             try:
                 viz_func(
@@ -1040,6 +827,7 @@
         report_name = title.lower().replace(" ", "_") + "_report.html"
         report_path = cwd / report_name
         output_dir = Path(output_dir)
+        output_type = None
 
         exp_dirs = sorted(
             output_dir.glob("experiment_run*"),
@@ -1059,7 +847,6 @@
         metrics_html = ""
         train_val_metrics_html = ""
         test_metrics_html = ""
-
         try:
             train_stats_path = exp_dir / "training_statistics.json"
             test_stats_path = exp_dir / TEST_STATISTICS_FILE_NAME
@@ -1069,18 +856,14 @@
                 with open(test_stats_path) as f:
                     test_stats = json.load(f)
                 output_type = detect_output_type(test_stats)
-                all_metrics = extract_metrics_from_json(
-                    train_stats,
-                    test_stats,
-                    output_type,
-                )
                 metrics_html = format_stats_table_html(train_stats, test_stats)
                 train_val_metrics_html = format_train_val_stats_table_html(
-                    train_stats,
-                    test_stats,
+                    train_stats, test_stats
                 )
                 test_metrics_html = format_test_merged_stats_table_html(
-                    all_metrics["test"],
+                    extract_metrics_from_json(train_stats, test_stats, output_type)[
+                        "test"
+                    ]
                 )
         except Exception as e:
             logger.warning(
@@ -1090,11 +873,15 @@
         config_html = ""
         training_progress = self.get_training_process(output_dir)
         try:
-            config_html = format_config_table_html(config, split_info, training_progress)
+            config_html = format_config_table_html(
+                config, split_info, training_progress
+            )
         except Exception as e:
             logger.warning(f"Could not load config for HTML report: {e}")
 
-        def render_img_section(title: str, dir_path: Path, output_type: str = None) -> str:
+        def render_img_section(
+            title: str, dir_path: Path, output_type: str = None
+        ) -> str:
             if not dir_path.exists():
                 return f"<h2>{title}</h2><p><em>Directory not found.</em></p>"
 
@@ -1141,11 +928,7 @@
                     img_names[fname] for fname in display_order if fname in img_names
                 ]
                 remaining = sorted(
-                    [
-                        img
-                        for img in img_names.values()
-                        if img.name not in display_order
-                    ]
+                    [img for img in img_names.values() if img.name not in display_order]
                 )
                 imgs = ordered_imgs + remaining
 
@@ -1173,46 +956,61 @@
             section_html += "</div>"
             return section_html
 
-        button_html = """
-        <button class="help-modal-btn openMetricsHelp">Model Evaluation Metrics — Help Guide</button>
-        <br><br>
-        <style>
-        .help-modal-btn {
-            background-color: #17623b;
-            color: #fff;
-            border: none;
-            border-radius: 24px;
-            padding: 10px 28px;
-            font-size: 1.1rem;
-            font-weight: bold;
-            letter-spacing: 0.03em;
-            cursor: pointer;
-            transition: background 0.2s, box-shadow 0.2s;
-            box-shadow: 0 2px 8px rgba(23,98,59,0.07);
-        }
-        .help-modal-btn:hover, .help-modal-btn:focus {
-            background-color: #21895e;
-            outline: none;
-            box-shadow: 0 4px 16px rgba(23,98,59,0.14);
-        }
-        </style>
-        """
-        tab1_content = button_html + config_html + metrics_html
-        tab2_content = (
-            button_html
-            + train_val_metrics_html
-            + render_img_section("Training & Validation Visualizations", train_viz_dir)
+        tab1_content = config_html + metrics_html
+
+        tab2_content = train_val_metrics_html + render_img_section(
+            "Training & Validation Visualizations", train_viz_dir
         )
+
+        # --- Predictions vs Ground Truth table ---
+        preds_section = ""
+        parquet_path = exp_dir / PREDICTIONS_PARQUET_FILE_NAME
+        if parquet_path.exists():
+            try:
+                # 1) load predictions from Parquet
+                df_preds = pd.read_parquet(parquet_path).reset_index(drop=True)
+                # assume the column containing your model's prediction is named "prediction"
+                # or contains that substring:
+                pred_col = next(
+                    (c for c in df_preds.columns if "prediction" in c.lower()),
+                    None,
+                )
+                if pred_col is None:
+                    raise ValueError("No prediction column found in Parquet output")
+                df_pred = df_preds[[pred_col]].rename(columns={pred_col: "prediction"})
+
+                # 2) load ground truth for the test split from prepared CSV
+                df_all = pd.read_csv(config["label_column_data_path"])
+                df_gt = df_all[df_all[SPLIT_COLUMN_NAME] == 2][
+                    LABEL_COLUMN_NAME
+                ].reset_index(drop=True)
+
+                # 3) concatenate side‐by‐side
+                df_table = pd.concat([df_gt, df_pred], axis=1)
+                df_table.columns = [LABEL_COLUMN_NAME, "prediction"]
+
+                # 4) render as HTML
+                preds_html = df_table.to_html(index=False, classes="predictions-table")
+                preds_section = (
+                    "<h2 style='text-align: center;'>Predictions vs. Ground Truth</h2>"
+                    "<div style='overflow-x:auto; margin-bottom:20px;'>"
+                    + preds_html
+                    + "</div>"
+                )
+            except Exception as e:
+                logger.warning(f"Could not build Predictions vs GT table: {e}")
+        # Test tab = Metrics + Preds table + Visualizations
+
         tab3_content = (
-            button_html
-            + test_metrics_html
+            test_metrics_html
+            + preds_section
             + render_img_section("Test Visualizations", test_viz_dir, output_type)
         )
 
+        # assemble the tabs and help modal
         tabbed_html = build_tabbed_html(tab1_content, tab2_content, tab3_content)
         modal_html = get_metrics_help_modal()
-        html += tabbed_html + modal_html
-        html += get_html_closing()
+        html += tabbed_html + modal_html + get_html_closing()
 
         try:
             with open(report_path, "w") as f:
@@ -1263,7 +1061,7 @@
             logger.error("Error extracting zip file", exc_info=True)
             raise
 
-    def _prepare_data(self) -> Tuple[Path, Dict[str, Any]]:
+    def _prepare_data(self) -> Tuple[Path, Dict[str, Any], str]:
         """Load CSV, update image paths, handle splits, and write prepared CSV."""
         if not self.temp_dir or not self.image_extract_dir:
             raise RuntimeError("Temp dirs not initialized before data prep.")
@@ -1302,8 +1100,9 @@
                 f"for train/val/test."
             )
 
-        final_csv = TEMP_CSV_FILENAME
+        final_csv = self.temp_dir / TEMP_CSV_FILENAME
         try:
+
             df.to_csv(final_csv, index=False)
             logger.info(f"Saved prepared data to {final_csv}")
         except Exception:
@@ -1312,7 +1111,9 @@
 
         return final_csv, split_config, split_info
 
-    def _process_fixed_split(self, df: pd.DataFrame) -> Dict[str, Any]:
+    def _process_fixed_split(
+        self, df: pd.DataFrame
+    ) -> Tuple[pd.DataFrame, Dict[str, Any], str]:
         """Process a fixed split column (0=train,1=val,2=test)."""
         logger.info(f"Fixed split column '{SPLIT_COLUMN_NAME}' detected.")
         try:
@@ -1384,6 +1185,7 @@
                 "random_seed": self.args.random_seed,
                 "early_stop": self.args.early_stop,
                 "label_column_data_path": csv_path,
+                "augmentation": self.args.augmentation,
             }
             yaml_str = self.backend.prepare_config(backend_args, split_cfg)
 
@@ -1422,6 +1224,29 @@
         return None
 
 
+def aug_parse(aug_string: str):
+    """
+    Parse comma-separated augmentation keys into Ludwig augmentation dicts.
+    Raises ValueError on unknown key.
+    """
+    mapping = {
+        "random_horizontal_flip": {"type": "random_horizontal_flip"},
+        "random_vertical_flip": {"type": "random_vertical_flip"},
+        "random_rotate": {"type": "random_rotate", "degree": 10},
+        "random_blur": {"type": "random_blur", "kernel_size": 3},
+        "random_brightness": {"type": "random_brightness", "min": 0.5, "max": 2.0},
+        "random_contrast": {"type": "random_contrast", "min": 0.5, "max": 2.0},
+    }
+    aug_list = []
+    for tok in aug_string.split(","):
+        key = tok.strip()
+        if key not in mapping:
+            valid = ", ".join(mapping.keys())
+            raise ValueError(f"Unknown augmentation '{key}'. Valid choices: {valid}")
+        aug_list.append(mapping[key])
+    return aug_list
+
+
 class SplitProbAction(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
         train, val, test = values
@@ -1508,7 +1333,10 @@
         metavar=("train", "val", "test"),
         action=SplitProbAction,
         default=[0.7, 0.1, 0.2],
-        help="Random split proportions (e.g., 0.7 0.1 0.2). Only used if no split column.",
+        help=(
+            "Random split proportions (e.g., 0.7 0.1 0.2)."
+            "Only used if no split column."
+        ),
     )
     parser.add_argument(
         "--random-seed",
@@ -1522,6 +1350,17 @@
         default=None,
         help="Learning rate. If not provided, Ludwig will auto-select it.",
     )
+    parser.add_argument(
+        "--augmentation",
+        type=str,
+        default=None,
+        help=(
+            "Comma-separated list (in order) of any of: "
+            "random_horizontal_flip, random_vertical_flip, random_rotate, "
+            "random_blur, random_brightness, random_contrast. "
+            "E.g. --augmentation random_horizontal_flip,random_rotate"
+        ),
+    )
 
     args = parser.parse_args()
 
@@ -1531,6 +1370,12 @@
         parser.error(f"CSV not found: {args.csv_file}")
     if not args.image_zip.is_file():
         parser.error(f"ZIP not found: {args.image_zip}")
+    if args.augmentation is not None:
+        try:
+            augmentation_setup = aug_parse(args.augmentation)
+            setattr(args, "augmentation", augmentation_setup)
+        except ValueError as e:
+            parser.error(str(e))
 
     backend_instance = LudwigDirectBackend()
     orchestrator = WorkflowOrchestrator(args, backend_instance)
Binary file test-data/age_regression.zip has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/expected_regression.html	Thu Jul 03 20:43:24 2025 +0000
@@ -0,0 +1,276 @@
+
+    <html>
+    <head>
+        <meta charset="UTF-8">
+        <title>Galaxy-Ludwig Report</title>
+        <style>
+          body {
+              font-family: Arial, sans-serif;
+              margin: 0;
+              padding: 20px;
+              background-color: #f4f4f4;
+          }
+          .container {
+              max-width: 800px;
+              margin: auto;
+              background: white;
+              padding: 20px;
+              box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+              overflow-x: auto;
+          }
+          h1 {
+              text-align: center;
+              color: #333;
+          }
+          h2 {
+              border-bottom: 2px solid #4CAF50;
+              color: #4CAF50;
+              padding-bottom: 5px;
+          }
+          table {
+              border-collapse: collapse;
+              margin: 20px 0;
+              width: 100%;
+              table-layout: fixed; /* Enforces consistent column widths */
+          }
+          table, th, td {
+              border: 1px solid #ddd;
+          }
+          th, td {
+              padding: 8px;
+              text-align: center; /* Center-align text */
+              vertical-align: middle; /* Center-align content vertically */
+              word-wrap: break-word; /* Break long words to avoid overflow */
+          }
+          th:first-child, td:first-child {
+              width: 5%; /* Smaller width for the first column */
+          }
+          th:nth-child(2), td:nth-child(2) {
+              width: 50%; /* Wider for the metric/description column */
+          }
+          th:last-child, td:last-child {
+              width: 25%; /* Value column gets remaining space */
+          }
+          th {
+              background-color: #4CAF50;
+              color: white;
+          }
+          .plot {
+              text-align: center;
+              margin: 20px 0;
+          }
+          .plot img {
+              max-width: 100%;
+              height: auto;
+          }
+        </style>
+    </head>
+    <body>
+    <div class="container">
+    <h1>Image Classification Results</h1>
+<style>
+  .tabs {
+    display: flex;
+    align-items: center;
+    border-bottom: 2px solid #ccc;
+    margin-bottom: 1rem;
+  }
+  .tab {
+    padding: 10px 20px;
+    cursor: pointer;
+    border: 1px solid #ccc;
+    border-bottom: none;
+    background: #f9f9f9;
+    margin-right: 5px;
+    border-top-left-radius: 8px;
+    border-top-right-radius: 8px;
+  }
+  .tab.active {
+    background: white;
+    font-weight: bold;
+  }
+  /* new help-button styling */
+  .help-btn {
+    margin-left: auto;
+    padding: 6px 12px;
+    font-size: 0.9rem;
+    border: 1px solid #4CAF50;
+    border-radius: 4px;
+    background: #4CAF50;
+    color: white;
+    cursor: pointer;
+  }
+  .tab-content {
+    display: none;
+    padding: 20px;
+    border: 1px solid #ccc;
+    border-top: none;
+  }
+  .tab-content.active {
+    display: block;
+  }
+</style>
+
+<div class="tabs">
+  <div class="tab active" onclick="showTab('metrics')">Config &amp; Results Summary</div>
+  <div class="tab" onclick="showTab('trainval')">Train/Validation Results</div>
+  <div class="tab" onclick="showTab('test')">Test Results</div>
+  <!-- always-visible help button -->
+  <button id="openMetricsHelp" class="help-btn">Help</button>
+</div>
+
+<div id="metrics" class="tab-content active">
+  <h2 style='text-align: center;'>Training Setup</h2><div style='display: flex; justify-content: center;'><table style='border-collapse: collapse; width: 60%; table-layout: auto;'><thead><tr><th style='padding: 10px; border: 1px solid #ccc; text-align: left;'>Parameter</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center;'>Value</th></tr></thead><tbody><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Task Type</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>Regression</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Model Name</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>resnet18</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Epochs</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>10</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Batch Size</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>Auto-selected batch size by Ludwig:<br><span style='font-size: 0.85em;'>1</span><br></td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Fine Tune</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>True</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Use Pretrained</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>True</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Learning Rate</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>Auto-selected learning rate by Ludwig:<br><span style='font-size: 0.85em;'>1e-05</span><br><span style='font-size: 0.85em;'>Based on model architecture and training setup (e.g., fine-tuning).<br>See <a href='https://ludwig.ai/latest/configuration/trainer/#trainer-parameters' target='_blank'>Ludwig Trainer Parameters</a> for details.</span></td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Random Seed</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>42</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Early Stop</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>5</td></tr><tr><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: left;'>Data Split</td><td style='padding: 6px 12px; border: 1px solid #ccc; text-align: center;'>Used user-defined split column from CSV.</td></tr></tbody></table></div><br><p style='text-align: center; font-size: 0.9em;'>Model trained using Ludwig.<br>If want to learn more about Ludwig default settings,please check their <a href='https://ludwig.ai' target='_blank'>website(ludwig.ai)</a>.</p><hr><h2 style='text-align: center;'>Model Performance Summary</h2><div style='display: flex; justify-content: center;'><table style='border-collapse: collapse; table-layout: auto;'><thead><tr><th style='padding: 10px; border: 1px solid #ccc; text-align: left; white-space: nowrap;'>Metric</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Train</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Validation</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Test</th></tr></thead><tbody><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Loss</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>420.7510</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>2060.3052</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>8205.5977</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Absolute Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>17.3023</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>45.1572</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>86.0225</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Absolute % Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.6416</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9613</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9580</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Squared Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>420.7510</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>2060.3052</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>8205.5977</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>R² Score</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>-2.1257</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>-81.4122</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>-10.2560</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Root Mean Squared Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>20.5122</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>45.3906</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>90.5848</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Root Mean Squared % Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.6416</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9613</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9580</td></tr></tbody></table></div><br>
+</div>
+<div id="trainval" class="tab-content">
+  <h2 style='text-align: center;'>Train/Validation Performance Summary</h2><div style='display: flex; justify-content: center;'><table style='border-collapse: collapse; table-layout: auto;'><thead><tr><th style='padding: 10px; border: 1px solid #ccc; text-align: left; white-space: nowrap;'>Metric</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Train</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Validation</th></tr></thead><tbody><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Loss</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>420.7510</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>2060.3052</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Absolute Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>17.3023</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>45.1572</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Absolute % Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.6416</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9613</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Squared Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>420.7510</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>2060.3052</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>R² Score</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>-2.1257</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>-81.4122</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Root Mean Squared Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>20.5122</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>45.3906</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Root Mean Squared % Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.6416</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9613</td></tr></tbody></table></div><br><h2 style='text-align: center;'>Training & Validation Visualizations</h2><div><div class="plot" style="margin-bottom:20px;text-align:center;"><h3>Learning Curves Label Loss</h3><img src="data:image/png;base64,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AA8PDwDAmTNnoNPp0KVLF7GMv78/fH19xQAYHx+P5s2bw9s7/+nbYWFhmD17NhITE9GyZUvEx8eLAbJgmQULFlSofoIgQGaD7/izdYIgwGg0QhAEa1eFKohtZ5/YbvaJ7WafaqLdqrpvmw6AgiBgwYIFaNeuHZo3bw4ASEtLg0qlgru7+VPCa9eujdTUVLFMwfAHQJwvq0xGRgays7Ph6OhYrjomJSUxAFZSdnY2kpKSrF0NqgS2nX1iu9kntpt9qu52MxqNVdrepgPgnDlzcPHiRaxfv97aVSmRv78/FAqFtathdwRBQGJiIvz9/SG35AvOqdqx7ewT280+sd3sU020m8FgwKlTpyq9vc0GwLlz5+LAgQP48ssvUa9e/nv0vL29odPpkJ6ebtYLeOvWLfj4+IhlCn8peXcJFyxT+M7htLQ0uLq6lrv3DwDkcjn/UVaSTCbj92en2Hb2ie1mn9hu9qm6262qPYA299tkNBoxd+5c7N27F1988QUaNmxotr5169ZQqVQ4cuSIuOzSpUtISUlBcHAwACA4OBgXLlzArVu3xDKHDx+Gq6srAgICxDJHjx412/fhw4fFfRARERE9qGwuAM6ZMwc7duzAu+++CxcXF6SmpiI1NRXZ2dkAADc3N/Tt2xcLFy7E0aNHcebMGUybNg0hISFieAsLC0NAQACmTJmCc+fO4ZdffsHSpUsxaNAgqNVqAMCAAQNw/fp1LF68GElJSVi3bh12796NoUOHWunMiYiIiGqGzQ0Bb9iwAQAwePBgs+UxMTGIjo4GAEybNg1yuRzjxo2DVqtFWFgYZs2aJZZVKBRYsWIFZs+ejf79+8PJyQlRUVEYN26cWKZhw4aIjY1FTEwM1qxZg3r16mH+/Pl8BAwRERE98GwuAJ4/f77MMg4ODpg1a5ZZ6CusQYMGWLlyZan76dSpE7Zv317RKhIRERHZNZsbAiYiIiKi6sUASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEmNzAfDEiRMYNWoUwsLCoNFosG/fPrP1Go2m2Omzzz4Ty0RERBRZ/+mnn5rt59y5cxg4cCCCgoIQHh6OlStX1sj5EREREVmb0toVKCwrKwsajQZ9+/bF2LFji6w/dOiQ2fzBgwcxffp0PPnkk2bLx40bh379+onzLi4u4ueMjAwMHz4coaGhmDNnDi5cuIBp06bB3d0d/fv3t/AZEREREdkWmwuA4eHhCA8PL3G9j4+P2fyPP/6ITp06oWHDhmbLXVxcipTNs2PHDuh0OixYsABqtRrNmjVDQkIC4uLiGACJiIjogWdzAbAi0tLS8PPPP2PhwoVF1q1cuRKffPIJ6tevj969e2Po0KFQKk2nGx8fjw4dOkCtVovlw8LCsHLlSty9exceHh7lroMgCJDJZFU/GYkRBAFGoxGCIFi7KlRBbDv7xHazT2w3+1QT7VbVfdt1ANy2bRtcXFzwxBNPmC0fPHgwWrZsCQ8PD5w8eRLvvfceUlNT8eabbwIwBUc/Pz+zbby9vcV1FQmASUlJDICVlJ2djaSkJGtXgyqBbWef2G72ie1mn6q73YxGY5W2t+sA+PXXX6NPnz5wcHAwW/7SSy+JnwMDA6FSqTBr1ixMnDjRrNfPEvz9/aFQKCy6TykQBAGJiYnw9/eHXG5z9yJRKdh29ontZp/YbvapJtrNYDDg1KlTld7ebgPgb7/9hsuXL2Pp0qVllm3bti30ej2Sk5PRtGlTeHt7Iy0tzaxM3nxeT2B5yeVy/qOsJJlMxu/PTrHt7BPbzT6x3exTdbdbVXsA7fa3acuWLWjVqhUCAwPLLJuQkAC5XI7atWsDAIKDg/Hbb79Bp9OJZQ4fPowmTZpUaPiXiIiIyB7ZXADMzMxEQkICEhISAADJyclISEhASkqKWCYjIwPff/89nnvuuSLbnzx5EqtXr8a5c+dw/fp17NixAzExMXj66afFcNenTx+oVCpMnz4dFy9exK5du7BmzRqzoWMiIiKiB5XNDQGfOXMGQ4YMEedjYmIAAFFRUeLdvt999x2MRiN69+5dZHu1Wo1du3Zh+fLl0Gq18PPzw9ChQ83CnZubG1atWoW5c+ciOjoatWrVwpgxY/gIGCIiIpIEmwuAnTp1wvnz50st079//xLDWqtWrbB58+YyjxMYGIj169dXqo5ERERE9szmhoCJiIiIqHoxABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcQwABIRERFJDAMgERERkcTYXAA8ceIERo0ahbCwMGg0Guzbt89s/dSpU6HRaMym4cOHm5W5c+cOJk6ciHbt2qFDhw6YNm0aMjMzzcqcO3cOAwcORFBQEMLDw7Fy5cpqPzciIiIiW6C0dgUKy8rKgkajQd++fTF27Nhiy3Tt2hUxMTHivFqtNls/adIkpKamIi4uDjqdDtOmTcPMmTPx7rvvAgAyMjIwfPhwhIaGYs6cObhw4QKmTZsGd3d39O/fv/pOjoiIiMgG2FwADA8PR3h4eKll1Go1fHx8il2XlJSEX375BVu2bEFQUBAAYMaMGRgxYgSmTJmCunXrYseOHdDpdFiwYAHUajWaNWuGhIQExMXFMQASERHRA8/mAmB5HD9+HKGhoXB3d0fnzp0xfvx41KpVCwBw8uRJuLu7i+EPALp06QK5XI5Tp06hR48eiI+PR4cOHcx6DsPCwrBy5UrcvXsXHh4e5a6LIAiQyWSWOzmJEAQBRqMRgiBYuypUQWw7+8R2s09sN/tUE+1W1X3bXQDs2rUrevToAT8/P1y/fh3vvfceXn75ZWzatAkKhQJpaWnw8vIy20apVMLDwwOpqakAgLS0NPj5+ZmV8fb2FtdVJAAmJSUxAFZSdnY2kpKSrF0NqgS2nX1iu9kntpt9qu52MxqNVdre7gJgZGSk+DnvJpDu3buLvYI1zd/fHwqFosaPa+8EQUBiYiL8/f0hl9vcvUhUCradfWK7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4w0MGDAAzs7OCAsLg4ODbQft4lisB9DZ2Rl37tyBr68vfv31VwwdOhQA4ODggJycHEsdhoiIiB4QTZo0waZNm8yWRUdHFynn5+eHNWvWmC0bNGiQ2XzhO4LPnz9fZD8FO6Q6depkViY6OrrIsbt3725WRqlU4q233sJbb70FABAEAT179kTPnj2LPT9bZrEA2KVLF8yYMQMtWrTAlStXEB4eDgC4ePEir/8jIiIiu3fjxg38+uuv6NixI7RaLdatW4cbN26gT58+1q5ahVlsCHjWrFkIDg7G7du38eGHH6JWrVoAgLNnzyIyMtJShyEiIiKyCrlcjq1bt+LZZ5/F888/jwsXLiAuLg7+/v7WrlqFWawH0N3dHTNnziyyPO/p3kRERET2rH79+ti4caO1q2ERFusBPHjwoNnY+rp16/B///d/mDhxIu7evWupwxARERFRFVksAL7zzjvIzMwEYLrwcuHChQgPD0dycjIWLlxoqcMQERERURVZbAg4OTlZHAP/4Ycf0K1bN0yYMAFnz57FiBEjLHUYIiIiIqoii/UAqlQqZGdnAwAOHz6MRx55BADg4eGBjIwMSx2GiIiIiKrIYj2A7dq1Q0xMDNq1a4fTp09j6dKlAIArV66gXr16ljoMEREREVWRxXoAZ86cCaVSiT179mDWrFmoW7cuANPNIV27drXUYYiIiIioiiwWAH19fREbG4sdO3bgueeeE5dPmzYNM2bMsNRhiIiIiAAAERERWL16tTiv0Wiwb9++EssnJydDo9EgISGhSse11H6syWJDwABgMBiwb98+JCUlAQCaNWuGiIgIKBQKSx6GiIiIqIhDhw7Bw8PDovucOnUq0tPT8fHHH4vL6tevj0OHDokvvbBHFguAV69exYgRI/Dvv/+iSZMmAIBPP/0U9erVw6effopGjRpZ6lBERERERfj4+NTIcRQKRY0dq7pYbAh4/vz5aNiwIQ4cOIBt27Zh27Zt+Omnn+Dn54f58+db6jBERERUHoIByEyr2UkwlLt6mzZtQlhYGARBMFs+evRovPnmm7h27RpGjx6NLl26ICQkBH379sXhw4dL3WfhIeBTp07hmWeeQVBQEKKjo4sM2RoMBkybNg0RERFo06YNnnzySXzxxRfi+mXLlmHbtm348ccfodFooNFocOzYsWKHgI8fP45nn30WrVu3RteuXbF0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q9Xy/0c2xGg0Iicnp0r70Gq10Ov1uHr1apE/AKraf2e3AVCn0+G1116D0WjEnDlzzNa99NJL4ufAwECoVCrMmjULEydOhFqttmg9/P392QNYCXl/1fr7+7M3ws6w7ewT280+lafd8noA1Wq12SNPyLqys7Or3B5GoxFKpRKNGzcusQewsuwyAOp0OowfPx4pKSn44osvzHr/itO2bVvo9XokJyejadOm8Pb2RlpamlmZvPm8nsDyksvl/I9pJclkMn5/doptZ5/YbvaprHaTy+WQyWTiRNZX8G7gqrRJXpsW1/5V7QG0u/8K5IW/q1evYvXq1ahVq1aZ2yQkJEAul6N27doATA9n/O2338ye83P48GE0adKkQsO/RERERPbI5gJgZmYmEhISxBcsJycnIyEhASkpKdDpdBg3bhzOnDmDJUuWwGAwIDU1FampqeJTxE+ePInVq1fj3LlzuH79Onbs2IGYmBg8/fTTYrjr06cPVCoVpk+fjosXL2LXrl1Ys2aN2dAxERER0YPK5oaAz5w5gyFDhojzec8ajIqKwtixY7F//34AwP/93/+ZbbdmzRp06tQJarUau3btwvLly6HVauHn54ehQ4eahTs3NzesWrUKc+fORXR0NGrVqoUxY8bwETBERGS3bPihHlRJ1dmmNhcAO3XqhPPnz5e4vrR1ANCqVSts3ry5zOMEBgZi/fr1Fa4fERGRLVGpVABML1JwcnKycm3IkrKysgDkt7El2VwAJCIiovJTKBTw9PTEzZs3AQDOzs68GcTKjEYjtFqt2c0gFd0+KysLN2/ehKenZ7U8bYQBkIiIyM7lvW82LwSSdRmNRuj1eiiVyiqFcU9Pz2p7lzADIBERkZ2TyWSoX78+6tSpY/aEC7IOQRBw9epVNG7cuNKPXVKpVNX6nGEGQCIiogeEQqHgywlsgCAIkMvlcHR0tNnnbtpmrYiIiIio2jAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyARERGRxDAAEhEREUkMAyAR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Hx8MHToU165dQ6NGjSx6fH9/fygUCovuUwoEQUBiYiL8/f0hl/NmdHvCtrNPbDf7xHazTzXRbgaDAadOnar09nYdAG/cuIHDhw9j2bJlpZZr27YtAODq1ato1KgRvL29i3xpaWlpAFDidYMlkcvl/EdZSTKZjN+fnWLb2Se2m31iu9mn6m63qvYA2vVv09atW1G7dm089thjpZZLSEgAkB/ugoODceHCBdy6dUssc/jwYbi6uiIgIKDa6ktERERkC+y2B1AQBGzduhXPPPOM2bP7rl27hp07dyI8PByenp44f/48YmJi0LFjRwQGBgIw3fAREBCAKVOmYPLkyUhNTcXSpUsxaNAg3gFMREREDzy7DYCHDx9GSkoK+vbta7ZcpVLhyJEjWLNmDbKyslC/fn088cQTGDNmjFhGoVBgxYoVmD17Nvr37w8nJydERUWZPTeQiIiI6EFltwEwLCwM58+fL7K8fv36+PLLL8vcvkGDBli5cmV1VI2IiIjIptn1NYBEREREVHEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDEMgEREREQSwwBIREREJDF2FwCXLVsGjUZjNj311FPi+pycHMyZMwedOnVCSEgIXn31VaSlpZntIyUlBSNGjEDbtm0RGhqKRYsWQa/X1/SpEBEREVmF0toVqIxmzZohLi5OnFcoFOLnBQsW4Oeff8bSpUvh5uaGefPmYezYsdi4cSMAwGAwYOTIkfD29sbGjRtx8+ZNvPHGG1CpVJgwYUKNn0tp/svUIuHvdDioFHB1UMLFIe+nEiqF3WV3IiIishF2GQAVCgV8fHyKLL937x6+/vprLFmyBKGhoQBMgbBXr16Ij49HcHAwDh06hMTERMTFxcHb2xstWrTAa6+9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tqxp06bYs2ePlWpE5bV48WKMGDFCvE5Mo9EgJSUFsbGxDIB2wsfHBwBw69Yt1KlTR1x+69YtBAYGWqtaIgZAqlFGoxHz5s3D3r17sXbtWl6Qbic6d+6MnTt3mi1788030bRpU7z88ssMfzaqXbt24jVkea5cuYIGDRpYqUZUXtnZ2ZDJZGbLFAoFHwNjR/z8/ODj44MjR46gRYsWAICMjAz8+eefeP75561cOwZAqmFz5szBt99+i48//hguLi7iNRJubm5wdHS0cu2oJK6urkWu03R2doanpyev37RhL774Ip5//nmsWLECPXv2xKlTp7B582bMnTvX2lWjMnTr1g0rVqyAr6+vOAQcFxeHvn37WrtqVEBmZiauXbsmzicnJyMhIQEeHh7w9fXFkCFD8Mknn6Bx48bw8/PDBx98gDp16oh3BVuTzMg/J6gGlfTsuJiYGLPhRbJ9gwcPRmBgIKZPn27tqlApfvrpJ7z33nu4cuUK/Pz88NJLL6Ffv37WrhaVISMjAx988AH27dsnDiFGRkbilVdegVqttnb1KNexY8cwZMiQIsujoqKwcOFCGI1GfPjhh9i8eTPS09PRvn17zJo1C02aNLFCbc0xABIRERFJDJ8DSERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERERCQxDIBEREREEsMASERkR44dOwaNRoP09HRrV4WI7BgDIBEREZHEMAASERERSQwDIBFRBQiCgNjYWERERKBNmzZ4+umn8f333wPIH549cOAA+vTpg6CgIPTr1w8XLlww28eePXsQGRmJ1q1bIyIiAp9//rnZeq1Wi3feeQfh4eFo3bo1evToga+++sqszNmzZxEdHY22bdtiwIABuHTpUvWeOBE9UJTWrgARkT2JjY3Fjh07MGfOHDz00EM4ceIEJk+eDC8vL7HM4sWLMX36dHh7e+P999/HqFGjsGfPHqhUKpw5cwbjx4/H2LFj0atXL5w8eRJz5syBp6cnoqOjAQBTpkxBfHw8ZsyYgcDAQCQnJ+O///4zq8f777+PqVOnwsvLC7NmzcK0adOwcePGGv0uiMh+MQASEZWTVqtFbGws4uLiEBISAgBo2LAhfv/9d2zatAn9+vUDAIwdOxaPPPIIAGDhwoUIDw/H3r170atXL8TFxSE0NBSvvPIKAKBJkyZITEzEqlWrEB0djcuXL2P37t2Ii4tDly5dxGMU9vrrr+Phhx8GAIwYMQIjRoxATk4OHBwcqv17ICL7xwBIRFROV69exf379zFs2DCz5TqdDi1atBDng4ODxc+enp5o0qSJOER76dIlPP7442bbt2vXDmvWrIHBYEBCQgIUCgU6duxYal00Go342cfHBwBw69Yt+Pr6VurciEhaGACJiMopKysLgGkYuG7dumbr1Go1rl27VuVjODo6lqucUpn/n2+ZTAbAdH0iEVF58CYQIqJy8vf3h1qtRkpKCho3bmw21a9fXywXHx8vfr579y6uXLmCpk2bAgCaNm2KP/74w2y/f/zxBx566CEoFAo0b94cgiDgxIkTNXJORCRN7AEkIionV1dXDBs2DDExMTAajWjfvj3u3buHP/74A66uruLw68cff4xatWqhdu3aeP/991GrVi10794dADBs2DA8++yz+Oijj9CrVy/Ex8dj3bp1mDVrFgDAz88PUVFRmDZtGmbMmAGNRoOUlBTcunULvXr1stq5E9GDhQGQiKgCxo8fDy8vL8TGxiI5ORlubm5o2bIlRo0aJQ7BTpw4EW+//TauXLmCFi1a4JNPPoFarQYAtGrVCkuXLsWHH36ITz75BD4+Phg3bpx4BzAAzJ49G++99x5mz56NO3fuwNfXFyNHjrTK+RLRg0lmNBqN1q4EEdGD4NixYxgyZAhOnDgBd3d3a1eHiKhEvAaQiIiISGIYAImIiIgkhkPARERERBLDHkAiIiIiiWEAJCIiIpIYBkAiIiIiiWEAJCIiIpIYBkAiIiIiiWEAJCIiIpIYBkAiIiIiiWEAJCIiIpIYBkAiIiIiiWEAJCIiIpIYBkAiIiIiiWEAJCIiIpIYBkAiIiIiiWEAJCIiIpKY/weDiEy1D9PXSQAAAABJRU5ErkJggg==" style="max-width:90%;max-height:600px;border:1px solid #ddd;" /></div></div>
+</div>
+<div id="test" class="tab-content">
+  <h2 style='text-align: center;'>Test Performance Summary</h2><div style='display: flex; justify-content: center;'><table style='border-collapse: collapse; table-layout: auto;'><thead><tr><th style='padding: 10px; border: 1px solid #ccc; text-align: left; white-space: nowrap;'>Metric</th><th style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Test</th></tr></thead><tbody><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Loss</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>8205.5977</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Absolute Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>86.0225</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Absolute % Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9580</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Mean Squared Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>8205.5977</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>R² Score</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>-10.2560</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Root Mean Squared Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>90.5848</td></tr><tr><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>Root Mean Squared % Error</td><td style='padding: 10px; border: 1px solid #ccc; text-align: center; white-space: nowrap;'>0.9580</td></tr></tbody></table></div><br><h2 style='text-align: center;'>Predictions vs. Ground Truth</h2><div style='overflow-x:auto; margin-bottom:20px;'><table border="1" class="dataframe predictions-table">
+  <thead>
+    <tr style="text-align: right;">
+      <th>label</th>
+      <th>prediction</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>62</td>
+      <td>4.362794</td>
+    </tr>
+    <tr>
+      <td>116</td>
+      <td>1.592189</td>
+    </tr>
+  </tbody>
+</table></div><h2 style='text-align: center;'>Test Visualizations</h2><div><div class="plot" style="margin-bottom:20px;text-align:center;"><h3>Compare Performance Label</h3><img src="data:image/png;base64,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" style="max-width:90%;max-height:600px;border:1px solid #ddd;" /></div></div>
+</div>
+
+<script>
+function showTab(id) {
+  document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
+  document.querySelectorAll('.tab').forEach(el => el.classList.remove('active'));
+  document.getElementById(id).classList.add('active');
+  document.querySelector(`.tab[onclick*="${id}"]`).classList.add('active');
+}
+</script>
+
+<style>
+.modal {
+  display: none;
+  position: fixed;
+  z-index: 1;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+  background-color: rgba(0,0,0,0.4);
+}
+.modal-content {
+  background-color: #fefefe;
+  margin: 15% auto;
+  padding: 20px;
+  border: 1px solid #888;
+  width: 80%;
+  max-width: 800px;
+}
+.close {
+  color: #aaa;
+  float: right;
+  font-size: 28px;
+  font-weight: bold;
+}
+.close:hover,
+.close:focus {
+  color: black;
+  text-decoration: none;
+  cursor: pointer;
+}
+.metrics-guide h3 {
+  margin-top: 20px;
+}
+.metrics-guide p {
+  margin: 5px 0;
+}
+.metrics-guide ul {
+  margin: 10px 0;
+  padding-left: 20px;
+}
+</style>
+
+<div id="metricsHelpModal" class="modal">
+  <div class="modal-content">
+    <span class="close">×</span>
+    <h2>Model Evaluation Metrics — Help Guide</h2>
+    <div class="metrics-guide">
+      <h3>1) General Metrics</h3>
+      <p><strong>Loss:</strong> Measures the difference between predicted and actual values. Lower is better. Often used for optimization during training.</p>
+      <p><strong>Accuracy:</strong> Proportion of correct predictions among all predictions. Simple but can be misleading for imbalanced datasets.</p>
+      <p><strong>Micro Accuracy:</strong> Calculates accuracy by summing up all individual true positives and true negatives across all classes, making it suitable for multiclass or multilabel problems.</p>
+      <p><strong>Token Accuracy:</strong> Measures how often the predicted tokens (e.g., in sequences) match the true tokens. Useful in sequence prediction tasks like NLP.</p>
+      <h3>2) Precision, Recall & Specificity</h3>
+      <p><strong>Precision:</strong> Out of all positive predictions, how many were correct. Precision = TP / (TP + FP). Helps when false positives are costly.</p>
+      <p><strong>Recall (Sensitivity):</strong> Out of all actual positives, how many were predicted correctly. Recall = TP / (TP + FN). Important when missing positives is risky.</p>
+      <p><strong>Specificity:</strong> True negative rate. Measures how well the model identifies negatives. Specificity = TN / (TN + FP). Useful in medical testing to avoid false alarms.</p>
+      <h3>3) Macro, Micro, and Weighted Averages</h3>
+      <p><strong>Macro Precision / Recall / F1:</strong> Averages the metric across all classes, treating each class equally, regardless of class frequency. Best when class sizes are balanced.</p>
+      <p><strong>Micro Precision / Recall / F1:</strong> Aggregates TP, FP, FN across all classes before computing the metric. Gives a global view and is ideal for class-imbalanced problems.</p>
+      <p><strong>Weighted Precision / Recall / F1:</strong> Averages each metric across classes, weighted by the number of true instances per class. Balances importance of classes based on frequency.</p>
+      <h3>4) Average Precision (PR-AUC Variants)</h3>
+      <p><strong>Average Precision Macro:</strong> Precision-Recall AUC averaged across all classes equally. Useful for balanced multi-class problems.</p>
+      <p><strong>Average Precision Micro:</strong> Global Precision-Recall AUC using all instances. Best for imbalanced data or multi-label classification.</p>
+      <p><strong>Average Precision Samples:</strong> Precision-Recall AUC averaged across individual samples (not classes). Ideal for multi-label problems where each sample can belong to multiple classes.</p>
+      <h3>5) ROC-AUC Variants</h3>
+      <p><strong>ROC-AUC:</strong> Measures model's ability to distinguish between classes. AUC = 1 is perfect; 0.5 is random guessing. Use for binary classification.</p>
+      <p><strong>Macro ROC-AUC:</strong> Averages the AUC across all classes equally. Suitable when classes are balanced and of equal importance.</p>
+      <p><strong>Micro ROC-AUC:</strong> Computes AUC from aggregated predictions across all classes. Useful in multiclass or multilabel settings with imbalance.</p>
+      <h3>6) Ranking Metrics</h3>
+      <p><strong>Hits at K:</strong> Measures whether the true label is among the top-K predictions. Common in recommendation systems and retrieval tasks.</p>
+      <h3>7) Confusion Matrix Stats (Per Class)</h3>
+      <p><strong>True Positives / Negatives (TP / TN):</strong> Correct predictions for positives and negatives respectively.</p>
+      <p><strong>False Positives / Negatives (FP / FN):</strong> Incorrect predictions — false alarms and missed detections.</p>
+      <h3>8) Other Useful Metrics</h3>
+      <p><strong>Cohen's Kappa:</strong> Measures agreement between predicted and actual values adjusted for chance. Useful for multiclass classification with imbalanced labels.</p>
+      <p><strong>Matthews Correlation Coefficient (MCC):</strong> Balanced measure of prediction quality that takes into account TP, TN, FP, and FN. Particularly effective for imbalanced datasets.</p>
+      <h3>9) Metric Recommendations</h3>
+      <ul>
+        <li>Use <strong>Accuracy + F1</strong> for balanced data.</li>
+        <li>Use <strong>Precision, Recall, ROC-AUC</strong> for imbalanced datasets.</li>
+        <li>Use <strong>Average Precision Micro</strong> for multilabel or class-imbalanced problems.</li>
+        <li>Use <strong>Macro scores</strong> when all classes should be treated equally.</li>
+        <li>Use <strong>Weighted scores</strong> when class imbalance should be accounted for without ignoring small classes.</li>
+        <li>Use <strong>Confusion Matrix stats</strong> to analyze class-wise performance.</li>
+        <li>Use <strong>Hits at K</strong> for recommendation or ranking-based tasks.</li>
+      </ul>
+    </div>
+  </div>
+</div>
+
+<script>
+document.addEventListener("DOMContentLoaded", function() {
+  var modal = document.getElementById("metricsHelpModal");
+  var openBtn = document.getElementById("openMetricsHelp");
+  var span = document.getElementsByClassName("close")[0];
+  if (openBtn && modal) {
+    openBtn.onclick = function() {
+      modal.style.display = "block";
+    };
+  }
+  if (span && modal) {
+    span.onclick = function() {
+      modal.style.display = "none";
+    };
+  }
+  window.onclick = function(event) {
+    if (event.target == modal) {
+      modal.style.display = "none";
+    }
+  }
+});
+</script>
+
+    </div>
+    </body>
+    </html>
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/utkface_labels.csv	Thu Jul 03 20:43:24 2025 +0000
@@ -0,0 +1,13 @@
+image_path,label,split
+1_0_4_20161221195047839.jpg.chip.jpg,1,0
+4_0_0_20170110213253207.jpg.chip.jpg,4,0
+18_1_0_20170109212647587.jpg.chip.jpg,18,0
+24_1_2_20170116164628750.jpg.chip.jpg,24,0
+26_1_0_20170116164911648.jpg.chip.jpg,26,0
+28_1_0_20170109141748286.jpg.chip.jpg,28,0
+31_0_4_20170120133240958.jpg.chip.jpg,31,0
+35_0_0_20170104202556995.jpg.chip.jpg,35,0
+42_0_2_20170117130543345.jpg.chip.jpg,42,1
+52_0_1_20170117175021585.jpg.chip.jpg,52,1
+62_1_3_20170109132000815.jpg.chip.jpg,62,2
+116_1_2_20170112220255503.jpg.chip.jpg,116,2
--- a/utils.py	Wed Jul 02 18:59:10 2025 +0000
+++ b/utils.py	Thu Jul 03 20:43:24 2025 +0000
@@ -155,3 +155,199 @@
     if isinstance(json_data, str):
         json_data = json.loads(json_data)
     return json_to_nested_html_table(json_data)
+
+
+def build_tabbed_html(metrics_html: str, train_val_html: str, test_html: str) -> str:
+    return f"""
+<style>
+  .tabs {{
+    display: flex;
+    align-items: center;
+    border-bottom: 2px solid #ccc;
+    margin-bottom: 1rem;
+  }}
+  .tab {{
+    padding: 10px 20px;
+    cursor: pointer;
+    border: 1px solid #ccc;
+    border-bottom: none;
+    background: #f9f9f9;
+    margin-right: 5px;
+    border-top-left-radius: 8px;
+    border-top-right-radius: 8px;
+  }}
+  .tab.active {{
+    background: white;
+    font-weight: bold;
+  }}
+  /* new help-button styling */
+  .help-btn {{
+    margin-left: auto;
+    padding: 6px 12px;
+    font-size: 0.9rem;
+    border: 1px solid #4CAF50;
+    border-radius: 4px;
+    background: #4CAF50;
+    color: white;
+    cursor: pointer;
+  }}
+  .tab-content {{
+    display: none;
+    padding: 20px;
+    border: 1px solid #ccc;
+    border-top: none;
+  }}
+  .tab-content.active {{
+    display: block;
+  }}
+</style>
+
+<div class="tabs">
+  <div class="tab active" onclick="showTab('metrics')">Config &amp; Results Summary</div>
+  <div class="tab" onclick="showTab('trainval')">Train/Validation Results</div>
+  <div class="tab" onclick="showTab('test')">Test Results</div>
+  <!-- always-visible help button -->
+  <button id="openMetricsHelp" class="help-btn">Help</button>
+</div>
+
+<div id="metrics" class="tab-content active">
+  {metrics_html}
+</div>
+<div id="trainval" class="tab-content">
+  {train_val_html}
+</div>
+<div id="test" class="tab-content">
+  {test_html}
+</div>
+
+<script>
+function showTab(id) {{
+  document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
+  document.querySelectorAll('.tab').forEach(el => el.classList.remove('active'));
+  document.getElementById(id).classList.add('active');
+  document.querySelector(`.tab[onclick*="${{id}}"]`).classList.add('active');
+}}
+</script>
+"""
+
+
+def get_metrics_help_modal() -> str:
+    modal_html = """
+<div id="metricsHelpModal" class="modal">
+  <div class="modal-content">
+    <span class="close">×</span>
+    <h2>Model Evaluation Metrics — Help Guide</h2>
+    <div class="metrics-guide">
+      <h3>1) General Metrics</h3>
+      <p><strong>Loss:</strong> Measures the difference between predicted and actual values. Lower is better. Often used for optimization during training.</p>
+      <p><strong>Accuracy:</strong> Proportion of correct predictions among all predictions. Simple but can be misleading for imbalanced datasets.</p>
+      <p><strong>Micro Accuracy:</strong> Calculates accuracy by summing up all individual true positives and true negatives across all classes, making it suitable for multiclass or multilabel problems.</p>
+      <p><strong>Token Accuracy:</strong> Measures how often the predicted tokens (e.g., in sequences) match the true tokens. Useful in sequence prediction tasks like NLP.</p>
+      <h3>2) Precision, Recall & Specificity</h3>
+      <p><strong>Precision:</strong> Out of all positive predictions, how many were correct. Precision = TP / (TP + FP). Helps when false positives are costly.</p>
+      <p><strong>Recall (Sensitivity):</strong> Out of all actual positives, how many were predicted correctly. Recall = TP / (TP + FN). Important when missing positives is risky.</p>
+      <p><strong>Specificity:</strong> True negative rate. Measures how well the model identifies negatives. Specificity = TN / (TN + FP). Useful in medical testing to avoid false alarms.</p>
+      <h3>3) Macro, Micro, and Weighted Averages</h3>
+      <p><strong>Macro Precision / Recall / F1:</strong> Averages the metric across all classes, treating each class equally, regardless of class frequency. Best when class sizes are balanced.</p>
+      <p><strong>Micro Precision / Recall / F1:</strong> Aggregates TP, FP, FN across all classes before computing the metric. Gives a global view and is ideal for class-imbalanced problems.</p>
+      <p><strong>Weighted Precision / Recall / F1:</strong> Averages each metric across classes, weighted by the number of true instances per class. Balances importance of classes based on frequency.</p>
+      <h3>4) Average Precision (PR-AUC Variants)</h3>
+      <p><strong>Average Precision Macro:</strong> Precision-Recall AUC averaged across all classes equally. Useful for balanced multi-class problems.</p>
+      <p><strong>Average Precision Micro:</strong> Global Precision-Recall AUC using all instances. Best for imbalanced data or multi-label classification.</p>
+      <p><strong>Average Precision Samples:</strong> Precision-Recall AUC averaged across individual samples (not classes). Ideal for multi-label problems where each sample can belong to multiple classes.</p>
+      <h3>5) ROC-AUC Variants</h3>
+      <p><strong>ROC-AUC:</strong> Measures model's ability to distinguish between classes. AUC = 1 is perfect; 0.5 is random guessing. Use for binary classification.</p>
+      <p><strong>Macro ROC-AUC:</strong> Averages the AUC across all classes equally. Suitable when classes are balanced and of equal importance.</p>
+      <p><strong>Micro ROC-AUC:</strong> Computes AUC from aggregated predictions across all classes. Useful in multiclass or multilabel settings with imbalance.</p>
+      <h3>6) Ranking Metrics</h3>
+      <p><strong>Hits at K:</strong> Measures whether the true label is among the top-K predictions. Common in recommendation systems and retrieval tasks.</p>
+      <h3>7) Confusion Matrix Stats (Per Class)</h3>
+      <p><strong>True Positives / Negatives (TP / TN):</strong> Correct predictions for positives and negatives respectively.</p>
+      <p><strong>False Positives / Negatives (FP / FN):</strong> Incorrect predictions — false alarms and missed detections.</p>
+      <h3>8) Other Useful Metrics</h3>
+      <p><strong>Cohen's Kappa:</strong> Measures agreement between predicted and actual values adjusted for chance. Useful for multiclass classification with imbalanced labels.</p>
+      <p><strong>Matthews Correlation Coefficient (MCC):</strong> Balanced measure of prediction quality that takes into account TP, TN, FP, and FN. Particularly effective for imbalanced datasets.</p>
+      <h3>9) Metric Recommendations</h3>
+      <ul>
+        <li>Use <strong>Accuracy + F1</strong> for balanced data.</li>
+        <li>Use <strong>Precision, Recall, ROC-AUC</strong> for imbalanced datasets.</li>
+        <li>Use <strong>Average Precision Micro</strong> for multilabel or class-imbalanced problems.</li>
+        <li>Use <strong>Macro scores</strong> when all classes should be treated equally.</li>
+        <li>Use <strong>Weighted scores</strong> when class imbalance should be accounted for without ignoring small classes.</li>
+        <li>Use <strong>Confusion Matrix stats</strong> to analyze class-wise performance.</li>
+        <li>Use <strong>Hits at K</strong> for recommendation or ranking-based tasks.</li>
+      </ul>
+    </div>
+  </div>
+</div>
+"""
+    modal_css = """
+<style>
+.modal {
+  display: none;
+  position: fixed;
+  z-index: 1;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+  background-color: rgba(0,0,0,0.4);
+}
+.modal-content {
+  background-color: #fefefe;
+  margin: 15% auto;
+  padding: 20px;
+  border: 1px solid #888;
+  width: 80%;
+  max-width: 800px;
+}
+.close {
+  color: #aaa;
+  float: right;
+  font-size: 28px;
+  font-weight: bold;
+}
+.close:hover,
+.close:focus {
+  color: black;
+  text-decoration: none;
+  cursor: pointer;
+}
+.metrics-guide h3 {
+  margin-top: 20px;
+}
+.metrics-guide p {
+  margin: 5px 0;
+}
+.metrics-guide ul {
+  margin: 10px 0;
+  padding-left: 20px;
+}
+</style>
+"""
+    modal_js = """
+<script>
+document.addEventListener("DOMContentLoaded", function() {
+  var modal = document.getElementById("metricsHelpModal");
+  var openBtn = document.getElementById("openMetricsHelp");
+  var span = document.getElementsByClassName("close")[0];
+  if (openBtn && modal) {
+    openBtn.onclick = function() {
+      modal.style.display = "block";
+    };
+  }
+  if (span && modal) {
+    span.onclick = function() {
+      modal.style.display = "none";
+    };
+  }
+  window.onclick = function(event) {
+    if (event.target == modal) {
+      modal.style.display = "none";
+    }
+  }
+});
+</script>
+"""
+    return modal_css + modal_html + modal_js