Akshay4506 commited on
Commit
e057d08
Β·
1 Parent(s): cb9e57b

Revert back

Browse files
Files changed (44) hide show
  1. Dockerfile +2 -16
  2. code/analysis/__init__.py +11 -0
  3. code/analysis/aggregate_results.py +99 -0
  4. code/config/datasets.yaml +33 -0
  5. code/config/experiments.yaml +64 -0
  6. code/config/models.yaml +84 -0
  7. code/docker/Dockerfile +102 -0
  8. code/evaluation/__init__.py +24 -0
  9. code/evaluation/compute_tracker.py +114 -0
  10. code/evaluation/cross_validation.py +127 -0
  11. code/evaluation/metrics.py +116 -0
  12. code/evaluation/statistical_tests.py +109 -0
  13. {webapp β†’ code}/models/__init__.py +0 -0
  14. {webapp β†’ code}/models/autogluon_wrapper.py +0 -0
  15. {webapp β†’ code}/models/base_wrapper.py +0 -0
  16. {webapp β†’ code}/models/baseline_wrappers.py +0 -0
  17. {webapp β†’ code}/models/sap_rpt1_hf_wrapper.py +0 -0
  18. {webapp β†’ code}/models/sap_rpt1_wrapper.py +0 -0
  19. {webapp β†’ code}/models/tabicl_wrapper.py +0 -0
  20. {webapp β†’ code}/models/tabpfn_wrapper.py +24 -43
  21. code/runners/__init__.py +11 -0
  22. code/runners/run_baselines.py +50 -0
  23. code/runners/run_batch.py +289 -0
  24. code/runners/run_experiment.py +260 -0
  25. {webapp β†’ code}/sap_rpt1.egg-info/PKG-INFO +0 -0
  26. code/sap_rpt1.egg-info/SOURCES.txt +28 -0
  27. {webapp β†’ code}/sap_rpt1.egg-info/dependency_links.txt +0 -0
  28. {webapp β†’ code}/sap_rpt1.egg-info/requires.txt +0 -0
  29. code/sap_rpt1.egg-info/top_level.txt +5 -0
  30. code/utils/__init__.py +11 -0
  31. code/utils/logging_utils.py +63 -0
  32. requirements.txt +1 -0
  33. setup.py +2 -2
  34. webapp/benchmark.py +23 -76
  35. webapp/catboost_info/catboost_training.json +200 -200
  36. webapp/catboost_info/learn/events.out.tfevents +1 -1
  37. webapp/catboost_info/learn_error.tsv +200 -200
  38. webapp/catboost_info/time_left.tsv +200 -200
  39. webapp/ensemble.py +5 -11
  40. webapp/main.py +20 -48
  41. webapp/requirements.txt +1 -3
  42. webapp/sap_rpt1.egg-info/SOURCES.txt +0 -15
  43. webapp/sap_rpt1.egg-info/top_level.txt +0 -1
  44. webapp/static/app.js +2 -3
Dockerfile CHANGED
@@ -17,16 +17,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
17
  && rm -rf /var/lib/apt/lists/*
18
  USER user
19
 
20
- # ── TabPFN license acceptance ──────────────────────────────────────────────────
21
- # Set ALL known env var names TabPFN v2 checks for, at the container level.
22
- # This must be done before any Python code runs β€” setting them inside Python
23
- # files is too late because TabPFN checks on import.
24
- ENV TABPFN_ACCEPT_LICENSE=1 \
25
- TABPFN_LICENSE=accept \
26
- TABPFN_ACCEPT_TERMS=1 \
27
- TABPFN_LICENSE_ACCEPTED=1 \
28
- AGREE_TABPFN_LICENSE=1
29
-
30
  # Copy the entire project
31
  COPY --chown=user . $HOME/app/
32
 
@@ -37,12 +27,8 @@ RUN pip install --no-cache-dir -r webapp/requirements.txt
37
  # Install SAP-RPT-1 OSS directly from GitHub (needed for the real model)
38
  RUN pip install --no-cache-dir git+https://github.com/SAP-samples/sap-rpt-1-oss.git
39
 
40
- # Pre-download Sentence Transformers weights to avoid runtime hangs
41
- # This specific model is used by the SAP RPT-1 OSS model.
42
- RUN python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2')"
43
-
44
  # Expose port 7860 (Hugging Face Spaces default port)
45
  EXPOSE 7860
46
 
47
- # Run the FastAPI app with a single worker to save RAM and avoid download race conditions
48
- CMD ["python", "-m", "uvicorn", "webapp.main:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
 
17
  && rm -rf /var/lib/apt/lists/*
18
  USER user
19
 
 
 
 
 
 
 
 
 
 
 
20
  # Copy the entire project
21
  COPY --chown=user . $HOME/app/
22
 
 
27
  # Install SAP-RPT-1 OSS directly from GitHub (needed for the real model)
28
  RUN pip install --no-cache-dir git+https://github.com/SAP-samples/sap-rpt-1-oss.git
29
 
 
 
 
 
30
  # Expose port 7860 (Hugging Face Spaces default port)
31
  EXPOSE 7860
32
 
33
+ # Run the FastAPI app
34
+ CMD ["python", "-m", "uvicorn", "webapp.main:app", "--host", "0.0.0.0", "--port", "7860"]
code/analysis/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Analysis Package
3
+ ================
4
+
5
+ Results aggregation, statistical analysis, and visualization.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ __all__ = ['aggregate_results']
code/analysis/aggregate_results.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Results Aggregation
3
+ ===================
4
+
5
+ Aggregate all experiment results into summary tables.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ import glob
12
+ import json
13
+ import pandas as pd
14
+ import os
15
+ import logging
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ def aggregate_all_results(
21
+ results_dir: str = '../results/raw',
22
+ output_file: str = '../results/processed/aggregated_results.csv'
23
+ ) -> pd.DataFrame:
24
+ """
25
+ Aggregate all experiment results into single DataFrame.
26
+
27
+ Parameters
28
+ ----------
29
+ results_dir : str
30
+ Directory containing result JSON files
31
+ output_file : str
32
+ Where to save aggregated CSV
33
+
34
+ Returns
35
+ -------
36
+ df : pd.DataFrame
37
+ Aggregated results
38
+ """
39
+ logger.info(f"Aggregating results from {results_dir}")
40
+
41
+ result_files = glob.glob(os.path.join(results_dir, '*.json'))
42
+ logger.info(f"Found {len(result_files)} result files")
43
+
44
+ aggregated = []
45
+
46
+ for file in result_files:
47
+ try:
48
+ with open(file) as f:
49
+ data = json.load(f)
50
+
51
+ record = {
52
+ 'dataset': data['dataset'],
53
+ 'model': data['model'],
54
+ 'task_type': data['task_type'],
55
+ 'n_samples': data['n_samples'],
56
+ 'n_features': data['n_features'],
57
+ 'n_folds': data['n_folds']
58
+ }
59
+
60
+ # Add mean metrics
61
+ for metric, value in data['mean_metrics'].items():
62
+ record[f'mean_{metric}'] = value
63
+
64
+ # Add std metrics
65
+ for metric, value in data['std_metrics'].items():
66
+ record[f'std_{metric}'] = value
67
+
68
+ # Add compute info
69
+ if 'compute' in data:
70
+ record['elapsed_hours'] = data['compute'].get('elapsed_hours')
71
+ record['cost_usd'] = data['compute'].get('cost_usd')
72
+
73
+ aggregated.append(record)
74
+
75
+ except Exception as e:
76
+ logger.warning(f"Failed to process {file}: {e}")
77
+
78
+ # Create DataFrame
79
+ df = pd.DataFrame(aggregated)
80
+
81
+ # Save
82
+ os.makedirs(os.path.dirname(output_file), exist_ok=True)
83
+ df.to_csv(output_file, index=False)
84
+
85
+ logger.info(f"Aggregated {len(df)} results to {output_file}")
86
+
87
+ return df
88
+
89
+
90
+ if __name__ == "__main__":
91
+ logging.basicConfig(level=logging.INFO)
92
+
93
+ df = aggregate_all_results()
94
+
95
+ print(f"\nβœ… Aggregated {len(df)} experiment results")
96
+ print(f"\nDatasets: {df['dataset'].nunique()}")
97
+ print(f"Models: {df['model'].nunique()}")
98
+ print(f"\nSample of results:")
99
+ print(df.head())
code/config/datasets.yaml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dataset Configuration
2
+ # =====================
3
+
4
+ # Local Datasets (from datasets folder)
5
+ local_datasets:
6
+ enabled: true
7
+ path: '../datasets'
8
+
9
+ # TabZilla Datasets (subset of 20)
10
+ tabzilla:
11
+ enabled: false # Enable when data is available
12
+ path: '../datasets/tabzilla'
13
+
14
+ # OpenML-CC18 (Classification subset)
15
+ openml_cc18:
16
+ enabled: false
17
+ path: '../datasets/openml_cc18'
18
+
19
+ # Dataset Filters
20
+ filters:
21
+ min_samples: 100
22
+ max_samples: 100000
23
+ min_features: 2
24
+ max_features: 1000
25
+ task_types:
26
+ - classification
27
+ - regression
28
+
29
+ # Preprocessing
30
+ preprocessing:
31
+ handle_missing: 'mean' # mean, median, most_frequent, drop
32
+ encode_categoricals: true
33
+ scale_features: false # Most models handle scaling internally
code/config/experiments.yaml ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Experiment Configuration
2
+ # ========================
3
+
4
+ # Cross-Validation Settings
5
+ n_folds: 10
6
+ random_state: 42
7
+ timeout: 86400 # 24 hours per experiment
8
+
9
+ # Compute Resources
10
+ cost_per_hour: 0.90 # USD per GPU-hour (H200)
11
+ gpu_type: 'H200'
12
+ gpu_memory_limit: 80 # GB
13
+ checkpoint_interval: 3600 # Save checkpoint every hour
14
+
15
+ # Model-Specific Parameters
16
+ model_params:
17
+ sap_rpt1:
18
+ context_size: 4096
19
+ bagging_factor: 4
20
+ model_size: 'small' # or 'large'
21
+
22
+ sap_rpt1_hf:
23
+ max_context_size: 4096
24
+ bagging: 4
25
+
26
+ tabpfn:
27
+ n_ensemble: 1
28
+ device: 'auto'
29
+
30
+ autogluon:
31
+ time_limit: 300 # 5 minutes
32
+ preset: 'medium_quality' # best_quality, high_quality, good_quality, medium_quality
33
+
34
+ xgboost:
35
+ n_estimators: 100
36
+ learning_rate: 0.1
37
+ max_depth: 6
38
+
39
+ catboost:
40
+ iterations: 100
41
+ learning_rate: 0.1
42
+ depth: 6
43
+
44
+ lightgbm:
45
+ n_estimators: 100
46
+ learning_rate: 0.1
47
+ max_depth: -1
48
+
49
+ # Evaluation Metrics
50
+ primary_metric:
51
+ classification: 'roc_auc'
52
+ regression: 'r2'
53
+
54
+ # Statistical Testing
55
+ statistical_tests:
56
+ friedman_alpha: 0.05
57
+ nemenyi_alpha: 0.05
58
+
59
+ # Reproducibility
60
+ reproducibility:
61
+ save_predictions: true
62
+ save_models: false # Models can be large
63
+ log_hyperparameters: true
64
+ track_compute: true
code/config/models.yaml ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Configuration
2
+ # ====================
3
+
4
+ models:
5
+ # SAP RPT-1 (Primary Model)
6
+ - name: 'sap-rpt1-small'
7
+ enabled: true
8
+ priority: 'high'
9
+ docker_image: 'sap-rpt1'
10
+
11
+ - name: 'sap-rpt1-large'
12
+ enabled: true
13
+ priority: 'high'
14
+ docker_image: 'sap-rpt1'
15
+
16
+ # SAP RPT-1 OSS via Hugging Face (Open Source)
17
+ - name: 'sap-rpt1-hf'
18
+ enabled: true
19
+ priority: 'high'
20
+ docker_image: 'sap-rpt1'
21
+ description: 'SAP RPT-1 OSS model via HuggingFace token authentication'
22
+
23
+ # Pretrained Competitors
24
+ - name: 'tabpfn'
25
+ enabled: true
26
+ priority: 'high'
27
+ docker_image: 'tabpfn'
28
+
29
+ - name: 'tabicl'
30
+ enabled: false # Enable when implementation ready
31
+ priority: 'medium'
32
+ docker_image: 'tabicl'
33
+
34
+ # AutoML
35
+ - name: 'autogluon'
36
+ enabled: true
37
+ priority: 'medium'
38
+ docker_image: 'autogluon'
39
+
40
+ # Gradient Boosting Baselines
41
+ - name: 'xgboost'
42
+ enabled: true
43
+ priority: 'medium'
44
+ docker_image: 'baselines'
45
+
46
+ - name: 'catboost'
47
+ enabled: true
48
+ priority: 'medium'
49
+ docker_image: 'baselines'
50
+
51
+ - name: 'lightgbm'
52
+ enabled: true
53
+ priority: 'low'
54
+ docker_image: 'baselines'
55
+
56
+ # Model Groups (for batch experiments)
57
+ model_groups:
58
+ all:
59
+ - sap-rpt1-small
60
+ - sap-rpt1-large
61
+ - sap-rpt1-hf
62
+ - tabpfn
63
+ - autogluon
64
+ - xgboost
65
+ - catboost
66
+ - lightgbm
67
+
68
+ pretrained_only:
69
+ - sap-rpt1-small
70
+ - sap-rpt1-large
71
+ - sap-rpt1-hf
72
+ - tabpfn
73
+
74
+ baselines_only:
75
+ - xgboost
76
+ - catboost
77
+ - lightgbm
78
+
79
+ high_priority:
80
+ - sap-rpt1-small
81
+ - sap-rpt1-large
82
+ - sap-rpt1-hf
83
+ - tabpfn
84
+
code/docker/Dockerfile ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =============================================================================
2
+ # SAP RPT-1 Benchmarking - Multi-stage Dockerfile
3
+ # =============================================================================
4
+ # Builds two targets:
5
+ # - sap-rpt1: Python 3.11 with SAP RPT-1 OSS + all dependencies
6
+ # - baselines: Python 3.11 with XGBoost, CatBoost, LightGBM
7
+ #
8
+ # Usage:
9
+ # docker-compose build
10
+ # docker-compose run sap-rpt1
11
+ # docker-compose run baselines
12
+ # =============================================================================
13
+
14
+ # ---------- Base stage (shared by all targets) ----------
15
+ FROM python:3.11-slim AS base
16
+
17
+ # System dependencies
18
+ RUN apt-get update && apt-get install -y --no-install-recommends \
19
+ git \
20
+ build-essential \
21
+ && rm -rf /var/lib/apt/lists/*
22
+
23
+ WORKDIR /app
24
+
25
+ # Copy requirements first (for Docker layer caching)
26
+ COPY requirements.txt /app/requirements.txt
27
+
28
+ # ---------- SAP RPT-1 target ----------
29
+ FROM base AS sap-rpt1
30
+
31
+ # Install core scientific stack first (heavy packages)
32
+ RUN pip install --default-timeout=1000 --retries 5 --no-cache-dir \
33
+ numpy==1.26.4 \
34
+ pandas==2.2.3 \
35
+ scikit-learn==1.6.1 \
36
+ scipy==1.14.1 \
37
+ matplotlib==3.9.2 \
38
+ seaborn==0.13.2
39
+
40
+ # Install Hugging Face and PyTorch stack
41
+ RUN pip install --default-timeout=1000 --retries 5 --no-cache-dir \
42
+ --extra-index-url https://download.pytorch.org/whl/cpu \
43
+ torch==2.7.0+cpu \
44
+ transformers==4.52.4 \
45
+ accelerate==1.6.0 \
46
+ huggingface-hub==0.30.2 \
47
+ datasets==3.5.0 \
48
+ pyarrow==20.0.0 \
49
+ torcheval==0.0.7
50
+
51
+ # Install SAP RPT-1 and remaining requirements
52
+ RUN pip install --default-timeout=1000 --retries 5 --no-cache-dir -r requirements.txt
53
+
54
+ # Copy project code
55
+ COPY . /app
56
+
57
+ # Set Python path
58
+ ENV PYTHONPATH=/app/code
59
+
60
+ WORKDIR /app/code
61
+
62
+ # Set entrypoint so you can run via arguments natively
63
+ ENTRYPOINT ["python"]
64
+ CMD ["-m", "runners.run_experiment", "--dataset", "adult", "--model", "sap-rpt1-hf"]
65
+
66
+ # ---------- Baselines target ----------
67
+ FROM base AS baselines
68
+
69
+ # Install core scientific stack (heavy packages)
70
+ RUN pip install --default-timeout=1000 --retries 5 --no-cache-dir \
71
+ numpy==1.26.4 \
72
+ pandas==2.2.3 \
73
+ scikit-learn==1.6.1 \
74
+ scipy==1.14.1
75
+
76
+ # Install visualization and utilities
77
+ RUN pip install --default-timeout=1000 --retries 5 --no-cache-dir \
78
+ matplotlib==3.9.2 \
79
+ seaborn==0.13.2 \
80
+ pyyaml==6.0.2 \
81
+ tqdm==4.67.1 \
82
+ joblib==1.4.2 \
83
+ python-dotenv==1.0.1
84
+
85
+ # Install ML frameworks and OpenML
86
+ RUN pip install --default-timeout=1000 --retries 5 --no-cache-dir \
87
+ openml==0.14.2 \
88
+ xgboost \
89
+ catboost \
90
+ lightgbm
91
+
92
+ # Copy project code
93
+ COPY . /app
94
+
95
+ # Set Python path
96
+ ENV PYTHONPATH=/app/code
97
+
98
+ WORKDIR /app/code
99
+
100
+ # Set entrypoint so you can run via arguments natively
101
+ ENTRYPOINT ["python"]
102
+ CMD ["-m", "runners.run_batch", "--datasets", "config/datasets.yaml", "--models", "config/models.yaml"]
code/evaluation/__init__.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Evaluation Package
3
+ ==================
4
+
5
+ Tools for model evaluation, statistical testing, and benchmarking.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ from .metrics import calculate_classification_metrics, calculate_regression_metrics
12
+ from .cross_validation import run_cross_validation
13
+ from .statistical_tests import friedman_test, nemenyi_post_hoc, critical_difference
14
+ from .compute_tracker import ComputeTracker
15
+
16
+ __all__ = [
17
+ 'calculate_classification_metrics',
18
+ 'calculate_regression_metrics',
19
+ 'run_cross_validation',
20
+ 'friedman_test',
21
+ 'nemenyi_post_hoc',
22
+ 'critical_difference',
23
+ 'ComputeTracker'
24
+ ]
code/evaluation/compute_tracker.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Compute Resource Tracker
3
+ =========================
4
+
5
+ Track GPU hours, costs, and resource usage for experiments.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ import time
12
+ import numpy as np
13
+ from typing import Dict, Optional, List
14
+
15
+ try:
16
+ import psutil
17
+ HAS_PSUTIL = True
18
+ except ImportError:
19
+ HAS_PSUTIL = False
20
+ import logging
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class ComputeTracker:
26
+ """
27
+ Track compute resources and costs.
28
+
29
+ Parameters
30
+ ----------
31
+ cost_per_hour : float
32
+ Cost per GPU-hour in USD
33
+ gpu_type : str
34
+ GPU type (e.g., 'H200', 'A100', 'L40S')
35
+ """
36
+
37
+ def __init__(self, cost_per_hour: float = 0.90, gpu_type: str = 'H200'):
38
+ self.cost_per_hour = cost_per_hour
39
+ self.gpu_type = gpu_type
40
+ self.start_time: Optional[float] = None
41
+ self.end_time: Optional[float] = None
42
+ self.gpu_usage_log: List[Dict] = []
43
+
44
+ def start(self):
45
+ """Start tracking."""
46
+ self.start_time = time.time()
47
+ self.gpu_usage_log = []
48
+ logger.info(f"Compute tracking started (GPU: {self.gpu_type}, ${self.cost_per_hour}/hr)")
49
+
50
+ def log_gpu_usage(self):
51
+ """Log current GPU usage."""
52
+ try:
53
+ import GPUtil
54
+ gpus = GPUtil.getGPUs()
55
+
56
+ for gpu in gpus:
57
+ self.gpu_usage_log.append({
58
+ 'timestamp': time.time(),
59
+ 'gpu_id': gpu.id,
60
+ 'gpu_load': gpu.load * 100,
61
+ 'memory_used_mb': gpu.memoryUsed,
62
+ 'memory_total_mb': gpu.memoryTotal,
63
+ 'memory_util': (gpu.memoryUsed / gpu.memoryTotal) * 100,
64
+ 'temperature': getattr(gpu, 'temperature', None)
65
+ })
66
+ except ImportError:
67
+ logger.warning("GPUtil not installed, GPU tracking unavailable")
68
+ except Exception as e:
69
+ logger.warning(f"GPU logging failed: {e}")
70
+
71
+ def stop(self) -> Dict:
72
+ """
73
+ Stop tracking and calculate costs.
74
+
75
+ Returns
76
+ -------
77
+ summary : dict
78
+ Elapsed time, costs, and GPU usage summary
79
+ """
80
+ self.end_time = time.time()
81
+
82
+ elapsed_hours = (self.end_time - self.start_time) / 3600
83
+ total_cost = elapsed_hours * self.cost_per_hour
84
+
85
+ # CPU usage
86
+ if HAS_PSUTIL:
87
+ cpu_percent = psutil.cpu_percent(interval=1)
88
+ memory_info = psutil.virtual_memory()
89
+ memory_percent = memory_info.percent
90
+ memory_used_gb = memory_info.used / (1024 ** 3)
91
+ else:
92
+ cpu_percent = 0.0
93
+ memory_percent = 0.0
94
+ memory_used_gb = 0.0
95
+
96
+ summary = {
97
+ 'elapsed_hours': elapsed_hours,
98
+ 'cost_usd': total_cost,
99
+ 'cost_per_hour': self.cost_per_hour,
100
+ 'gpu_type': self.gpu_type,
101
+ 'cpu_percent': cpu_percent,
102
+ 'memory_percent': memory_percent,
103
+ 'memory_used_gb': memory_used_gb,
104
+ 'gpu_logs_count': len(self.gpu_usage_log)
105
+ }
106
+
107
+ # Average GPU utilization
108
+ if self.gpu_usage_log:
109
+ summary['avg_gpu_load'] = np.mean([log['gpu_load'] for log in self.gpu_usage_log])
110
+ summary['avg_gpu_memory_util'] = np.mean([log['memory_util'] for log in self.gpu_usage_log])
111
+
112
+ logger.info(f"Compute tracking stopped: {elapsed_hours:.2f} hours, ${total_cost:.2f}")
113
+
114
+ return summary
code/evaluation/cross_validation.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Cross-Validation
3
+ ================
4
+
5
+ 10-fold stratified cross-validation for model evaluation.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ import numpy as np
12
+ import pandas as pd
13
+ from sklearn.model_selection import StratifiedKFold, KFold
14
+ from sklearn.preprocessing import LabelEncoder
15
+ from typing import List, Dict
16
+ import logging
17
+
18
+ from .metrics import calculate_classification_metrics, calculate_regression_metrics
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ def _encode_categorical_columns(X_train, X_val):
24
+ """
25
+ Label-encode object/categorical columns. Fitted on X_train,
26
+ applied to both X_train and X_val. Unknown categories in X_val
27
+ are mapped to -1.
28
+ """
29
+ X_train = X_train.copy()
30
+ X_val = X_val.copy()
31
+
32
+ cat_cols = X_train.select_dtypes(include=['object', 'category']).columns
33
+ if len(cat_cols) == 0:
34
+ return X_train, X_val
35
+
36
+ logger.info(f" Encoding {len(cat_cols)} categorical columns: {list(cat_cols[:5])}{'...' if len(cat_cols) > 5 else ''}")
37
+
38
+ for col in cat_cols:
39
+ le = LabelEncoder()
40
+ # Fit on combined unique values from train (+ handle unseen in val)
41
+ combined = pd.concat([X_train[col], X_val[col]], axis=0).astype(str)
42
+ le.fit(combined)
43
+ X_train[col] = le.transform(X_train[col].astype(str))
44
+ X_val[col] = le.transform(X_val[col].astype(str))
45
+
46
+ return X_train, X_val
47
+
48
+
49
+ def run_cross_validation(
50
+ model,
51
+ X: pd.DataFrame,
52
+ y: pd.Series,
53
+ task_type: str = 'classification',
54
+ n_folds: int = 10,
55
+ random_state: int = 42
56
+ ) -> List[Dict]:
57
+ """
58
+ Run k-fold cross-validation.
59
+
60
+ Parameters
61
+ ----------
62
+ model : BaseModelWrapper
63
+ Model to evaluate (must have fit/predict methods)
64
+ X : pd.DataFrame
65
+ Features
66
+ y : pd.Series
67
+ Target
68
+ task_type : str
69
+ 'classification' or 'regression'
70
+ n_folds : int
71
+ Number of folds
72
+ random_state : int
73
+ Random seed
74
+
75
+ Returns
76
+ -------
77
+ fold_results : list of dict
78
+ Results for each fold
79
+ """
80
+ logger.info(f"Running {n_folds}-fold CV for {model.__class__.__name__}")
81
+
82
+ # Choose CV splitter
83
+ if task_type == 'classification':
84
+ cv = StratifiedKFold(n_splits=n_folds, shuffle=True, random_state=random_state)
85
+ else:
86
+ cv = KFold(n_splits=n_folds, shuffle=True, random_state=random_state)
87
+
88
+ fold_results = []
89
+
90
+ for fold_idx, (train_idx, val_idx) in enumerate(cv.split(X, y)):
91
+ logger.info(f" Fold {fold_idx + 1}/{n_folds}")
92
+
93
+ # Split data
94
+ X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
95
+ y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
96
+
97
+ # Auto-encode categorical columns so tree models can handle them
98
+ X_train, X_val = _encode_categorical_columns(X_train, X_val)
99
+
100
+ # Fit model
101
+ model.fit(X_train, y_train)
102
+
103
+ # Predict
104
+ y_pred = model.predict(X_val)
105
+ y_proba = None
106
+ if task_type == 'classification':
107
+ try:
108
+ y_proba = model.predict_proba(X_val)
109
+ except:
110
+ pass
111
+
112
+ # Calculate metrics
113
+ if task_type == 'classification':
114
+ metrics = calculate_classification_metrics(y_val, y_pred, y_proba)
115
+ else:
116
+ metrics = calculate_regression_metrics(y_val, y_pred)
117
+
118
+ # Add timing info
119
+ metrics.update({
120
+ 'fold': fold_idx,
121
+ 'fit_time': model.fit_time,
122
+ 'predict_time': model.predict_time
123
+ })
124
+
125
+ fold_results.append(metrics)
126
+
127
+ return fold_results
code/evaluation/metrics.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Evaluation Metrics
3
+ ==================
4
+
5
+ Comprehensive metrics for classification and regression tasks.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ import numpy as np
12
+ from sklearn.metrics import (
13
+ roc_auc_score, accuracy_score, f1_score, precision_score, recall_score,
14
+ r2_score, mean_squared_error, mean_absolute_error, log_loss
15
+ )
16
+ from typing import Dict, Optional
17
+ import logging
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ def calculate_classification_metrics(
23
+ y_true: np.ndarray,
24
+ y_pred: np.ndarray,
25
+ y_proba: Optional[np.ndarray] = None
26
+ ) -> Dict[str, float]:
27
+ """
28
+ Calculate all classification metrics.
29
+
30
+ Parameters
31
+ ----------
32
+ y_true : np.ndarray
33
+ True labels
34
+ y_pred : np.ndarray
35
+ Predicted labels
36
+ y_proba : np.ndarray, optional
37
+ Predicted probabilities (n_samples, n_classes)
38
+
39
+ Returns
40
+ -------
41
+ metrics : dict
42
+ Dictionary of metric names and values
43
+ """
44
+ metrics = {
45
+ 'accuracy': accuracy_score(y_true, y_pred),
46
+ 'f1_macro': f1_score(y_true, y_pred, average='macro', zero_division=0),
47
+ 'f1_weighted': f1_score(y_true, y_pred, average='weighted', zero_division=0),
48
+ 'precision_macro': precision_score(y_true, y_pred, average='macro', zero_division=0),
49
+ 'recall_macro': recall_score(y_true, y_pred, average='macro', zero_division=0)
50
+ }
51
+
52
+ # ROC-AUC (if probabilities available)
53
+ if y_proba is not None:
54
+ try:
55
+ n_classes = len(np.unique(y_true))
56
+
57
+ if n_classes == 2:
58
+ # Binary classification
59
+ metrics['roc_auc'] = roc_auc_score(y_true, y_proba[:, 1])
60
+ else:
61
+ # Multi-class classification
62
+ metrics['roc_auc'] = roc_auc_score(
63
+ y_true, y_proba,
64
+ multi_class='ovr',
65
+ average='macro'
66
+ )
67
+
68
+ # Log loss
69
+ metrics['log_loss'] = log_loss(y_true, y_proba)
70
+
71
+ except Exception as e:
72
+ logger.warning(f"ROC-AUC calculation failed: {e}")
73
+ metrics['roc_auc'] = np.nan
74
+ metrics['log_loss'] = np.nan
75
+
76
+ return metrics
77
+
78
+
79
+ def calculate_regression_metrics(
80
+ y_true: np.ndarray,
81
+ y_pred: np.ndarray
82
+ ) -> Dict[str, float]:
83
+ """
84
+ Calculate all regression metrics.
85
+
86
+ Parameters
87
+ ----------
88
+ y_true : np.ndarray
89
+ True values
90
+ y_pred : np.ndarray
91
+ Predicted values
92
+
93
+ Returns
94
+ -------
95
+ metrics : dict
96
+ Dictionary of metric names and values
97
+ """
98
+ metrics = {
99
+ 'r2': r2_score(y_true, y_pred),
100
+ 'rmse': np.sqrt(mean_squared_error(y_true, y_pred)),
101
+ 'mae': mean_absolute_error(y_true, y_pred),
102
+ 'mse': mean_squared_error(y_true, y_pred)
103
+ }
104
+
105
+ # MAPE (avoid division by zero)
106
+ try:
107
+ non_zero_mask = y_true != 0
108
+ if np.any(non_zero_mask):
109
+ mape = np.mean(np.abs((y_true[non_zero_mask] - y_pred[non_zero_mask]) / y_true[non_zero_mask])) * 100
110
+ metrics['mape'] = mape
111
+ else:
112
+ metrics['mape'] = np.nan
113
+ except:
114
+ metrics['mape'] = np.nan
115
+
116
+ return metrics
code/evaluation/statistical_tests.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Statistical Tests
3
+ =================
4
+
5
+ Statistical significance testing for model comparisons.
6
+
7
+ Implements:
8
+ - Friedman test (non-parametric ANOVA)
9
+ - Nemenyi post-hoc test
10
+ - Critical difference calculation
11
+
12
+ Author: UW MSIM Team
13
+ Date: November 2025
14
+ """
15
+
16
+ import numpy as np
17
+ import pandas as pd
18
+ from scipy import stats
19
+ from typing import Dict, Tuple
20
+ import logging
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ def friedman_test(results_df: pd.DataFrame) -> Dict:
26
+ """
27
+ Friedman test for comparing multiple models.
28
+
29
+ Parameters
30
+ ----------
31
+ results_df : pd.DataFrame
32
+ Rows = datasets, columns = models, values = metric scores
33
+
34
+ Returns
35
+ -------
36
+ results : dict
37
+ Test statistic, p-value, and significance
38
+ """
39
+ # Rank models for each dataset (higher is better)
40
+ ranks = results_df.rank(axis=1, ascending=False)
41
+
42
+ # Friedman test
43
+ stat, p_value = stats.friedmanchisquare(*[ranks[col] for col in ranks.columns])
44
+
45
+ logger.info(f"Friedman Test: statistic={stat:.4f}, p-value={p_value:.4e}")
46
+
47
+ return {
48
+ 'statistic': stat,
49
+ 'p_value': p_value,
50
+ 'significant': p_value < 0.05,
51
+ 'avg_ranks': ranks.mean().to_dict()
52
+ }
53
+
54
+
55
+ def nemenyi_post_hoc(results_df: pd.DataFrame) -> pd.DataFrame:
56
+ """
57
+ Nemenyi post-hoc test (pairwise comparisons).
58
+
59
+ Parameters
60
+ ----------
61
+ results_df : pd.DataFrame
62
+ Rows = datasets, columns = models, values = metric scores
63
+
64
+ Returns
65
+ -------
66
+ p_values : pd.DataFrame
67
+ Pairwise p-values
68
+ """
69
+ try:
70
+ import scikit_posthocs as sp
71
+ ranks = results_df.rank(axis=1, ascending=False)
72
+ p_values = sp.posthoc_nemenyi_friedman(ranks.T)
73
+ return p_values
74
+ except ImportError:
75
+ logger.error("scikit-posthocs not installed. Install with: pip install scikit-posthocs")
76
+ raise
77
+
78
+
79
+ def critical_difference(
80
+ n_datasets: int,
81
+ n_models: int,
82
+ alpha: float = 0.05
83
+ ) -> float:
84
+ """
85
+ Calculate critical difference for CD diagrams.
86
+
87
+ Parameters
88
+ ----------
89
+ n_datasets : int
90
+ Number of datasets
91
+ n_models : int
92
+ Number of models
93
+ alpha : float
94
+ Significance level
95
+
96
+ Returns
97
+ -------
98
+ cd : float
99
+ Critical difference value
100
+ """
101
+ # Critical value from Nemenyi distribution
102
+ # Approximation using normal distribution
103
+ q_alpha = stats.norm.ppf(1 - alpha / 2)
104
+
105
+ cd = q_alpha * np.sqrt((n_models * (n_models + 1)) / (6 * n_datasets))
106
+
107
+ logger.info(f"Critical Difference: {cd:.4f} (alpha={alpha})")
108
+
109
+ return cd
{webapp β†’ code}/models/__init__.py RENAMED
File without changes
{webapp β†’ code}/models/autogluon_wrapper.py RENAMED
File without changes
{webapp β†’ code}/models/base_wrapper.py RENAMED
File without changes
{webapp β†’ code}/models/baseline_wrappers.py RENAMED
File without changes
{webapp β†’ code}/models/sap_rpt1_hf_wrapper.py RENAMED
File without changes
{webapp β†’ code}/models/sap_rpt1_wrapper.py RENAMED
File without changes
{webapp β†’ code}/models/tabicl_wrapper.py RENAMED
File without changes
{webapp β†’ code}/models/tabpfn_wrapper.py RENAMED
@@ -18,19 +18,9 @@ from typing import Optional, Union
18
  import numpy as np
19
  import pandas as pd
20
 
21
- # ── TabPFN non-interactive authentication ─────────────────────────────────────
22
- # For TabPFN v2 (PriorLabs), set TABPFN_TOKEN from the HF Space secret.
23
- # The user must add TABPFN_TOKEN as a secret in HF Space settings.
24
- _tabpfn_token = os.environ.get("TABPFN_TOKEN", "")
25
- if _tabpfn_token:
26
- os.environ["TABPFN_TOKEN"] = _tabpfn_token # ensure it's set for child processes
27
-
28
- # Cover all license-acceptance env var names across TabPFN versions.
29
- os.environ["TABPFN_ACCEPT_LICENSE"] = "1"
30
- os.environ["TABPFN_LICENSE"] = "accept"
31
- os.environ["TABPFN_ACCEPT_TERMS"] = "1"
32
- os.environ["TABPFN_LICENSE_ACCEPTED"] = "1"
33
- os.environ["AGREE_TABPFN_LICENSE"] = "1"
34
 
35
  # ── Patch for old TabPFN compatibility with newer torch ──────────────────────
36
  try:
@@ -84,10 +74,6 @@ class TabPFNWrapper(BaseModelWrapper):
84
  Random seed
85
  """
86
 
87
- # Class-level cache: weights are loaded once and shared across ALL instances
88
- # in the same process. This prevents reloading 103 weight files on every CV fold.
89
- _shared_classifier = None
90
-
91
  def __init__(
92
  self,
93
  task_type: str = 'classification',
@@ -106,6 +92,18 @@ class TabPFNWrapper(BaseModelWrapper):
106
  def fit(self, X: Union[pd.DataFrame, np.ndarray], y: Union[pd.Series, np.ndarray]) -> 'TabPFNWrapper':
107
  """
108
  Fit TabPFN (stores training data for in-context learning).
 
 
 
 
 
 
 
 
 
 
 
 
109
  """
110
  self._validate_input(X, y)
111
 
@@ -141,35 +139,18 @@ class TabPFNWrapper(BaseModelWrapper):
141
  try:
142
  from tabpfn import TabPFNClassifier
143
 
 
144
  import tabpfn
145
-
146
- # Reuse class-level cached classifier so weights are only loaded ONCE
147
- # per process, not once per CV fold.
148
- if TabPFNWrapper._shared_classifier is None:
149
- logger.info("Creating new TabPFNClassifier and caching at class level...")
150
- # TabPFN v2: no device/N_ensemble args; token read from TABPFN_TOKEN env var.
151
- # TabPFN v0.1.x: needs device + N_ensemble_configurations.
152
- version = getattr(tabpfn, '__version__', '0')
153
- if version.startswith('0.1'):
154
- import torch
155
- actual_device = 'cuda' if (self.device == 'auto' and torch.cuda.is_available()) else 'cpu'
156
- TabPFNWrapper._shared_classifier = TabPFNClassifier(
157
- device=actual_device,
158
- N_ensemble_configurations=self.n_ensemble
159
- )
160
- else:
161
- # v2+: just instantiate β€” auth is via TABPFN_TOKEN env var
162
- TabPFNWrapper._shared_classifier = TabPFNClassifier()
163
  else:
164
- logger.info("Reusing cached TabPFN classifier (weights NOT reloaded).")
165
-
166
- self.model = TabPFNWrapper._shared_classifier
167
 
168
- # Fit β€” v0.1.x accepts overwrite_warning=True; v2+ does not.
169
- try:
170
- self.model.fit(X, y, overwrite_warning=True)
171
- except TypeError:
172
- self.model.fit(X, y)
173
 
174
  self.is_fitted = True
175
  self.fit_time = time.time() - start_time
 
18
  import numpy as np
19
  import pandas as pd
20
 
21
+ # Automatically accept the TabPFN license to prevent browser/socket crashes on Windows
22
+ os.environ["TABPFN_LICENSE"] = "accept"
23
+ os.environ["TABPFN_ACCEPT_LICENSE"] = "1"
 
 
 
 
 
 
 
 
 
 
24
 
25
  # ── Patch for old TabPFN compatibility with newer torch ──────────────────────
26
  try:
 
74
  Random seed
75
  """
76
 
 
 
 
 
77
  def __init__(
78
  self,
79
  task_type: str = 'classification',
 
92
  def fit(self, X: Union[pd.DataFrame, np.ndarray], y: Union[pd.Series, np.ndarray]) -> 'TabPFNWrapper':
93
  """
94
  Fit TabPFN (stores training data for in-context learning).
95
+
96
+ Parameters
97
+ ----------
98
+ X : pd.DataFrame or np.ndarray, shape (n_samples, n_features)
99
+ Training features (max 1000 samples, 100 features)
100
+ y : pd.Series or np.ndarray, shape (n_samples,)
101
+ Training target
102
+
103
+ Returns
104
+ -------
105
+ self : TabPFNWrapper
106
+ Fitted model
107
  """
108
  self._validate_input(X, y)
109
 
 
139
  try:
140
  from tabpfn import TabPFNClassifier
141
 
142
+ import torch
143
  import tabpfn
144
+
145
+ actual_device = 'cuda' if (self.device == 'auto' and torch.cuda.is_available()) else ('cpu' if self.device == 'auto' else self.device)
146
+
147
+ if hasattr(tabpfn, '__version__') and tabpfn.__version__.startswith('0.1'):
148
+ self.model = TabPFNClassifier(device=actual_device, N_ensemble_configurations=self.n_ensemble)
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  else:
150
+ self.model = TabPFNClassifier(device=actual_device)
 
 
151
 
152
+ # Fit model
153
+ self.model.fit(X, y)
 
 
 
154
 
155
  self.is_fitted = True
156
  self.fit_time = time.time() - start_time
code/runners/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Experiment Runners Package
3
+ ===========================
4
+
5
+ Tools for executing benchmarking experiments.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ __all__ = ['run_experiment', 'run_batch']
code/runners/run_baselines.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Baseline Models Batch Runner
3
+ ==============================
4
+
5
+ Run all baseline models (XGBoost, CatBoost, LightGBM) on all or specific datasets.
6
+
7
+ Usage:
8
+ # Run on ALL datasets
9
+ py -3.12 -m runners.run_baselines
10
+
11
+ # Run on specific datasets
12
+ py -3.12 -m runners.run_baselines --dataset analcatdata_authorship diabetes
13
+
14
+ Author: UW MSIM Team
15
+ Date: April 2026
16
+ """
17
+
18
+ import argparse
19
+ import sys
20
+ from pathlib import Path
21
+
22
+ # Add parent directory to path
23
+ sys.path.insert(0, str(Path(__file__).parent.parent))
24
+
25
+ from runners.run_batch import main as run_batch_main
26
+
27
+
28
+ BASELINE_MODELS = ['xgboost', 'catboost', 'lightgbm']
29
+
30
+
31
+ def main():
32
+ """Run all baseline models on all or specific datasets."""
33
+ parser = argparse.ArgumentParser(description='Run baseline models')
34
+ parser.add_argument('--dataset', nargs='*', default=None,
35
+ help='Specific dataset(s) to run (e.g., --dataset analcatdata_authorship diabetes)')
36
+
37
+ args = parser.parse_args()
38
+
39
+ # Build sys.argv for run_batch
40
+ batch_args = ['run_baselines', '--model-filter', *BASELINE_MODELS]
41
+
42
+ if args.dataset:
43
+ batch_args.extend(['--dataset-filter', *args.dataset])
44
+
45
+ sys.argv = batch_args
46
+ run_batch_main()
47
+
48
+
49
+ if __name__ == '__main__':
50
+ main()
code/runners/run_batch.py ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Batch Experiment Runner
3
+ ========================
4
+
5
+ Run multiple models on multiple datasets.
6
+
7
+ Usage:
8
+ python -m runners.run_batch \
9
+ --datasets config/datasets.yaml \
10
+ --models config/models.yaml
11
+
12
+ Author: UW MSIM Team
13
+ Date: April 2026
14
+ """
15
+
16
+ import argparse
17
+ import yaml
18
+ import logging
19
+ import sys
20
+ import os
21
+ import json
22
+ import time
23
+ from pathlib import Path
24
+ from typing import List, Dict, Optional
25
+
26
+ # Add parent directory to path
27
+ sys.path.insert(0, str(Path(__file__).parent.parent))
28
+
29
+ from runners.run_experiment import run_single_experiment, get_model
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ def get_dataset_list(datasets_config: dict, dataset_dir: str = None) -> List[str]:
35
+ """
36
+ Get list of available dataset names from the download directory.
37
+
38
+ Parameters
39
+ ----------
40
+ datasets_config : dict
41
+ Datasets YAML configuration
42
+ dataset_dir : str
43
+ Directory containing downloaded datasets
44
+
45
+ Returns
46
+ -------
47
+ datasets : list of str
48
+ List of dataset names
49
+ """
50
+ datasets = []
51
+
52
+ if dataset_dir is None:
53
+ dataset_dir = str(Path(__file__).parent.parent.parent / 'datasets')
54
+
55
+ if os.path.isdir(dataset_dir):
56
+ # Find all *_X.csv files and extract dataset names
57
+ for f in sorted(os.listdir(dataset_dir)):
58
+ if f.endswith('_X.csv'):
59
+ name = f[:-6] # Remove '_X.csv'
60
+ # Verify y file also exists
61
+ y_file = os.path.join(dataset_dir, f"{name}_y.csv")
62
+ if os.path.exists(y_file):
63
+ datasets.append(name)
64
+
65
+ logger.info(f"Found {len(datasets)} datasets in {dataset_dir}")
66
+ else:
67
+ logger.warning(f"Dataset directory not found: {dataset_dir}")
68
+
69
+ return datasets
70
+
71
+
72
+ def get_model_list(models_config: dict) -> List[str]:
73
+ """
74
+ Get list of enabled model names from configuration.
75
+
76
+ Parameters
77
+ ----------
78
+ models_config : dict
79
+ Models YAML configuration
80
+
81
+ Returns
82
+ -------
83
+ models : list of str
84
+ List of enabled model names
85
+ """
86
+ models = []
87
+
88
+ for model_entry in models_config.get('models', []):
89
+ if model_entry.get('enabled', True):
90
+ models.append(model_entry['name'])
91
+
92
+ return models
93
+
94
+
95
+ def run_batch_experiments(
96
+ datasets: List[str],
97
+ models: List[str],
98
+ experiment_config: dict,
99
+ output_dir: str = '../results/raw',
100
+ skip_existing: bool = True
101
+ ) -> dict:
102
+ """
103
+ Run experiments for all dataset Γ— model combinations.
104
+
105
+ Parameters
106
+ ----------
107
+ datasets : list of str
108
+ Dataset names
109
+ models : list of str
110
+ Model names
111
+ experiment_config : dict
112
+ Experiment configuration (n_folds, random_state, etc.)
113
+ output_dir : str
114
+ Where to save results
115
+ skip_existing : bool
116
+ If True, skip experiments that already have result files
117
+
118
+ Returns
119
+ -------
120
+ summary : dict
121
+ Batch run summary with successes and failures
122
+ """
123
+ total_experiments = len(datasets) * len(models)
124
+ logger.info(f"\n{'='*60}")
125
+ logger.info(f"BATCH RUN: {len(datasets)} datasets Γ— {len(models)} models = {total_experiments} experiments")
126
+ logger.info(f"{'='*60}\n")
127
+
128
+ summary = {
129
+ 'total': total_experiments,
130
+ 'completed': 0,
131
+ 'skipped': 0,
132
+ 'failed': 0,
133
+ 'results': [],
134
+ 'errors': []
135
+ }
136
+
137
+ batch_start_time = time.time()
138
+
139
+ for i, dataset_name in enumerate(datasets):
140
+ for j, model_name in enumerate(models):
141
+ experiment_num = i * len(models) + j + 1
142
+ output_file = os.path.join(output_dir, f"{dataset_name}_{model_name}.json")
143
+
144
+ # Skip existing results
145
+ if skip_existing and os.path.exists(output_file):
146
+ logger.info(
147
+ f"[{experiment_num}/{total_experiments}] "
148
+ f"SKIP {model_name} on {dataset_name} (result exists)"
149
+ )
150
+ summary['skipped'] += 1
151
+ continue
152
+
153
+ logger.info(
154
+ f"\n[{experiment_num}/{total_experiments}] "
155
+ f"Running {model_name} on {dataset_name}..."
156
+ )
157
+
158
+ try:
159
+ result = run_single_experiment(
160
+ dataset_name=dataset_name,
161
+ model_name=model_name,
162
+ config=experiment_config,
163
+ output_dir=output_dir
164
+ )
165
+ summary['completed'] += 1
166
+ summary['results'].append({
167
+ 'dataset': dataset_name,
168
+ 'model': model_name,
169
+ 'status': 'success'
170
+ })
171
+
172
+ except Exception as e:
173
+ logger.error(f"FAILED: {model_name} on {dataset_name}: {e}")
174
+ summary['failed'] += 1
175
+ summary['errors'].append({
176
+ 'dataset': dataset_name,
177
+ 'model': model_name,
178
+ 'error': str(e)
179
+ })
180
+
181
+ batch_elapsed = time.time() - batch_start_time
182
+
183
+ # Print summary
184
+ logger.info(f"\n{'='*60}")
185
+ logger.info(f"BATCH RUN COMPLETE")
186
+ logger.info(f"{'='*60}")
187
+ logger.info(f" Total experiments: {summary['total']}")
188
+ logger.info(f" Completed: {summary['completed']}")
189
+ logger.info(f" Skipped: {summary['skipped']}")
190
+ logger.info(f" Failed: {summary['failed']}")
191
+ logger.info(f" Total time: {batch_elapsed / 3600:.2f} hours")
192
+ logger.info(f"{'='*60}\n")
193
+
194
+ # Save batch summary
195
+ os.makedirs(output_dir, exist_ok=True)
196
+ summary_file = os.path.join(output_dir, '_batch_summary.json')
197
+ summary['elapsed_hours'] = batch_elapsed / 3600
198
+ with open(summary_file, 'w') as f:
199
+ json.dump(summary, f, indent=2)
200
+ logger.info(f"Batch summary saved to {summary_file}")
201
+
202
+ return summary
203
+
204
+
205
+ def main():
206
+ """Entry point for batch runner."""
207
+ # Setup logging
208
+ logging.basicConfig(
209
+ level=logging.INFO,
210
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
211
+ )
212
+
213
+ # Parse arguments
214
+ parser = argparse.ArgumentParser(description='Run batch benchmarking experiments')
215
+ parser.add_argument('--datasets', default='config/datasets.yaml',
216
+ help='Datasets config file')
217
+ parser.add_argument('--models', default='config/models.yaml',
218
+ help='Models config file')
219
+ parser.add_argument('--config', default='config/experiments.yaml',
220
+ help='Experiment config file')
221
+ parser.add_argument('--output-dir', default='../results/raw',
222
+ help='Output directory')
223
+ parser.add_argument('--dataset-dir', default=None,
224
+ help='Directory containing downloaded datasets')
225
+ parser.add_argument('--no-skip', action='store_true',
226
+ help='Re-run experiments even if results exist')
227
+ parser.add_argument('--model-filter', nargs='*', default=None,
228
+ help='Only run specific models (e.g., --model-filter sap-rpt1-hf xgboost)')
229
+ parser.add_argument('--dataset-filter', nargs='*', default=None,
230
+ help='Only run specific datasets')
231
+
232
+ args = parser.parse_args()
233
+
234
+ # Load configs
235
+ if os.path.exists(args.datasets):
236
+ with open(args.datasets) as f:
237
+ datasets_config = yaml.safe_load(f)
238
+ else:
239
+ datasets_config = {}
240
+
241
+ if os.path.exists(args.models):
242
+ with open(args.models) as f:
243
+ models_config = yaml.safe_load(f)
244
+ else:
245
+ models_config = {}
246
+
247
+ if os.path.exists(args.config):
248
+ with open(args.config) as f:
249
+ experiment_config = yaml.safe_load(f)
250
+ else:
251
+ experiment_config = {
252
+ 'n_folds': 10,
253
+ 'random_state': 42,
254
+ 'cost_per_hour': 0.90,
255
+ 'gpu_type': 'H200'
256
+ }
257
+
258
+ # Get dataset and model lists
259
+ dataset_list = args.dataset_filter or get_dataset_list(datasets_config, args.dataset_dir)
260
+ model_list = args.model_filter or get_model_list(models_config)
261
+
262
+ if not dataset_list:
263
+ print("[ERROR] No datasets found in the datasets directory.")
264
+ sys.exit(1)
265
+
266
+ if not model_list:
267
+ print("[ERROR] No models enabled in config. Check config/models.yaml")
268
+ sys.exit(1)
269
+
270
+ print(f"\n[INFO] Datasets ({len(dataset_list)}): {dataset_list[:5]}{'...' if len(dataset_list) > 5 else ''}")
271
+ print(f"[INFO] Models ({len(model_list)}): {model_list}")
272
+
273
+ # Add dataset_dir to config for run_experiment to use
274
+ experiment_config['dataset_dir'] = args.dataset_dir if args.dataset_dir else str(Path(__file__).parent.parent.parent / 'datasets')
275
+
276
+ # Run batch
277
+ summary = run_batch_experiments(
278
+ datasets=dataset_list,
279
+ models=model_list,
280
+ experiment_config=experiment_config,
281
+ output_dir=args.output_dir,
282
+ skip_existing=not args.no_skip
283
+ )
284
+
285
+ print(f"\n[SUCCESS] Batch complete! {summary['completed']} succeeded, {summary['failed']} failed")
286
+
287
+
288
+ if __name__ == "__main__":
289
+ main()
code/runners/run_experiment.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Single Experiment Runner
3
+ =========================
4
+
5
+ Run a single model on a single dataset.
6
+
7
+ Usage:
8
+ python -m runners.run_experiment --dataset adult --model sap-rpt1
9
+
10
+ Author: UW MSIM Team
11
+ Date: November 2025
12
+ """
13
+
14
+ import argparse
15
+ import json
16
+ import yaml
17
+ import logging
18
+ import sys
19
+ import os
20
+ from pathlib import Path
21
+
22
+ # Add parent directory to path
23
+ sys.path.insert(0, str(Path(__file__).parent.parent))
24
+
25
+ from models import *
26
+ from datasets.preprocessors import load_dataset
27
+ from datasets.dataset_catalog import DatasetCatalog
28
+ from evaluation import run_cross_validation, ComputeTracker
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ def get_model(model_name: str, task_type: str, config: dict):
34
+ """
35
+ Initialize model by name.
36
+
37
+ Parameters
38
+ ----------
39
+ model_name : str
40
+ Model identifier
41
+ task_type : str
42
+ 'classification' or 'regression'
43
+ config : dict
44
+ Model configuration
45
+
46
+ Returns
47
+ -------
48
+ model : BaseModelWrapper
49
+ Initialized model
50
+ """
51
+ model_map = {
52
+ 'sap-rpt1': SAPRPT1Wrapper,
53
+ 'sap-rpt1-small': lambda **kwargs: SAPRPT1Wrapper(model_size='small', **kwargs),
54
+ 'sap-rpt1-large': lambda **kwargs: SAPRPT1Wrapper(model_size='large', **kwargs),
55
+ 'sap-rpt1-hf': SAPRPT1HFWrapper,
56
+ 'tabpfn': TabPFNWrapper,
57
+ 'tabicl': TabICLWrapper,
58
+ 'autogluon': AutoGluonWrapper,
59
+ 'xgboost': XGBoostWrapper,
60
+ 'catboost': CatBoostWrapper,
61
+ 'lightgbm': LightGBMWrapper
62
+ }
63
+
64
+ if model_name not in model_map:
65
+ raise ValueError(f"Unknown model: {model_name}. Choose from {list(model_map.keys())}")
66
+
67
+ model_class = model_map[model_name]
68
+
69
+ # Get specific parameters for this model
70
+ model_config_key = model_name.replace('-', '_')
71
+ # Special handling for size variants like sap-rpt1-small -> sap_rpt1
72
+ if model_name.startswith('sap-rpt1-') and model_name not in ['sap-rpt1-hf']:
73
+ model_config_key = 'sap_rpt1'
74
+
75
+ model_params = config.get('model_params', {}).get(model_config_key, {})
76
+
77
+ model = model_class(task_type=task_type, **model_params)
78
+
79
+ logger.info(f"Initialized {model_name} for {task_type}")
80
+
81
+ return model
82
+
83
+
84
+ def run_single_experiment(
85
+ dataset_name: str,
86
+ model_name: str,
87
+ config: dict,
88
+ output_dir: str = '../results/raw'
89
+ ) -> dict:
90
+ """
91
+ Run experiment on single dataset with single model.
92
+
93
+ Parameters
94
+ ----------
95
+ dataset_name : str
96
+ Dataset name
97
+ model_name : str
98
+ Model name
99
+ config : dict
100
+ Experiment configuration
101
+ output_dir : str
102
+ Where to save results
103
+
104
+ Returns
105
+ -------
106
+ summary : dict
107
+ Experiment results
108
+ """
109
+ logger.info(f"\n{'='*60}")
110
+ logger.info(f"Experiment: {model_name} on {dataset_name}")
111
+ logger.info(f"{'='*60}\n")
112
+
113
+ # Create output directory
114
+ os.makedirs(output_dir, exist_ok=True)
115
+
116
+ # Start compute tracking
117
+ tracker = ComputeTracker(
118
+ cost_per_hour=config.get('cost_per_hour', 0.90),
119
+ gpu_type=config.get('gpu_type', 'H200')
120
+ )
121
+ tracker.start()
122
+
123
+ try:
124
+ # Load dataset
125
+ logger.info("Loading dataset...")
126
+ default_dataset_dir = str(Path(__file__).parent.parent.parent / 'datasets')
127
+ dataset_dir = config.get('dataset_dir', default_dataset_dir)
128
+ dataset_path = config.get('dataset_path', None)
129
+
130
+ if dataset_path and os.path.exists(dataset_path):
131
+ # Explicit path provided
132
+ X, y, task_type = load_dataset(dataset_path)
133
+ elif os.path.isdir(dataset_dir):
134
+ # Search for dataset files in the download directory
135
+ X_file = None
136
+ y_file = None
137
+ for f in os.listdir(dataset_dir):
138
+ fname_lower = f.lower()
139
+ dname_lower = dataset_name.lower()
140
+ if fname_lower == f"{dname_lower}_x.csv" or (fname_lower.endswith('_x.csv') and dname_lower in fname_lower):
141
+ X_file = os.path.join(dataset_dir, f)
142
+ if fname_lower == f"{dname_lower}_y.csv" or (fname_lower.endswith('_y.csv') and dname_lower in fname_lower):
143
+ y_file = os.path.join(dataset_dir, f)
144
+
145
+ if X_file and y_file:
146
+ import pandas as pd_load
147
+ X = pd_load.read_csv(X_file)
148
+ y = pd_load.read_csv(y_file).iloc[:, 0]
149
+ # Determine task type
150
+ if y.dtype == 'object' or len(y.unique()) < 20:
151
+ task_type = 'classification'
152
+ else:
153
+ task_type = 'regression'
154
+ logger.info(f"Loaded {dataset_name}: {X.shape[0]} samples, {X.shape[1]} features, task={task_type}")
155
+ else:
156
+ # Fallback: try as a single CSV file
157
+ csv_path = os.path.join(dataset_dir, f"{dataset_name}.csv")
158
+ if os.path.exists(csv_path):
159
+ X, y, task_type = load_dataset(csv_path)
160
+ else:
161
+ raise FileNotFoundError(
162
+ f"Dataset '{dataset_name}' not found in {dataset_dir}.\n"
163
+ f"Available files: {os.listdir(dataset_dir)[:10]}..."
164
+ )
165
+ else:
166
+ raise FileNotFoundError(
167
+ f"Dataset directory not found: {dataset_dir}"
168
+ )
169
+
170
+ # Initialize model
171
+ model = get_model(model_name, task_type, config)
172
+
173
+ # Run cross-validation
174
+ fold_results = run_cross_validation(
175
+ model=model,
176
+ X=X,
177
+ y=y,
178
+ task_type=task_type,
179
+ n_folds=config.get('n_folds', 10),
180
+ random_state=config.get('random_state', 42)
181
+ )
182
+
183
+ # Stop tracking
184
+ compute_summary = tracker.stop()
185
+
186
+ # Aggregate results
187
+ import pandas as pd
188
+ results_df = pd.DataFrame(fold_results)
189
+
190
+ summary = {
191
+ 'dataset': dataset_name,
192
+ 'model': model_name,
193
+ 'task_type': task_type,
194
+ 'n_samples': len(X),
195
+ 'n_features': X.shape[1],
196
+ 'n_folds': config.get('n_folds', 10),
197
+ 'mean_metrics': results_df.mean().to_dict(),
198
+ 'std_metrics': results_df.std().to_dict(),
199
+ 'fold_results': fold_results,
200
+ 'compute': compute_summary
201
+ }
202
+
203
+ # Save results
204
+ output_file = os.path.join(output_dir, f"{dataset_name}_{model_name}.json")
205
+ with open(output_file, 'w') as f:
206
+ json.dump(summary, f, indent=2)
207
+
208
+ logger.info(f"\n[SUCCESS] Results saved to {output_file}")
209
+
210
+ # Print summary
211
+ primary_metric = 'roc_auc' if task_type == 'classification' else 'r2'
212
+ if primary_metric in summary['mean_metrics']:
213
+ mean_val = summary['mean_metrics'][primary_metric]
214
+ std_val = summary['std_metrics'][primary_metric]
215
+ logger.info(f"\nPrimary Metric ({primary_metric}): {mean_val:.4f} Β± {std_val:.4f}")
216
+
217
+ return summary
218
+
219
+ except Exception as e:
220
+ logger.error(f"Experiment failed: {e}", exc_info=True)
221
+ raise
222
+
223
+
224
+ if __name__ == "__main__":
225
+ # Setup logging
226
+ logging.basicConfig(
227
+ level=logging.INFO,
228
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
229
+ )
230
+
231
+ # Parse arguments
232
+ parser = argparse.ArgumentParser(description='Run single benchmarking experiment')
233
+ parser.add_argument('--dataset', required=True, help='Dataset name')
234
+ parser.add_argument('--model', required=True, help='Model name')
235
+ parser.add_argument('--config', default='../config/experiments.yaml', help='Config file')
236
+ parser.add_argument('--output-dir', default='../results/raw', help='Output directory')
237
+
238
+ args = parser.parse_args()
239
+
240
+ # Load config
241
+ if os.path.exists(args.config):
242
+ with open(args.config) as f:
243
+ config = yaml.safe_load(f)
244
+ else:
245
+ config = {
246
+ 'n_folds': 10,
247
+ 'random_state': 42,
248
+ 'cost_per_hour': 0.90,
249
+ 'gpu_type': 'H200'
250
+ }
251
+
252
+ # Run experiment
253
+ results = run_single_experiment(
254
+ dataset_name=args.dataset,
255
+ model_name=args.model,
256
+ config=config,
257
+ output_dir=args.output_dir
258
+ )
259
+
260
+ print("\n[SUCCESS] Experiment complete!")
{webapp β†’ code}/sap_rpt1.egg-info/PKG-INFO RENAMED
File without changes
code/sap_rpt1.egg-info/SOURCES.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ README.md
2
+ setup.py
3
+ code/analysis/__init__.py
4
+ code/analysis/aggregate_results.py
5
+ code/evaluation/__init__.py
6
+ code/evaluation/compute_tracker.py
7
+ code/evaluation/cross_validation.py
8
+ code/evaluation/metrics.py
9
+ code/evaluation/statistical_tests.py
10
+ code/models/__init__.py
11
+ code/models/autogluon_wrapper.py
12
+ code/models/base_wrapper.py
13
+ code/models/baseline_wrappers.py
14
+ code/models/sap_rpt1_hf_wrapper.py
15
+ code/models/sap_rpt1_wrapper.py
16
+ code/models/tabicl_wrapper.py
17
+ code/models/tabpfn_wrapper.py
18
+ code/runners/__init__.py
19
+ code/runners/run_baselines.py
20
+ code/runners/run_batch.py
21
+ code/runners/run_experiment.py
22
+ code/sap_rpt1.egg-info/PKG-INFO
23
+ code/sap_rpt1.egg-info/SOURCES.txt
24
+ code/sap_rpt1.egg-info/dependency_links.txt
25
+ code/sap_rpt1.egg-info/requires.txt
26
+ code/sap_rpt1.egg-info/top_level.txt
27
+ code/utils/__init__.py
28
+ code/utils/logging_utils.py
{webapp β†’ code}/sap_rpt1.egg-info/dependency_links.txt RENAMED
File without changes
{webapp β†’ code}/sap_rpt1.egg-info/requires.txt RENAMED
File without changes
code/sap_rpt1.egg-info/top_level.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ analysis
2
+ evaluation
3
+ models
4
+ runners
5
+ utils
code/utils/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utilities Package
3
+ =================
4
+
5
+ Logging, result export, and helper functions.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ __all__ = []
code/utils/logging_utils.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Logging Utilities
3
+ =================
4
+
5
+ Structured logging for experiments.
6
+
7
+ Author: UW MSIM Team
8
+ Date: November 2025
9
+ """
10
+
11
+ import logging
12
+ import sys
13
+ from pathlib import Path
14
+
15
+
16
+ def setup_logger(
17
+ name: str,
18
+ log_file: str = None,
19
+ level: int = logging.INFO,
20
+ format_string: str = None
21
+ ) -> logging.Logger:
22
+ """
23
+ Setup logger with file and console handlers.
24
+
25
+ Parameters
26
+ ----------
27
+ name : str
28
+ Logger name
29
+ log_file : str, optional
30
+ Log file path
31
+ level : int
32
+ Logging level
33
+ format_string : str, optional
34
+ Custom format string
35
+
36
+ Returns
37
+ -------
38
+ logger : logging.Logger
39
+ Configured logger
40
+ """
41
+ if format_string is None:
42
+ format_string = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
43
+
44
+ # Create logger
45
+ logger = logging.getLogger(name)
46
+ logger.setLevel(level)
47
+ logger.handlers = [] # Clear existing handlers
48
+
49
+ # Console handler
50
+ console_handler = logging.StreamHandler(sys.stdout)
51
+ console_handler.setLevel(level)
52
+ console_handler.setFormatter(logging.Formatter(format_string))
53
+ logger.addHandler(console_handler)
54
+
55
+ # File handler (if specified)
56
+ if log_file:
57
+ Path(log_file).parent.mkdir(parents=True, exist_ok=True)
58
+ file_handler = logging.FileHandler(log_file)
59
+ file_handler.setLevel(level)
60
+ file_handler.setFormatter(logging.Formatter(format_string))
61
+ logger.addHandler(file_handler)
62
+
63
+ return logger
requirements.txt CHANGED
@@ -35,3 +35,4 @@ torcheval==0.0.7
35
 
36
  # SAP RPT-1 OSS model (pinned to release v1.1.2)
37
  sap-rpt-oss @ git+https://github.com/SAP-samples/sap-rpt-1-oss.git@v1.1.2
 
 
35
 
36
  # SAP RPT-1 OSS model (pinned to release v1.1.2)
37
  sap-rpt-oss @ git+https://github.com/SAP-samples/sap-rpt-1-oss.git@v1.1.2
38
+
setup.py CHANGED
@@ -3,8 +3,8 @@ from setuptools import setup, find_packages
3
  setup(
4
  name="sap-rpt1",
5
  version="0.1.0",
6
- package_dir={"": "webapp"},
7
- packages=find_packages(where="webapp"),
8
  install_requires=[
9
  "numpy>=1.26.4",
10
  "pandas>=2.2.3",
 
3
  setup(
4
  name="sap-rpt1",
5
  version="0.1.0",
6
+ package_dir={"": "code"},
7
+ packages=find_packages(where="code"),
8
  install_requires=[
9
  "numpy>=1.26.4",
10
  "pandas>=2.2.3",
webapp/benchmark.py CHANGED
@@ -16,21 +16,10 @@ from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
16
 
17
  warnings.filterwarnings("ignore")
18
 
19
- # Accept TabPFN license non-interactively β€” must be set before any tabpfn import.
20
- # Cover all env var names used across different TabPFN versions.
21
- os.environ.setdefault("TABPFN_ACCEPT_LICENSE", "1")
22
- os.environ.setdefault("TABPFN_LICENSE", "accept")
23
- os.environ.setdefault("TABPFN_ACCEPT_TERMS", "1")
24
- os.environ.setdefault("TABPFN_LICENSE_ACCEPTED", "1")
25
- os.environ.setdefault("AGREE_TABPFN_LICENSE", "1")
26
-
27
- # Flexible imports to support both HF Space (root) and local execution (inside webapp)
28
- try:
29
- from webapp.models.tabpfn_wrapper import TabPFNWrapper
30
- except (ImportError, ModuleNotFoundError):
31
- from models.tabpfn_wrapper import TabPFNWrapper
32
 
33
- N_FOLDS = int(os.getenv("N_FOLDS", "3"))
34
  RAND = int(os.getenv("RANDOM_STATE", "42"))
35
  HF_TOKEN = os.getenv("HUGGING_FACE_HUB_TOKEN", "")
36
 
@@ -65,20 +54,15 @@ def _cat(task):
65
  def _tabpfn(task):
66
  if task != "classification":
67
  raise ValueError("TabPFN only supports classification tasks")
68
- # TabPFNWrapper uses a class-level _shared_classifier so weights are only
69
- # loaded once per process regardless of how many instances are created.
70
  return TabPFNWrapper(task_type=task, random_state=RAND)
71
 
72
 
73
-
74
  class _SAPModel:
75
  """
76
  Tries the real SAP RPT-1 OSS via HuggingFace; falls back to k-NN simulator
77
  if the package is not installed or authentication fails.
78
  """
79
- # Class-level cache to avoid reloading Transformer weights on every fold
80
- _shared_model = None
81
-
82
  def __init__(self, task):
83
  self.task = task
84
  self._real = False
@@ -86,19 +70,14 @@ class _SAPModel:
86
 
87
  if HF_TOKEN:
88
  try:
89
- # Reuse shared model if available
90
- if _SAPModel._shared_model is not None and _SAPModel._shared_model.task == task:
91
- self._model = _SAPModel._shared_model._model
92
- self._real = True
 
93
  else:
94
- from sap_rpt_oss import SAP_RPT_OSS_Classifier, SAP_RPT_OSS_Regressor
95
- if task == "classification":
96
- self._model = SAP_RPT_OSS_Classifier(max_context_size=2048, bagging=1)
97
- else:
98
- self._model = SAP_RPT_OSS_Regressor(max_context_size=2048, bagging=1)
99
- self._real = True
100
- # Store in class-level cache
101
- _SAPModel._shared_model = self
102
  except Exception:
103
  self._init_sim()
104
  else:
@@ -123,23 +102,12 @@ class _SAPModel:
123
  return self
124
 
125
  def predict(self, X):
126
- if self._real and len(X) == 1:
127
- # SAP RPT-1 OSS crashes on single-row input (np.concatenate on 0-dim arrays).
128
- # Duplicate the row to form a 2-row batch, then return only the first result.
129
- import pandas as pd
130
- X_pad = pd.concat([X, X], ignore_index=True) if hasattr(X, 'iloc') else np.vstack([X, X])
131
- preds = self._model.predict(X_pad)[:1]
132
- else:
133
- preds = self._model.predict(X)
134
  if not self._real and self.task == "classification":
135
  preds = self._le.inverse_transform(preds)
136
  return preds
137
 
138
  def predict_proba(self, X):
139
- if self._real and len(X) == 1:
140
- import pandas as pd
141
- X_pad = pd.concat([X, X], ignore_index=True) if hasattr(X, 'iloc') else np.vstack([X, X])
142
- return self._model.predict_proba(X_pad)[:1]
143
  return self._model.predict_proba(X)
144
 
145
  @property
@@ -227,17 +195,14 @@ def _run_cv(builder, X, y, task):
227
  else:
228
  splits = list(KFold(N_FOLDS, shuffle=True, random_state=RAND).split(X))
229
 
230
- # Pre-fit encoders on the full dataset to ensure consistent feature space
231
- X_full_p, global_encoders = _prep(X)
232
-
233
  fold_results = []
234
  for tr_idx, val_idx in splits:
235
  Xtr, Xval = X.iloc[tr_idx], X.iloc[val_idx]
236
  ytr, yval = y.iloc[tr_idx], y.iloc[val_idx]
237
 
238
- # Apply the global encoders to both splits
239
- Xtr_p, _ = _prep(Xtr, encoders=global_encoders)
240
- Xval_p, _ = _prep(Xval, encoders=global_encoders)
241
 
242
  model = builder(task)
243
  if task == "classification":
@@ -356,25 +321,16 @@ def _statistical_analysis(results: dict, task: str) -> dict:
356
  return {}
357
 
358
  # Extract scores per fold for each model
359
- # Only include models that have a consistent number of folds
360
- temp_matrix = {}
361
- max_folds = 0
362
  for name in model_names:
363
  folds = results[name].get("folds", [])
364
- if not folds: continue
365
  scores = [f.get(primary, 0) for f in folds]
366
- temp_matrix[name] = scores
367
- max_folds = max(max_folds, len(scores))
368
 
369
- if max_folds == 0: return {}
370
-
371
- # Final list of models that have the full fold count
372
- valid_names = [n for n, s in temp_matrix.items() if len(s) == max_folds]
373
- if len(valid_names) < 2: return {}
374
-
375
- matrix = np.array([temp_matrix[n] for n in valid_names]).T # Shape: (n_folds, n_models)
376
- n_folds = max_folds
377
- model_names = valid_names # Update model_names to match matrix columns
378
 
379
  # Calculate ranks for each fold (row)
380
  # Higher score = lower rank (1 is best). Using method='min' for competition ranking (ties get same best rank)
@@ -440,21 +396,12 @@ def run_benchmark(df: pd.DataFrame, target_col: str) -> dict:
440
  dict with keys: dataset_info, task, results, ensemble_info, recommendation
441
  """
442
  try:
443
- from webapp.ensemble import select_top_models, run_voting_ensemble, run_stacking_ensemble, SKLEARN_SAFE
444
- except (ImportError, ModuleNotFoundError):
445
  from ensemble import select_top_models, run_voting_ensemble, run_stacking_ensemble, SKLEARN_SAFE
 
 
446
 
447
  y_raw = df[target_col].copy()
448
  X = df.drop(columns=[target_col]).copy()
449
-
450
- # Subsample for benchmarking if the dataset is too large (>1000 rows)
451
- # This prevents the "decades of time" issue on Hugging Face CPU spaces.
452
- if len(df) > 1000:
453
- print(f"Subsampling dataset from {len(df)} to 1000 rows for benchmarking speed.")
454
- df = df.sample(n=1000, random_state=RAND)
455
- y_raw = df[target_col].copy()
456
- X = df.drop(columns=[target_col]).copy()
457
-
458
  task = infer_task(y_raw)
459
  y, _ = _encode_target(y_raw, task)
460
 
 
16
 
17
  warnings.filterwarnings("ignore")
18
 
19
+ # Allow importing model wrappers from the code directory
20
+ sys.path.insert(0, str(Path(__file__).parent.parent / "code"))
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ N_FOLDS = int(os.getenv("N_FOLDS", "5"))
23
  RAND = int(os.getenv("RANDOM_STATE", "42"))
24
  HF_TOKEN = os.getenv("HUGGING_FACE_HUB_TOKEN", "")
25
 
 
54
  def _tabpfn(task):
55
  if task != "classification":
56
  raise ValueError("TabPFN only supports classification tasks")
57
+ from models.tabpfn_wrapper import TabPFNWrapper
 
58
  return TabPFNWrapper(task_type=task, random_state=RAND)
59
 
60
 
 
61
  class _SAPModel:
62
  """
63
  Tries the real SAP RPT-1 OSS via HuggingFace; falls back to k-NN simulator
64
  if the package is not installed or authentication fails.
65
  """
 
 
 
66
  def __init__(self, task):
67
  self.task = task
68
  self._real = False
 
70
 
71
  if HF_TOKEN:
72
  try:
73
+ from huggingface_hub import login
74
+ login(token=HF_TOKEN, add_to_git_credential=False)
75
+ from sap_rpt_oss import SAP_RPT_OSS_Classifier, SAP_RPT_OSS_Regressor
76
+ if task == "classification":
77
+ self._model = SAP_RPT_OSS_Classifier(max_context_size=2048, bagging=1)
78
  else:
79
+ self._model = SAP_RPT_OSS_Regressor(max_context_size=2048, bagging=1)
80
+ self._real = True
 
 
 
 
 
 
81
  except Exception:
82
  self._init_sim()
83
  else:
 
102
  return self
103
 
104
  def predict(self, X):
105
+ preds = self._model.predict(X)
 
 
 
 
 
 
 
106
  if not self._real and self.task == "classification":
107
  preds = self._le.inverse_transform(preds)
108
  return preds
109
 
110
  def predict_proba(self, X):
 
 
 
 
111
  return self._model.predict_proba(X)
112
 
113
  @property
 
195
  else:
196
  splits = list(KFold(N_FOLDS, shuffle=True, random_state=RAND).split(X))
197
 
 
 
 
198
  fold_results = []
199
  for tr_idx, val_idx in splits:
200
  Xtr, Xval = X.iloc[tr_idx], X.iloc[val_idx]
201
  ytr, yval = y.iloc[tr_idx], y.iloc[val_idx]
202
 
203
+ # Capture encoders from training set and apply to validation set
204
+ Xtr_p, encoders = _prep(Xtr)
205
+ Xval_p, _ = _prep(Xval, encoders=encoders)
206
 
207
  model = builder(task)
208
  if task == "classification":
 
321
  return {}
322
 
323
  # Extract scores per fold for each model
324
+ # Matrix: rows = folds, cols = models
325
+ matrix = []
326
+ n_folds = 0
327
  for name in model_names:
328
  folds = results[name].get("folds", [])
329
+ n_folds = len(folds)
330
  scores = [f.get(primary, 0) for f in folds]
331
+ matrix.append(scores)
 
332
 
333
+ matrix = np.array(matrix).T # Now (n_folds, n_models)
 
 
 
 
 
 
 
 
334
 
335
  # Calculate ranks for each fold (row)
336
  # Higher score = lower rank (1 is best). Using method='min' for competition ranking (ties get same best rank)
 
396
  dict with keys: dataset_info, task, results, ensemble_info, recommendation
397
  """
398
  try:
 
 
399
  from ensemble import select_top_models, run_voting_ensemble, run_stacking_ensemble, SKLEARN_SAFE
400
+ except ImportError:
401
+ from webapp.ensemble import select_top_models, run_voting_ensemble, run_stacking_ensemble, SKLEARN_SAFE
402
 
403
  y_raw = df[target_col].copy()
404
  X = df.drop(columns=[target_col]).copy()
 
 
 
 
 
 
 
 
 
405
  task = infer_task(y_raw)
406
  y, _ = _encode_target(y_raw, task)
407
 
webapp/catboost_info/catboost_training.json CHANGED
@@ -1,204 +1,204 @@
1
  {
2
  "meta":{"test_sets":[],"test_metrics":[],"learn_metrics":[{"best_value":"Min","name":"MultiClass"}],"launch_mode":"Train","parameters":"","iteration_count":200,"learn_sets":["learn"],"name":"experiment"},
3
  "iterations":[
4
- {"learn":[1.091148423],"iteration":0,"passed_time":0.00282132088,"remaining_time":0.5614428552},
5
- {"learn":[1.086418765],"iteration":1,"passed_time":0.004661279676,"remaining_time":0.461466688},
6
- {"learn":[1.0773991],"iteration":2,"passed_time":0.00686823605,"remaining_time":0.4510141673},
7
- {"learn":[1.071672289],"iteration":3,"passed_time":0.009224603804,"remaining_time":0.4520055864},
8
- {"learn":[1.066004714],"iteration":4,"passed_time":0.011783565,"remaining_time":0.4595590352},
9
- {"learn":[1.059330013],"iteration":5,"passed_time":0.01414772569,"remaining_time":0.4574431307},
10
- {"learn":[1.05490226],"iteration":6,"passed_time":0.01652457928,"remaining_time":0.4556062573},
11
- {"learn":[1.048588391],"iteration":7,"passed_time":0.01874668105,"remaining_time":0.4499203453},
12
- {"learn":[1.043833033],"iteration":8,"passed_time":0.02056725855,"remaining_time":0.4364829315},
13
- {"learn":[1.037311438],"iteration":9,"passed_time":0.02246572539,"remaining_time":0.4268487824},
14
- {"learn":[1.031927739],"iteration":10,"passed_time":0.02500469334,"remaining_time":0.4296260947},
15
- {"learn":[1.025841223],"iteration":11,"passed_time":0.0273518553,"remaining_time":0.4285123996},
16
- {"learn":[1.021936274],"iteration":12,"passed_time":0.02974148281,"remaining_time":0.4278197913},
17
- {"learn":[1.016038582],"iteration":13,"passed_time":0.03166456883,"remaining_time":0.4206864144},
18
- {"learn":[1.011831586],"iteration":14,"passed_time":0.03329416411,"remaining_time":0.410628024},
19
- {"learn":[1.007661983],"iteration":15,"passed_time":0.03589234115,"remaining_time":0.4127619232},
20
- {"learn":[1.00331399],"iteration":16,"passed_time":0.03732309974,"remaining_time":0.4017721914},
21
- {"learn":[0.9969175017],"iteration":17,"passed_time":0.03904952284,"remaining_time":0.3948340642},
22
- {"learn":[0.9915381213],"iteration":18,"passed_time":0.04129692366,"remaining_time":0.3934075359},
23
- {"learn":[0.987027199],"iteration":19,"passed_time":0.04352230508,"remaining_time":0.3917007457},
24
- {"learn":[0.9806451898],"iteration":20,"passed_time":0.04767395464,"remaining_time":0.4063637086},
25
- {"learn":[0.97625914],"iteration":21,"passed_time":0.05769974089,"remaining_time":0.4668433581},
26
- {"learn":[0.9684721006],"iteration":22,"passed_time":0.08061496164,"remaining_time":0.6203847048},
27
- {"learn":[0.9650061706],"iteration":23,"passed_time":0.09306077751,"remaining_time":0.6824457017},
28
- {"learn":[0.9574638884],"iteration":24,"passed_time":0.10622083,"remaining_time":0.7435458098},
29
- {"learn":[0.9535340201],"iteration":25,"passed_time":0.1209920735,"remaining_time":0.8097161843},
30
- {"learn":[0.9493774514],"iteration":26,"passed_time":0.1297345247,"remaining_time":0.8312619547},
31
- {"learn":[0.9458850596],"iteration":27,"passed_time":0.1384080506,"remaining_time":0.8502208825},
32
- {"learn":[0.9407835813],"iteration":28,"passed_time":0.147551706,"remaining_time":0.8700462666},
33
- {"learn":[0.9365937962],"iteration":29,"passed_time":0.1543006766,"remaining_time":0.8743705007},
34
- {"learn":[0.9314428367],"iteration":30,"passed_time":0.1587093077,"remaining_time":0.86522171},
35
- {"learn":[0.9270029216],"iteration":31,"passed_time":0.1619613449,"remaining_time":0.8502970607},
36
- {"learn":[0.9234886611],"iteration":32,"passed_time":0.1646294734,"remaining_time":0.8331249109},
37
- {"learn":[0.9183877748],"iteration":33,"passed_time":0.169222928,"remaining_time":0.8262060601},
38
- {"learn":[0.9155318031],"iteration":34,"passed_time":0.1721472039,"remaining_time":0.811551104},
39
- {"learn":[0.9112328302],"iteration":35,"passed_time":0.1750561636,"remaining_time":0.7974780786},
40
- {"learn":[0.90756732],"iteration":36,"passed_time":0.1778744654,"remaining_time":0.7836091314},
41
- {"learn":[0.9006450864],"iteration":37,"passed_time":0.1810274889,"remaining_time":0.7717487683},
42
- {"learn":[0.898315496],"iteration":38,"passed_time":0.1877579839,"remaining_time":0.7751034722},
43
- {"learn":[0.8949441838],"iteration":39,"passed_time":0.1906573888,"remaining_time":0.7626295554},
44
- {"learn":[0.8903109401],"iteration":40,"passed_time":0.1937938245,"remaining_time":0.7515419046},
45
- {"learn":[0.8866011593],"iteration":41,"passed_time":0.1964065181,"remaining_time":0.7388626158},
46
- {"learn":[0.8818539442],"iteration":42,"passed_time":0.200377863,"remaining_time":0.7316121974},
47
- {"learn":[0.8766400926],"iteration":43,"passed_time":0.2023094867,"remaining_time":0.7172790892},
48
- {"learn":[0.8711942711],"iteration":44,"passed_time":0.2046830136,"remaining_time":0.7050192689},
49
- {"learn":[0.8664049339],"iteration":45,"passed_time":0.2074059643,"remaining_time":0.6943590979},
50
- {"learn":[0.8605692297],"iteration":46,"passed_time":0.2099182439,"remaining_time":0.6833508791},
51
- {"learn":[0.855305651],"iteration":47,"passed_time":0.2128794227,"remaining_time":0.6741181719},
52
- {"learn":[0.8498381077],"iteration":48,"passed_time":0.2167459054,"remaining_time":0.6679312594},
53
- {"learn":[0.8457962609],"iteration":49,"passed_time":0.218386666,"remaining_time":0.6551599981},
54
- {"learn":[0.8416413202],"iteration":50,"passed_time":0.2204240023,"remaining_time":0.6439838497},
55
- {"learn":[0.8364743562],"iteration":51,"passed_time":0.2233911129,"remaining_time":0.6358054752},
56
- {"learn":[0.8325194429],"iteration":52,"passed_time":0.2262674652,"remaining_time":0.627572026},
57
- {"learn":[0.8284764993],"iteration":53,"passed_time":0.2291484016,"remaining_time":0.6195493822},
58
- {"learn":[0.8236751265],"iteration":54,"passed_time":0.2311438446,"remaining_time":0.6093792266},
59
- {"learn":[0.8181696307],"iteration":55,"passed_time":0.2329766587,"remaining_time":0.5990828366},
60
- {"learn":[0.814313061],"iteration":56,"passed_time":0.2344071372,"remaining_time":0.588074046},
61
- {"learn":[0.8115976577],"iteration":57,"passed_time":0.2373364472,"remaining_time":0.581065095},
62
- {"learn":[0.807758466],"iteration":58,"passed_time":0.2402929971,"remaining_time":0.5742595354},
63
- {"learn":[0.802321422],"iteration":59,"passed_time":0.2432855194,"remaining_time":0.567666212},
64
- {"learn":[0.798807136],"iteration":60,"passed_time":0.2458100965,"remaining_time":0.5601246461},
65
- {"learn":[0.7948400764],"iteration":61,"passed_time":0.2483936116,"remaining_time":0.5528761033},
66
- {"learn":[0.7916880148],"iteration":62,"passed_time":0.2499576877,"remaining_time":0.5435587812},
67
- {"learn":[0.7873311755],"iteration":63,"passed_time":0.2520703854,"remaining_time":0.5356495691},
68
- {"learn":[0.7827613451],"iteration":64,"passed_time":0.2549412732,"remaining_time":0.5294934135},
69
- {"learn":[0.7786702385],"iteration":65,"passed_time":0.2581479894,"remaining_time":0.5241186452},
70
- {"learn":[0.7764977254],"iteration":66,"passed_time":0.2605647051,"remaining_time":0.5172403848},
71
- {"learn":[0.7730194967],"iteration":67,"passed_time":0.2630132522,"remaining_time":0.5105551367},
72
- {"learn":[0.7696007626],"iteration":68,"passed_time":0.2654128606,"remaining_time":0.5038997788},
73
- {"learn":[0.7642752146],"iteration":69,"passed_time":0.2680231461,"remaining_time":0.4977572714},
74
- {"learn":[0.760253606],"iteration":70,"passed_time":0.2703621365,"remaining_time":0.4912213467},
75
- {"learn":[0.7577785571],"iteration":71,"passed_time":0.2723268734,"remaining_time":0.4841366639},
76
- {"learn":[0.7539434543],"iteration":72,"passed_time":0.2750061922,"remaining_time":0.4784354303},
77
- {"learn":[0.7495444532],"iteration":73,"passed_time":0.2772363226,"remaining_time":0.4720510358},
78
- {"learn":[0.7455923189],"iteration":74,"passed_time":0.2801728829,"remaining_time":0.4669548049},
79
- {"learn":[0.7429488753],"iteration":75,"passed_time":0.2820680153,"remaining_time":0.4602162355},
80
- {"learn":[0.7400940248],"iteration":76,"passed_time":0.2838023389,"remaining_time":0.4533465933},
81
- {"learn":[0.737176055],"iteration":77,"passed_time":0.2862566885,"remaining_time":0.4477348204},
82
- {"learn":[0.7334430947],"iteration":78,"passed_time":0.2886098781,"remaining_time":0.4420480412},
83
- {"learn":[0.7307758227],"iteration":79,"passed_time":0.2907228845,"remaining_time":0.4360843268},
84
- {"learn":[0.7271924097],"iteration":80,"passed_time":0.2926877115,"remaining_time":0.4299979959},
85
- {"learn":[0.7233691229],"iteration":81,"passed_time":0.2951436988,"remaining_time":0.4247189812},
86
- {"learn":[0.7199860815],"iteration":82,"passed_time":0.2976942861,"remaining_time":0.419641343},
87
- {"learn":[0.7166443842],"iteration":83,"passed_time":0.2999935398,"remaining_time":0.4142767931},
88
- {"learn":[0.7120905194],"iteration":84,"passed_time":0.3025034543,"remaining_time":0.4092693794},
89
- {"learn":[0.7080689226],"iteration":85,"passed_time":0.3052517734,"remaining_time":0.4046360717},
90
- {"learn":[0.7049974284],"iteration":86,"passed_time":0.3065849766,"remaining_time":0.398208073},
91
- {"learn":[0.7008658577],"iteration":87,"passed_time":0.3087478548,"remaining_time":0.3929518152},
92
- {"learn":[0.6968041294],"iteration":88,"passed_time":0.3113987764,"remaining_time":0.3883737549},
93
- {"learn":[0.6949067976],"iteration":89,"passed_time":0.314102279,"remaining_time":0.3839027854},
94
- {"learn":[0.6923908515],"iteration":90,"passed_time":0.3160477997,"remaining_time":0.378562749},
95
- {"learn":[0.6874475769],"iteration":91,"passed_time":0.3187214071,"remaining_time":0.3741512171},
96
- {"learn":[0.6834969954],"iteration":92,"passed_time":0.3207574415,"remaining_time":0.3690435079},
97
- {"learn":[0.6797426739],"iteration":93,"passed_time":0.3226379974,"remaining_time":0.3638258268},
98
- {"learn":[0.676311281],"iteration":94,"passed_time":0.3251686663,"remaining_time":0.359396947},
99
- {"learn":[0.6732950825],"iteration":95,"passed_time":0.328981045,"remaining_time":0.3563961321},
100
- {"learn":[0.670343132],"iteration":96,"passed_time":0.3310233733,"remaining_time":0.3514990459},
101
- {"learn":[0.6672527936],"iteration":97,"passed_time":0.3338898708,"remaining_time":0.3475180288},
102
- {"learn":[0.6654513235],"iteration":98,"passed_time":0.3363799535,"remaining_time":0.3431755081},
103
- {"learn":[0.6629430399],"iteration":99,"passed_time":0.3386832141,"remaining_time":0.3386832141},
104
- {"learn":[0.6599425476],"iteration":100,"passed_time":0.3414548313,"remaining_time":0.3346933495},
105
- {"learn":[0.6563456648],"iteration":101,"passed_time":0.3435269652,"remaining_time":0.3300553195},
106
- {"learn":[0.6533420617],"iteration":102,"passed_time":0.3458327628,"remaining_time":0.325687165},
107
- {"learn":[0.6521604983],"iteration":103,"passed_time":0.3474527952,"remaining_time":0.3207256571},
108
- {"learn":[0.6486732019],"iteration":104,"passed_time":0.3493654418,"remaining_time":0.3160925425},
109
- {"learn":[0.6452204016],"iteration":105,"passed_time":0.3512939785,"remaining_time":0.3115248489},
110
- {"learn":[0.6428646774],"iteration":106,"passed_time":0.3530746596,"remaining_time":0.3068779752},
111
- {"learn":[0.6392699247],"iteration":107,"passed_time":0.3555656343,"remaining_time":0.302889244},
112
- {"learn":[0.6357158219],"iteration":108,"passed_time":0.357897057,"remaining_time":0.2987947907},
113
- {"learn":[0.6328221906],"iteration":109,"passed_time":0.360163507,"remaining_time":0.294679233},
114
- {"learn":[0.6295509884],"iteration":110,"passed_time":0.36264645,"remaining_time":0.290770577},
115
- {"learn":[0.6261120005],"iteration":111,"passed_time":0.3645674342,"remaining_time":0.2864458411},
116
- {"learn":[0.6236044192],"iteration":112,"passed_time":0.3665369016,"remaining_time":0.2822009773},
117
- {"learn":[0.6212460917],"iteration":113,"passed_time":0.3679470133,"remaining_time":0.2775740626},
118
- {"learn":[0.6177241089],"iteration":114,"passed_time":0.3701892461,"remaining_time":0.2736181385},
119
- {"learn":[0.6157604351],"iteration":115,"passed_time":0.3723852712,"remaining_time":0.2696582998},
120
- {"learn":[0.6132566809],"iteration":116,"passed_time":0.374601129,"remaining_time":0.2657426813},
121
- {"learn":[0.6104162939],"iteration":117,"passed_time":0.3771927004,"remaining_time":0.2621169613},
122
- {"learn":[0.6079636357],"iteration":118,"passed_time":0.3787314159,"remaining_time":0.2577919721},
123
- {"learn":[0.6063102359],"iteration":119,"passed_time":0.3800805327,"remaining_time":0.2533870218},
124
- {"learn":[0.602804494],"iteration":120,"passed_time":0.3818635245,"remaining_time":0.2493158548},
125
- {"learn":[0.5991211844],"iteration":121,"passed_time":0.3832718363,"remaining_time":0.2450426494},
126
- {"learn":[0.5958434122],"iteration":122,"passed_time":0.3852467789,"remaining_time":0.2411707478},
127
- {"learn":[0.5932912801],"iteration":123,"passed_time":0.3872305242,"remaining_time":0.2373348374},
128
- {"learn":[0.5918961165],"iteration":124,"passed_time":0.3893693878,"remaining_time":0.2336216327},
129
- {"learn":[0.5896874223],"iteration":125,"passed_time":0.3914201661,"remaining_time":0.2298816848},
130
- {"learn":[0.5868596712],"iteration":126,"passed_time":0.3941199966,"remaining_time":0.2265414154},
131
- {"learn":[0.584461876],"iteration":127,"passed_time":0.3958663077,"remaining_time":0.2226747981},
132
- {"learn":[0.5808172852],"iteration":128,"passed_time":0.4007838151,"remaining_time":0.2205864409},
133
- {"learn":[0.5787637725],"iteration":129,"passed_time":0.4068101448,"remaining_time":0.2190516165},
134
- {"learn":[0.5750088728],"iteration":130,"passed_time":0.4146420973,"remaining_time":0.2183992726},
135
- {"learn":[0.5727294917],"iteration":131,"passed_time":0.420835855,"remaining_time":0.2167942283},
136
- {"learn":[0.5707527172],"iteration":132,"passed_time":0.4282958359,"remaining_time":0.2157580527},
137
- {"learn":[0.5675028367],"iteration":133,"passed_time":0.4351253386,"remaining_time":0.2143154653},
138
- {"learn":[0.5651542372],"iteration":134,"passed_time":0.4419929698,"remaining_time":0.2128114299},
139
- {"learn":[0.5618670971],"iteration":135,"passed_time":0.4522148581,"remaining_time":0.2128069921},
140
- {"learn":[0.5595066967],"iteration":136,"passed_time":0.4781720255,"remaining_time":0.2198893256},
141
- {"learn":[0.5571694458],"iteration":137,"passed_time":0.4879483047,"remaining_time":0.2192231514},
142
- {"learn":[0.5549336755],"iteration":138,"passed_time":0.4951066577,"remaining_time":0.2172770224},
143
- {"learn":[0.5532775438],"iteration":139,"passed_time":0.5011632957,"remaining_time":0.2147842696},
144
- {"learn":[0.5514989197],"iteration":140,"passed_time":0.5063335673,"remaining_time":0.2118700743},
145
- {"learn":[0.5486121339],"iteration":141,"passed_time":0.5122684628,"remaining_time":0.2092364144},
146
- {"learn":[0.546200445],"iteration":142,"passed_time":0.5159091414,"remaining_time":0.2056421053},
147
- {"learn":[0.5435735305],"iteration":143,"passed_time":0.5191018998,"remaining_time":0.201872961},
148
- {"learn":[0.5412421678],"iteration":144,"passed_time":0.521702871,"remaining_time":0.1978872959},
149
- {"learn":[0.5400257427],"iteration":145,"passed_time":0.5238612043,"remaining_time":0.1937568838},
150
- {"learn":[0.5377417958],"iteration":146,"passed_time":0.5276108955,"remaining_time":0.1902270576},
151
- {"learn":[0.5355061154],"iteration":147,"passed_time":0.5300877322,"remaining_time":0.186247041},
152
- {"learn":[0.5336979056],"iteration":148,"passed_time":0.5328222124,"remaining_time":0.1823753882},
153
- {"learn":[0.5324000403],"iteration":149,"passed_time":0.5353904443,"remaining_time":0.1784634814},
154
- {"learn":[0.529710259],"iteration":150,"passed_time":0.5381127569,"remaining_time":0.1746193714},
155
- {"learn":[0.5261298352],"iteration":151,"passed_time":0.542975469,"remaining_time":0.1714659376},
156
- {"learn":[0.524202506],"iteration":152,"passed_time":0.5458683536,"remaining_time":0.1676850498},
157
- {"learn":[0.5218890341],"iteration":153,"passed_time":0.5479374329,"remaining_time":0.1636696228},
158
- {"learn":[0.5199542674],"iteration":154,"passed_time":0.5499653081,"remaining_time":0.1596673475},
159
- {"learn":[0.5170063595],"iteration":155,"passed_time":0.5522630441,"remaining_time":0.1557664996},
160
- {"learn":[0.514594135],"iteration":156,"passed_time":0.5558652196,"remaining_time":0.1522433404},
161
- {"learn":[0.5124848793],"iteration":157,"passed_time":0.5601070832,"remaining_time":0.1488892246},
162
- {"learn":[0.5080709565],"iteration":158,"passed_time":0.5630406954,"remaining_time":0.1451865944},
163
- {"learn":[0.5061450651],"iteration":159,"passed_time":0.5684726582,"remaining_time":0.1421181646},
164
- {"learn":[0.5042162721],"iteration":160,"passed_time":0.5760691223,"remaining_time":0.1395446942},
165
- {"learn":[0.5021700926],"iteration":161,"passed_time":0.5788425276,"remaining_time":0.1357778768},
166
- {"learn":[0.4989800163],"iteration":162,"passed_time":0.5814199747,"remaining_time":0.1319787673},
167
- {"learn":[0.4964408967],"iteration":163,"passed_time":0.5843230052,"remaining_time":0.1282660255},
168
- {"learn":[0.494442716],"iteration":164,"passed_time":0.5874847574,"remaining_time":0.1246179788},
169
- {"learn":[0.4921323494],"iteration":165,"passed_time":0.5914682955,"remaining_time":0.1211441087},
170
- {"learn":[0.4892845676],"iteration":166,"passed_time":0.5942250571,"remaining_time":0.1174217179},
171
- {"learn":[0.4867820408],"iteration":167,"passed_time":0.5973976121,"remaining_time":0.1137900214},
172
- {"learn":[0.4847887077],"iteration":168,"passed_time":0.6003783558,"remaining_time":0.1101285741},
173
- {"learn":[0.4819279446],"iteration":169,"passed_time":0.6021641262,"remaining_time":0.1062642576},
174
- {"learn":[0.4800765981],"iteration":170,"passed_time":0.6036769811,"remaining_time":0.1023779676},
175
- {"learn":[0.4776716805],"iteration":171,"passed_time":0.6070431417,"remaining_time":0.09882097655},
176
- {"learn":[0.4756304192],"iteration":172,"passed_time":0.6089885033,"remaining_time":0.09504444849},
177
- {"learn":[0.4738263312],"iteration":173,"passed_time":0.6111772912,"remaining_time":0.09132534236},
178
- {"learn":[0.4708585845],"iteration":174,"passed_time":0.6131144527,"remaining_time":0.08758777896},
179
- {"learn":[0.4695127327],"iteration":175,"passed_time":0.6153722409,"remaining_time":0.08391439648},
180
- {"learn":[0.4680357734],"iteration":176,"passed_time":0.6178598629,"remaining_time":0.08028687484},
181
- {"learn":[0.4656655379],"iteration":177,"passed_time":0.6200927552,"remaining_time":0.07664067761},
182
- {"learn":[0.4641295221],"iteration":178,"passed_time":0.6234510855,"remaining_time":0.07314230612},
183
- {"learn":[0.4629025785],"iteration":179,"passed_time":0.6251597123,"remaining_time":0.06946219026},
184
- {"learn":[0.4611566405],"iteration":180,"passed_time":0.6275776105,"remaining_time":0.06587831271},
185
- {"learn":[0.4583394488],"iteration":181,"passed_time":0.6303844571,"remaining_time":0.06234571554},
186
- {"learn":[0.4557703947],"iteration":182,"passed_time":0.6328000346,"remaining_time":0.05878470267},
187
- {"learn":[0.453369136],"iteration":183,"passed_time":0.635321629,"remaining_time":0.05524535904},
188
- {"learn":[0.4511683723],"iteration":184,"passed_time":0.6376511671,"remaining_time":0.05170144598},
189
- {"learn":[0.4489689354],"iteration":185,"passed_time":0.6394511361,"remaining_time":0.04813073067},
190
- {"learn":[0.4460674255],"iteration":186,"passed_time":0.6411012041,"remaining_time":0.0445685329},
191
- {"learn":[0.4442073274],"iteration":187,"passed_time":0.6428618492,"remaining_time":0.04103373506},
192
- {"learn":[0.4422920248],"iteration":188,"passed_time":0.6443135751,"remaining_time":0.03749973189},
193
- {"learn":[0.4410763507],"iteration":189,"passed_time":0.6465920922,"remaining_time":0.03403116275},
194
- {"learn":[0.4396820004],"iteration":190,"passed_time":0.6490610492,"remaining_time":0.0305840285},
195
- {"learn":[0.4384941295],"iteration":191,"passed_time":0.6511965491,"remaining_time":0.02713318954},
196
- {"learn":[0.4362369638],"iteration":192,"passed_time":0.6528933411,"remaining_time":0.02368006936},
197
- {"learn":[0.434566568],"iteration":193,"passed_time":0.6549387261,"remaining_time":0.02025583689},
198
- {"learn":[0.4327457921],"iteration":194,"passed_time":0.6562730476,"remaining_time":0.01682751404},
199
- {"learn":[0.4307460928],"iteration":195,"passed_time":0.6580760406,"remaining_time":0.01343012328},
200
- {"learn":[0.4291619818],"iteration":196,"passed_time":0.6599830219,"remaining_time":0.01005050287},
201
- {"learn":[0.4275679969],"iteration":197,"passed_time":0.6664784173,"remaining_time":0.006732105225},
202
- {"learn":[0.425495808],"iteration":198,"passed_time":0.6736799319,"remaining_time":0.003385326291},
203
- {"learn":[0.4246656913],"iteration":199,"passed_time":0.6791263424,"remaining_time":0}
204
  ]}
 
1
  {
2
  "meta":{"test_sets":[],"test_metrics":[],"learn_metrics":[{"best_value":"Min","name":"MultiClass"}],"launch_mode":"Train","parameters":"","iteration_count":200,"learn_sets":["learn"],"name":"experiment"},
3
  "iterations":[
4
+ {"learn":[1.093205242],"iteration":0,"passed_time":0.002700530746,"remaining_time":0.5374056184},
5
+ {"learn":[1.089296198],"iteration":1,"passed_time":0.004458564866,"remaining_time":0.4413979218},
6
+ {"learn":[1.085800463],"iteration":2,"passed_time":0.006334754819,"remaining_time":0.4159822331},
7
+ {"learn":[1.082940579],"iteration":3,"passed_time":0.007956610432,"remaining_time":0.3898739111},
8
+ {"learn":[1.076902286],"iteration":4,"passed_time":0.00973436367,"remaining_time":0.3796401831},
9
+ {"learn":[1.072424915],"iteration":5,"passed_time":0.01158463775,"remaining_time":0.3745699538},
10
+ {"learn":[1.070486521],"iteration":6,"passed_time":0.01333745344,"remaining_time":0.3677326448},
11
+ {"learn":[1.067709739],"iteration":7,"passed_time":0.01524372946,"remaining_time":0.3658495071},
12
+ {"learn":[1.063947286],"iteration":8,"passed_time":0.01734970754,"remaining_time":0.3681993489},
13
+ {"learn":[1.059022405],"iteration":9,"passed_time":0.01928384774,"remaining_time":0.366393107},
14
+ {"learn":[1.054605749],"iteration":10,"passed_time":0.02110991174,"remaining_time":0.3627066654},
15
+ {"learn":[1.051037029],"iteration":11,"passed_time":0.02276974228,"remaining_time":0.3567259623},
16
+ {"learn":[1.046238247],"iteration":12,"passed_time":0.02424200037,"remaining_time":0.3487118515},
17
+ {"learn":[1.041694363],"iteration":13,"passed_time":0.02632824361,"remaining_time":0.3497895223},
18
+ {"learn":[1.037651376],"iteration":14,"passed_time":0.02835464484,"remaining_time":0.3497072863},
19
+ {"learn":[1.034067664],"iteration":15,"passed_time":0.03027838798,"remaining_time":0.3482014617},
20
+ {"learn":[1.031380894],"iteration":16,"passed_time":0.03188953079,"remaining_time":0.3432814197},
21
+ {"learn":[1.027554993],"iteration":17,"passed_time":0.0335196191,"remaining_time":0.3389205931},
22
+ {"learn":[1.023928755],"iteration":18,"passed_time":0.0350220636,"remaining_time":0.3336312375},
23
+ {"learn":[1.020661502],"iteration":19,"passed_time":0.03687955023,"remaining_time":0.3319159521},
24
+ {"learn":[1.015603636],"iteration":20,"passed_time":0.03856337309,"remaining_time":0.3287068468},
25
+ {"learn":[1.013288081],"iteration":21,"passed_time":0.04062659297,"remaining_time":0.3287060704},
26
+ {"learn":[1.010926858],"iteration":22,"passed_time":0.04219237606,"remaining_time":0.3246978506},
27
+ {"learn":[1.007751412],"iteration":23,"passed_time":0.04403800734,"remaining_time":0.3229453871},
28
+ {"learn":[1.004360662],"iteration":24,"passed_time":0.04581507457,"remaining_time":0.320705522},
29
+ {"learn":[0.9993662657],"iteration":25,"passed_time":0.04787310278,"remaining_time":0.320381534},
30
+ {"learn":[0.9969451375],"iteration":26,"passed_time":0.05006162113,"remaining_time":0.320765202},
31
+ {"learn":[0.9945409056],"iteration":27,"passed_time":0.05225948328,"remaining_time":0.3210225402},
32
+ {"learn":[0.9907006517],"iteration":28,"passed_time":0.05440212683,"remaining_time":0.3207849547},
33
+ {"learn":[0.9885561607],"iteration":29,"passed_time":0.05667896345,"remaining_time":0.3211807929},
34
+ {"learn":[0.984248119],"iteration":30,"passed_time":0.05890604908,"remaining_time":0.3211329772},
35
+ {"learn":[0.9807137036],"iteration":31,"passed_time":0.06108680467,"remaining_time":0.3207057245},
36
+ {"learn":[0.9780850221],"iteration":32,"passed_time":0.06319012336,"remaining_time":0.3197803213},
37
+ {"learn":[0.9740531802],"iteration":33,"passed_time":0.06508580667,"remaining_time":0.3177718796},
38
+ {"learn":[0.9713410447],"iteration":34,"passed_time":0.06668467638,"remaining_time":0.3143706172},
39
+ {"learn":[0.967412389],"iteration":35,"passed_time":0.06838351167,"remaining_time":0.3115248865},
40
+ {"learn":[0.9644315086],"iteration":36,"passed_time":0.07007147161,"remaining_time":0.3086932398},
41
+ {"learn":[0.9592457648],"iteration":37,"passed_time":0.07173115431,"remaining_time":0.3058012368},
42
+ {"learn":[0.9566252893],"iteration":38,"passed_time":0.07339949347,"remaining_time":0.3030081654},
43
+ {"learn":[0.9529972622],"iteration":39,"passed_time":0.07517147841,"remaining_time":0.3006859136},
44
+ {"learn":[0.9503961485],"iteration":40,"passed_time":0.07705750652,"remaining_time":0.2988327692},
45
+ {"learn":[0.9478966399],"iteration":41,"passed_time":0.07871183332,"remaining_time":0.2961064206},
46
+ {"learn":[0.944616608],"iteration":42,"passed_time":0.08037803821,"remaining_time":0.2934733023},
47
+ {"learn":[0.9409584079],"iteration":43,"passed_time":0.08202857612,"remaining_time":0.2908285881},
48
+ {"learn":[0.9385875314],"iteration":44,"passed_time":0.08393755501,"remaining_time":0.289118245},
49
+ {"learn":[0.9358293633],"iteration":45,"passed_time":0.08562284219,"remaining_time":0.2866503847},
50
+ {"learn":[0.9320133517],"iteration":46,"passed_time":0.08753530594,"remaining_time":0.2849553576},
51
+ {"learn":[0.9284762006],"iteration":47,"passed_time":0.08921765077,"remaining_time":0.2825225608},
52
+ {"learn":[0.9252772309],"iteration":48,"passed_time":0.09072459024,"remaining_time":0.2795798597},
53
+ {"learn":[0.9216958631],"iteration":49,"passed_time":0.09242161705,"remaining_time":0.2772648511},
54
+ {"learn":[0.918240019],"iteration":50,"passed_time":0.0940251503,"remaining_time":0.2747009293},
55
+ {"learn":[0.9149621868],"iteration":51,"passed_time":0.09566766222,"remaining_time":0.2722848848},
56
+ {"learn":[0.9118360189],"iteration":52,"passed_time":0.09735125731,"remaining_time":0.2700119778},
57
+ {"learn":[0.9081751934],"iteration":53,"passed_time":0.09917284675,"remaining_time":0.2681339931},
58
+ {"learn":[0.9050419952],"iteration":54,"passed_time":0.1010378643,"remaining_time":0.2663725514},
59
+ {"learn":[0.9017628251],"iteration":55,"passed_time":0.1025776132,"remaining_time":0.2637710053},
60
+ {"learn":[0.8993296976],"iteration":56,"passed_time":0.1045173621,"remaining_time":0.2622102242},
61
+ {"learn":[0.8964495626],"iteration":57,"passed_time":0.106001424,"remaining_time":0.2595207278},
62
+ {"learn":[0.893758375],"iteration":58,"passed_time":0.1074786601,"remaining_time":0.2568557809},
63
+ {"learn":[0.891306073],"iteration":59,"passed_time":0.1091309951,"remaining_time":0.2546389886},
64
+ {"learn":[0.8896240451],"iteration":60,"passed_time":0.1108353893,"remaining_time":0.2525593298},
65
+ {"learn":[0.886672253],"iteration":61,"passed_time":0.11242446,"remaining_time":0.2502350884},
66
+ {"learn":[0.8831787359],"iteration":62,"passed_time":0.1142783889,"remaining_time":0.2485101472},
67
+ {"learn":[0.8807247302],"iteration":63,"passed_time":0.115970814,"remaining_time":0.2464379798},
68
+ {"learn":[0.8775340418],"iteration":64,"passed_time":0.1176347221,"remaining_time":0.2443182689},
69
+ {"learn":[0.8757817027],"iteration":65,"passed_time":0.1192678026,"remaining_time":0.242149781},
70
+ {"learn":[0.8731628387],"iteration":66,"passed_time":0.1209697765,"remaining_time":0.240134034},
71
+ {"learn":[0.870440569],"iteration":67,"passed_time":0.1225921289,"remaining_time":0.237972956},
72
+ {"learn":[0.8676778125],"iteration":68,"passed_time":0.1242741951,"remaining_time":0.2359408631},
73
+ {"learn":[0.864782525],"iteration":69,"passed_time":0.1259839438,"remaining_time":0.2339701814},
74
+ {"learn":[0.8619514313],"iteration":70,"passed_time":0.1275830276,"remaining_time":0.2318057826},
75
+ {"learn":[0.8593813157],"iteration":71,"passed_time":0.1293105164,"remaining_time":0.2298853625},
76
+ {"learn":[0.8566989735],"iteration":72,"passed_time":0.1313927413,"remaining_time":0.2285873719},
77
+ {"learn":[0.8538559437],"iteration":73,"passed_time":0.1335838702,"remaining_time":0.2274536169},
78
+ {"learn":[0.8514273334],"iteration":74,"passed_time":0.1351317755,"remaining_time":0.2252196258},
79
+ {"learn":[0.8485875602],"iteration":75,"passed_time":0.1366301859,"remaining_time":0.2229229349},
80
+ {"learn":[0.8454171877],"iteration":76,"passed_time":0.1381832845,"remaining_time":0.2207343376},
81
+ {"learn":[0.8434237571],"iteration":77,"passed_time":0.1402676808,"remaining_time":0.2193930392},
82
+ {"learn":[0.8397825549],"iteration":78,"passed_time":0.1574408193,"remaining_time":0.2411435334},
83
+ {"learn":[0.8370105039],"iteration":79,"passed_time":0.1594920899,"remaining_time":0.2392381348},
84
+ {"learn":[0.8342251022],"iteration":80,"passed_time":0.1614106875,"remaining_time":0.2371342199},
85
+ {"learn":[0.8315255385],"iteration":81,"passed_time":0.1631617044,"remaining_time":0.2347936722},
86
+ {"learn":[0.8298459099],"iteration":82,"passed_time":0.1653348327,"remaining_time":0.2330623546},
87
+ {"learn":[0.8283612294],"iteration":83,"passed_time":0.1671237068,"remaining_time":0.2307898808},
88
+ {"learn":[0.8246264822],"iteration":84,"passed_time":0.1687709047,"remaining_time":0.2283371063},
89
+ {"learn":[0.8213473255],"iteration":85,"passed_time":0.1706165283,"remaining_time":0.2261660956},
90
+ {"learn":[0.8196070074],"iteration":86,"passed_time":0.1725107272,"remaining_time":0.2240656571},
91
+ {"learn":[0.8166511145],"iteration":87,"passed_time":0.174413605,"remaining_time":0.2219809518},
92
+ {"learn":[0.8135280587],"iteration":88,"passed_time":0.1759187212,"remaining_time":0.2194042478},
93
+ {"learn":[0.81036371],"iteration":89,"passed_time":0.1774937264,"remaining_time":0.2169367767},
94
+ {"learn":[0.8066284815],"iteration":90,"passed_time":0.1789450656,"remaining_time":0.2143407929},
95
+ {"learn":[0.8038651041],"iteration":91,"passed_time":0.180849495,"remaining_time":0.2123015811},
96
+ {"learn":[0.8010024622],"iteration":92,"passed_time":0.1823891432,"remaining_time":0.2098455733},
97
+ {"learn":[0.7965903543],"iteration":93,"passed_time":0.1839416246,"remaining_time":0.2074235342},
98
+ {"learn":[0.7938158579],"iteration":94,"passed_time":0.1856494004,"remaining_time":0.2051914425},
99
+ {"learn":[0.7917355846],"iteration":95,"passed_time":0.1873532136,"remaining_time":0.2029659814},
100
+ {"learn":[0.789231216],"iteration":96,"passed_time":0.1889143164,"remaining_time":0.2005997381},
101
+ {"learn":[0.7869594182],"iteration":97,"passed_time":0.1906026299,"remaining_time":0.1983823291},
102
+ {"learn":[0.7844456343],"iteration":98,"passed_time":0.1925205422,"remaining_time":0.1964098461},
103
+ {"learn":[0.7827182622],"iteration":99,"passed_time":0.1940725879,"remaining_time":0.1940725879},
104
+ {"learn":[0.7809365526],"iteration":100,"passed_time":0.1955105954,"remaining_time":0.1916390985},
105
+ {"learn":[0.7786073713],"iteration":101,"passed_time":0.1971157254,"remaining_time":0.189385697},
106
+ {"learn":[0.7756969319],"iteration":102,"passed_time":0.1988023642,"remaining_time":0.1872216439},
107
+ {"learn":[0.7725361088],"iteration":103,"passed_time":0.2007437213,"remaining_time":0.1853018966},
108
+ {"learn":[0.7707524593],"iteration":104,"passed_time":0.2023988274,"remaining_time":0.1831227486},
109
+ {"learn":[0.7680995843],"iteration":105,"passed_time":0.2039996243,"remaining_time":0.1809053272},
110
+ {"learn":[0.7661193713],"iteration":106,"passed_time":0.2059617819,"remaining_time":0.1790135114},
111
+ {"learn":[0.7638792989],"iteration":107,"passed_time":0.2077158662,"remaining_time":0.1769431453},
112
+ {"learn":[0.7615820938],"iteration":108,"passed_time":0.2095298505,"remaining_time":0.1749285908},
113
+ {"learn":[0.7598842725],"iteration":109,"passed_time":0.2110274037,"remaining_time":0.1726587848},
114
+ {"learn":[0.7561665501],"iteration":110,"passed_time":0.212599817,"remaining_time":0.1704629163},
115
+ {"learn":[0.7532353233],"iteration":111,"passed_time":0.2148096158,"remaining_time":0.1687789838},
116
+ {"learn":[0.7512791352],"iteration":112,"passed_time":0.2163519741,"remaining_time":0.1665718739},
117
+ {"learn":[0.7490483463],"iteration":113,"passed_time":0.2178098439,"remaining_time":0.1643126893},
118
+ {"learn":[0.7456312231],"iteration":114,"passed_time":0.2194688296,"remaining_time":0.1622160914},
119
+ {"learn":[0.7423207006],"iteration":115,"passed_time":0.2214830641,"remaining_time":0.1603842878},
120
+ {"learn":[0.7396266689],"iteration":116,"passed_time":0.223562745,"remaining_time":0.1585957934},
121
+ {"learn":[0.7374406621],"iteration":117,"passed_time":0.2250632395,"remaining_time":0.1563998783},
122
+ {"learn":[0.7347465285],"iteration":118,"passed_time":0.2267205133,"remaining_time":0.1543223662},
123
+ {"learn":[0.7316488359],"iteration":119,"passed_time":0.2285644763,"remaining_time":0.1523763175},
124
+ {"learn":[0.7291388918],"iteration":120,"passed_time":0.230050533,"remaining_time":0.1501982819},
125
+ {"learn":[0.7274213837],"iteration":121,"passed_time":0.2316809621,"remaining_time":0.1481238938},
126
+ {"learn":[0.7255509963],"iteration":122,"passed_time":0.2333922528,"remaining_time":0.1461073453},
127
+ {"learn":[0.7228838739],"iteration":123,"passed_time":0.235182611,"remaining_time":0.1441441809},
128
+ {"learn":[0.7212786404],"iteration":124,"passed_time":0.2368341941,"remaining_time":0.1421005164},
129
+ {"learn":[0.7192994996],"iteration":125,"passed_time":0.2386781333,"remaining_time":0.1401760465},
130
+ {"learn":[0.7170966975],"iteration":126,"passed_time":0.2404280474,"remaining_time":0.1381987989},
131
+ {"learn":[0.7152245863],"iteration":127,"passed_time":0.2420706343,"remaining_time":0.1361647318},
132
+ {"learn":[0.7137431062],"iteration":128,"passed_time":0.2437023638,"remaining_time":0.1341307584},
133
+ {"learn":[0.7110045802],"iteration":129,"passed_time":0.2452986882,"remaining_time":0.132083909},
134
+ {"learn":[0.7083429294],"iteration":130,"passed_time":0.24715349,"remaining_time":0.1301800825},
135
+ {"learn":[0.7059155467],"iteration":131,"passed_time":0.2492658582,"remaining_time":0.1284096845},
136
+ {"learn":[0.7045010934],"iteration":132,"passed_time":0.2510431177,"remaining_time":0.12646533},
137
+ {"learn":[0.701902575],"iteration":133,"passed_time":0.2530067292,"remaining_time":0.1246152547},
138
+ {"learn":[0.7001669261],"iteration":134,"passed_time":0.2547815629,"remaining_time":0.1226726043},
139
+ {"learn":[0.6980658317],"iteration":135,"passed_time":0.2564193979,"remaining_time":0.1206679519},
140
+ {"learn":[0.6961677749],"iteration":136,"passed_time":0.2581067099,"remaining_time":0.1186914068},
141
+ {"learn":[0.6930208614],"iteration":137,"passed_time":0.2597519338,"remaining_time":0.1167001442},
142
+ {"learn":[0.6907435615],"iteration":138,"passed_time":0.2614007832,"remaining_time":0.1147154516},
143
+ {"learn":[0.6889091552],"iteration":139,"passed_time":0.2629295781,"remaining_time":0.1126841049},
144
+ {"learn":[0.6860876176],"iteration":140,"passed_time":0.2646986602,"remaining_time":0.1107604323},
145
+ {"learn":[0.6828681848],"iteration":141,"passed_time":0.266390301,"remaining_time":0.108807306},
146
+ {"learn":[0.6806217027],"iteration":142,"passed_time":0.2681440335,"remaining_time":0.1068825868},
147
+ {"learn":[0.6774741387],"iteration":143,"passed_time":0.270101295,"remaining_time":0.1050393925},
148
+ {"learn":[0.6755280009],"iteration":144,"passed_time":0.2718263867,"remaining_time":0.1031065605},
149
+ {"learn":[0.6741665407],"iteration":145,"passed_time":0.2735399912,"remaining_time":0.1011723255},
150
+ {"learn":[0.6714424836],"iteration":146,"passed_time":0.2750842491,"remaining_time":0.09918003538},
151
+ {"learn":[0.6690518867],"iteration":147,"passed_time":0.2767590178,"remaining_time":0.0972396549},
152
+ {"learn":[0.6670540904],"iteration":148,"passed_time":0.2789507193,"remaining_time":0.09547977641},
153
+ {"learn":[0.6654624264],"iteration":149,"passed_time":0.2806616785,"remaining_time":0.09355389284},
154
+ {"learn":[0.6635237109],"iteration":150,"passed_time":0.2827075276,"remaining_time":0.09173952883},
155
+ {"learn":[0.6614735621],"iteration":151,"passed_time":0.2846036611,"remaining_time":0.08987484035},
156
+ {"learn":[0.6601319451],"iteration":152,"passed_time":0.2863283374,"remaining_time":0.08795707095},
157
+ {"learn":[0.6574872141],"iteration":153,"passed_time":0.2881504225,"remaining_time":0.08607090542},
158
+ {"learn":[0.6558207681],"iteration":154,"passed_time":0.2901007739,"remaining_time":0.08422280532},
159
+ {"learn":[0.6541525713],"iteration":155,"passed_time":0.2916399925,"remaining_time":0.08225743379},
160
+ {"learn":[0.6527845902],"iteration":156,"passed_time":0.2934304534,"remaining_time":0.08036630251},
161
+ {"learn":[0.6505051681],"iteration":157,"passed_time":0.2953386008,"remaining_time":0.07850772932},
162
+ {"learn":[0.6491150255],"iteration":158,"passed_time":0.2967857377,"remaining_time":0.07652965563},
163
+ {"learn":[0.6468753418],"iteration":159,"passed_time":0.2984442862,"remaining_time":0.07461107155},
164
+ {"learn":[0.6442990818],"iteration":160,"passed_time":0.3000145388,"remaining_time":0.07267432928},
165
+ {"learn":[0.6423880435],"iteration":161,"passed_time":0.3015877137,"remaining_time":0.07074279705},
166
+ {"learn":[0.6402743573],"iteration":162,"passed_time":0.3032131184,"remaining_time":0.06882751768},
167
+ {"learn":[0.6387280436],"iteration":163,"passed_time":0.3049731296,"remaining_time":0.06694532114},
168
+ {"learn":[0.6370099287],"iteration":164,"passed_time":0.3069621817,"remaining_time":0.06511319006},
169
+ {"learn":[0.6359368009],"iteration":165,"passed_time":0.3087835233,"remaining_time":0.06324481803},
170
+ {"learn":[0.6342299731],"iteration":166,"passed_time":0.3102145076,"remaining_time":0.06129987276},
171
+ {"learn":[0.6325437121],"iteration":167,"passed_time":0.3118666874,"remaining_time":0.05940317856},
172
+ {"learn":[0.6296576212],"iteration":168,"passed_time":0.3134897388,"remaining_time":0.05750403492},
173
+ {"learn":[0.6276389296],"iteration":169,"passed_time":0.3151600767,"remaining_time":0.05561648413},
174
+ {"learn":[0.6260245742],"iteration":170,"passed_time":0.3167978743,"remaining_time":0.05372595529},
175
+ {"learn":[0.6248907195],"iteration":171,"passed_time":0.3184121317,"remaining_time":0.05183453307},
176
+ {"learn":[0.623028321],"iteration":172,"passed_time":0.3202036,"remaining_time":0.04997397225},
177
+ {"learn":[0.6216858837],"iteration":173,"passed_time":0.3222818704,"remaining_time":0.04815706109},
178
+ {"learn":[0.6202385865],"iteration":174,"passed_time":0.3240270986,"remaining_time":0.04628958551},
179
+ {"learn":[0.6177599229],"iteration":175,"passed_time":0.325625778,"remaining_time":0.04440351518},
180
+ {"learn":[0.6163950426],"iteration":176,"passed_time":0.3276964807,"remaining_time":0.04258202856},
181
+ {"learn":[0.6153154716],"iteration":177,"passed_time":0.3292879606,"remaining_time":0.04069851198},
182
+ {"learn":[0.6137768141],"iteration":178,"passed_time":0.3310503301,"remaining_time":0.03883830688},
183
+ {"learn":[0.6122335411],"iteration":179,"passed_time":0.3328033649,"remaining_time":0.03697815165},
184
+ {"learn":[0.6088666804],"iteration":180,"passed_time":0.3346318929,"remaining_time":0.03512710478},
185
+ {"learn":[0.6076454874],"iteration":181,"passed_time":0.3364966389,"remaining_time":0.03327988737},
186
+ {"learn":[0.6060398876],"iteration":182,"passed_time":0.3381532629,"remaining_time":0.03141314464},
187
+ {"learn":[0.6041382727],"iteration":183,"passed_time":0.3399133396,"remaining_time":0.02955768171},
188
+ {"learn":[0.6026335698],"iteration":184,"passed_time":0.341658234,"remaining_time":0.02770201897},
189
+ {"learn":[0.6005888944],"iteration":185,"passed_time":0.3432049679,"remaining_time":0.025832632},
190
+ {"learn":[0.5982179508],"iteration":186,"passed_time":0.3449097475,"remaining_time":0.02397768298},
191
+ {"learn":[0.5967473936],"iteration":187,"passed_time":0.3465734418,"remaining_time":0.02212170905},
192
+ {"learn":[0.5951356964],"iteration":188,"passed_time":0.348354104,"remaining_time":0.02027457748},
193
+ {"learn":[0.5928623215],"iteration":189,"passed_time":0.3505087035,"remaining_time":0.0184478265},
194
+ {"learn":[0.5912863691],"iteration":190,"passed_time":0.3521537006,"remaining_time":0.01659362987},
195
+ {"learn":[0.5900052977],"iteration":191,"passed_time":0.353944627,"remaining_time":0.01474769279},
196
+ {"learn":[0.5881995754],"iteration":192,"passed_time":0.355983025,"remaining_time":0.01291130143},
197
+ {"learn":[0.5869825392],"iteration":193,"passed_time":0.3576171029,"remaining_time":0.01106032277},
198
+ {"learn":[0.584950899],"iteration":194,"passed_time":0.3591092785,"remaining_time":0.009207930217},
199
+ {"learn":[0.5821862973],"iteration":195,"passed_time":0.3607105283,"remaining_time":0.007361439353},
200
+ {"learn":[0.5798523192],"iteration":196,"passed_time":0.3628981881,"remaining_time":0.005526368346},
201
+ {"learn":[0.5789841317],"iteration":197,"passed_time":0.3647801393,"remaining_time":0.003684647872},
202
+ {"learn":[0.5773771607],"iteration":198,"passed_time":0.3664826952,"remaining_time":0.001841621584},
203
+ {"learn":[0.5750727931],"iteration":199,"passed_time":0.3681562943,"remaining_time":0}
204
  ]}
webapp/catboost_info/learn/events.out.tfevents CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f42e6245f9499a077aee7363d2094a4ec9f7ee73c1de24594f6bb1c91d6c8e5f
3
  size 12070
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d07956a3a8da8881442504752ad6649cc29acd6d9e73a31c71199d20da4bfbef
3
  size 12070
webapp/catboost_info/learn_error.tsv CHANGED
@@ -1,201 +1,201 @@
1
  iter MultiClass
2
- 0 1.091148423
3
- 1 1.086418765
4
- 2 1.0773991
5
- 3 1.071672289
6
- 4 1.066004714
7
- 5 1.059330013
8
- 6 1.05490226
9
- 7 1.048588391
10
- 8 1.043833033
11
- 9 1.037311438
12
- 10 1.031927739
13
- 11 1.025841223
14
- 12 1.021936274
15
- 13 1.016038582
16
- 14 1.011831586
17
- 15 1.007661983
18
- 16 1.00331399
19
- 17 0.9969175017
20
- 18 0.9915381213
21
- 19 0.987027199
22
- 20 0.9806451898
23
- 21 0.97625914
24
- 22 0.9684721006
25
- 23 0.9650061706
26
- 24 0.9574638884
27
- 25 0.9535340201
28
- 26 0.9493774514
29
- 27 0.9458850596
30
- 28 0.9407835813
31
- 29 0.9365937962
32
- 30 0.9314428367
33
- 31 0.9270029216
34
- 32 0.9234886611
35
- 33 0.9183877748
36
- 34 0.9155318031
37
- 35 0.9112328302
38
- 36 0.90756732
39
- 37 0.9006450864
40
- 38 0.898315496
41
- 39 0.8949441838
42
- 40 0.8903109401
43
- 41 0.8866011593
44
- 42 0.8818539442
45
- 43 0.8766400926
46
- 44 0.8711942711
47
- 45 0.8664049339
48
- 46 0.8605692297
49
- 47 0.855305651
50
- 48 0.8498381077
51
- 49 0.8457962609
52
- 50 0.8416413202
53
- 51 0.8364743562
54
- 52 0.8325194429
55
- 53 0.8284764993
56
- 54 0.8236751265
57
- 55 0.8181696307
58
- 56 0.814313061
59
- 57 0.8115976577
60
- 58 0.807758466
61
- 59 0.802321422
62
- 60 0.798807136
63
- 61 0.7948400764
64
- 62 0.7916880148
65
- 63 0.7873311755
66
- 64 0.7827613451
67
- 65 0.7786702385
68
- 66 0.7764977254
69
- 67 0.7730194967
70
- 68 0.7696007626
71
- 69 0.7642752146
72
- 70 0.760253606
73
- 71 0.7577785571
74
- 72 0.7539434543
75
- 73 0.7495444532
76
- 74 0.7455923189
77
- 75 0.7429488753
78
- 76 0.7400940248
79
- 77 0.737176055
80
- 78 0.7334430947
81
- 79 0.7307758227
82
- 80 0.7271924097
83
- 81 0.7233691229
84
- 82 0.7199860815
85
- 83 0.7166443842
86
- 84 0.7120905194
87
- 85 0.7080689226
88
- 86 0.7049974284
89
- 87 0.7008658577
90
- 88 0.6968041294
91
- 89 0.6949067976
92
- 90 0.6923908515
93
- 91 0.6874475769
94
- 92 0.6834969954
95
- 93 0.6797426739
96
- 94 0.676311281
97
- 95 0.6732950825
98
- 96 0.670343132
99
- 97 0.6672527936
100
- 98 0.6654513235
101
- 99 0.6629430399
102
- 100 0.6599425476
103
- 101 0.6563456648
104
- 102 0.6533420617
105
- 103 0.6521604983
106
- 104 0.6486732019
107
- 105 0.6452204016
108
- 106 0.6428646774
109
- 107 0.6392699247
110
- 108 0.6357158219
111
- 109 0.6328221906
112
- 110 0.6295509884
113
- 111 0.6261120005
114
- 112 0.6236044192
115
- 113 0.6212460917
116
- 114 0.6177241089
117
- 115 0.6157604351
118
- 116 0.6132566809
119
- 117 0.6104162939
120
- 118 0.6079636357
121
- 119 0.6063102359
122
- 120 0.602804494
123
- 121 0.5991211844
124
- 122 0.5958434122
125
- 123 0.5932912801
126
- 124 0.5918961165
127
- 125 0.5896874223
128
- 126 0.5868596712
129
- 127 0.584461876
130
- 128 0.5808172852
131
- 129 0.5787637725
132
- 130 0.5750088728
133
- 131 0.5727294917
134
- 132 0.5707527172
135
- 133 0.5675028367
136
- 134 0.5651542372
137
- 135 0.5618670971
138
- 136 0.5595066967
139
- 137 0.5571694458
140
- 138 0.5549336755
141
- 139 0.5532775438
142
- 140 0.5514989197
143
- 141 0.5486121339
144
- 142 0.546200445
145
- 143 0.5435735305
146
- 144 0.5412421678
147
- 145 0.5400257427
148
- 146 0.5377417958
149
- 147 0.5355061154
150
- 148 0.5336979056
151
- 149 0.5324000403
152
- 150 0.529710259
153
- 151 0.5261298352
154
- 152 0.524202506
155
- 153 0.5218890341
156
- 154 0.5199542674
157
- 155 0.5170063595
158
- 156 0.514594135
159
- 157 0.5124848793
160
- 158 0.5080709565
161
- 159 0.5061450651
162
- 160 0.5042162721
163
- 161 0.5021700926
164
- 162 0.4989800163
165
- 163 0.4964408967
166
- 164 0.494442716
167
- 165 0.4921323494
168
- 166 0.4892845676
169
- 167 0.4867820408
170
- 168 0.4847887077
171
- 169 0.4819279446
172
- 170 0.4800765981
173
- 171 0.4776716805
174
- 172 0.4756304192
175
- 173 0.4738263312
176
- 174 0.4708585845
177
- 175 0.4695127327
178
- 176 0.4680357734
179
- 177 0.4656655379
180
- 178 0.4641295221
181
- 179 0.4629025785
182
- 180 0.4611566405
183
- 181 0.4583394488
184
- 182 0.4557703947
185
- 183 0.453369136
186
- 184 0.4511683723
187
- 185 0.4489689354
188
- 186 0.4460674255
189
- 187 0.4442073274
190
- 188 0.4422920248
191
- 189 0.4410763507
192
- 190 0.4396820004
193
- 191 0.4384941295
194
- 192 0.4362369638
195
- 193 0.434566568
196
- 194 0.4327457921
197
- 195 0.4307460928
198
- 196 0.4291619818
199
- 197 0.4275679969
200
- 198 0.425495808
201
- 199 0.4246656913
 
1
  iter MultiClass
2
+ 0 1.093205242
3
+ 1 1.089296198
4
+ 2 1.085800463
5
+ 3 1.082940579
6
+ 4 1.076902286
7
+ 5 1.072424915
8
+ 6 1.070486521
9
+ 7 1.067709739
10
+ 8 1.063947286
11
+ 9 1.059022405
12
+ 10 1.054605749
13
+ 11 1.051037029
14
+ 12 1.046238247
15
+ 13 1.041694363
16
+ 14 1.037651376
17
+ 15 1.034067664
18
+ 16 1.031380894
19
+ 17 1.027554993
20
+ 18 1.023928755
21
+ 19 1.020661502
22
+ 20 1.015603636
23
+ 21 1.013288081
24
+ 22 1.010926858
25
+ 23 1.007751412
26
+ 24 1.004360662
27
+ 25 0.9993662657
28
+ 26 0.9969451375
29
+ 27 0.9945409056
30
+ 28 0.9907006517
31
+ 29 0.9885561607
32
+ 30 0.984248119
33
+ 31 0.9807137036
34
+ 32 0.9780850221
35
+ 33 0.9740531802
36
+ 34 0.9713410447
37
+ 35 0.967412389
38
+ 36 0.9644315086
39
+ 37 0.9592457648
40
+ 38 0.9566252893
41
+ 39 0.9529972622
42
+ 40 0.9503961485
43
+ 41 0.9478966399
44
+ 42 0.944616608
45
+ 43 0.9409584079
46
+ 44 0.9385875314
47
+ 45 0.9358293633
48
+ 46 0.9320133517
49
+ 47 0.9284762006
50
+ 48 0.9252772309
51
+ 49 0.9216958631
52
+ 50 0.918240019
53
+ 51 0.9149621868
54
+ 52 0.9118360189
55
+ 53 0.9081751934
56
+ 54 0.9050419952
57
+ 55 0.9017628251
58
+ 56 0.8993296976
59
+ 57 0.8964495626
60
+ 58 0.893758375
61
+ 59 0.891306073
62
+ 60 0.8896240451
63
+ 61 0.886672253
64
+ 62 0.8831787359
65
+ 63 0.8807247302
66
+ 64 0.8775340418
67
+ 65 0.8757817027
68
+ 66 0.8731628387
69
+ 67 0.870440569
70
+ 68 0.8676778125
71
+ 69 0.864782525
72
+ 70 0.8619514313
73
+ 71 0.8593813157
74
+ 72 0.8566989735
75
+ 73 0.8538559437
76
+ 74 0.8514273334
77
+ 75 0.8485875602
78
+ 76 0.8454171877
79
+ 77 0.8434237571
80
+ 78 0.8397825549
81
+ 79 0.8370105039
82
+ 80 0.8342251022
83
+ 81 0.8315255385
84
+ 82 0.8298459099
85
+ 83 0.8283612294
86
+ 84 0.8246264822
87
+ 85 0.8213473255
88
+ 86 0.8196070074
89
+ 87 0.8166511145
90
+ 88 0.8135280587
91
+ 89 0.81036371
92
+ 90 0.8066284815
93
+ 91 0.8038651041
94
+ 92 0.8010024622
95
+ 93 0.7965903543
96
+ 94 0.7938158579
97
+ 95 0.7917355846
98
+ 96 0.789231216
99
+ 97 0.7869594182
100
+ 98 0.7844456343
101
+ 99 0.7827182622
102
+ 100 0.7809365526
103
+ 101 0.7786073713
104
+ 102 0.7756969319
105
+ 103 0.7725361088
106
+ 104 0.7707524593
107
+ 105 0.7680995843
108
+ 106 0.7661193713
109
+ 107 0.7638792989
110
+ 108 0.7615820938
111
+ 109 0.7598842725
112
+ 110 0.7561665501
113
+ 111 0.7532353233
114
+ 112 0.7512791352
115
+ 113 0.7490483463
116
+ 114 0.7456312231
117
+ 115 0.7423207006
118
+ 116 0.7396266689
119
+ 117 0.7374406621
120
+ 118 0.7347465285
121
+ 119 0.7316488359
122
+ 120 0.7291388918
123
+ 121 0.7274213837
124
+ 122 0.7255509963
125
+ 123 0.7228838739
126
+ 124 0.7212786404
127
+ 125 0.7192994996
128
+ 126 0.7170966975
129
+ 127 0.7152245863
130
+ 128 0.7137431062
131
+ 129 0.7110045802
132
+ 130 0.7083429294
133
+ 131 0.7059155467
134
+ 132 0.7045010934
135
+ 133 0.701902575
136
+ 134 0.7001669261
137
+ 135 0.6980658317
138
+ 136 0.6961677749
139
+ 137 0.6930208614
140
+ 138 0.6907435615
141
+ 139 0.6889091552
142
+ 140 0.6860876176
143
+ 141 0.6828681848
144
+ 142 0.6806217027
145
+ 143 0.6774741387
146
+ 144 0.6755280009
147
+ 145 0.6741665407
148
+ 146 0.6714424836
149
+ 147 0.6690518867
150
+ 148 0.6670540904
151
+ 149 0.6654624264
152
+ 150 0.6635237109
153
+ 151 0.6614735621
154
+ 152 0.6601319451
155
+ 153 0.6574872141
156
+ 154 0.6558207681
157
+ 155 0.6541525713
158
+ 156 0.6527845902
159
+ 157 0.6505051681
160
+ 158 0.6491150255
161
+ 159 0.6468753418
162
+ 160 0.6442990818
163
+ 161 0.6423880435
164
+ 162 0.6402743573
165
+ 163 0.6387280436
166
+ 164 0.6370099287
167
+ 165 0.6359368009
168
+ 166 0.6342299731
169
+ 167 0.6325437121
170
+ 168 0.6296576212
171
+ 169 0.6276389296
172
+ 170 0.6260245742
173
+ 171 0.6248907195
174
+ 172 0.623028321
175
+ 173 0.6216858837
176
+ 174 0.6202385865
177
+ 175 0.6177599229
178
+ 176 0.6163950426
179
+ 177 0.6153154716
180
+ 178 0.6137768141
181
+ 179 0.6122335411
182
+ 180 0.6088666804
183
+ 181 0.6076454874
184
+ 182 0.6060398876
185
+ 183 0.6041382727
186
+ 184 0.6026335698
187
+ 185 0.6005888944
188
+ 186 0.5982179508
189
+ 187 0.5967473936
190
+ 188 0.5951356964
191
+ 189 0.5928623215
192
+ 190 0.5912863691
193
+ 191 0.5900052977
194
+ 192 0.5881995754
195
+ 193 0.5869825392
196
+ 194 0.584950899
197
+ 195 0.5821862973
198
+ 196 0.5798523192
199
+ 197 0.5789841317
200
+ 198 0.5773771607
201
+ 199 0.5750727931
webapp/catboost_info/time_left.tsv CHANGED
@@ -1,201 +1,201 @@
1
  iter Passed Remaining
2
- 0 2 561
3
- 1 4 461
4
- 2 6 451
5
- 3 9 452
6
- 4 11 459
7
- 5 14 457
8
- 6 16 455
9
- 7 18 449
10
- 8 20 436
11
- 9 22 426
12
- 10 25 429
13
- 11 27 428
14
- 12 29 427
15
- 13 31 420
16
- 14 33 410
17
- 15 35 412
18
- 16 37 401
19
- 17 39 394
20
- 18 41 393
21
- 19 43 391
22
- 20 47 406
23
- 21 57 466
24
- 22 80 620
25
- 23 93 682
26
- 24 106 743
27
- 25 120 809
28
- 26 129 831
29
- 27 138 850
30
- 28 147 870
31
- 29 154 874
32
- 30 158 865
33
- 31 161 850
34
- 32 164 833
35
- 33 169 826
36
- 34 172 811
37
- 35 175 797
38
- 36 177 783
39
- 37 181 771
40
- 38 187 775
41
- 39 190 762
42
- 40 193 751
43
- 41 196 738
44
- 42 200 731
45
- 43 202 717
46
- 44 204 705
47
- 45 207 694
48
- 46 209 683
49
- 47 212 674
50
- 48 216 667
51
- 49 218 655
52
- 50 220 643
53
- 51 223 635
54
- 52 226 627
55
- 53 229 619
56
- 54 231 609
57
- 55 232 599
58
- 56 234 588
59
- 57 237 581
60
- 58 240 574
61
- 59 243 567
62
- 60 245 560
63
- 61 248 552
64
- 62 249 543
65
- 63 252 535
66
- 64 254 529
67
- 65 258 524
68
- 66 260 517
69
- 67 263 510
70
- 68 265 503
71
- 69 268 497
72
- 70 270 491
73
- 71 272 484
74
- 72 275 478
75
- 73 277 472
76
- 74 280 466
77
- 75 282 460
78
- 76 283 453
79
- 77 286 447
80
- 78 288 442
81
- 79 290 436
82
- 80 292 429
83
- 81 295 424
84
- 82 297 419
85
- 83 299 414
86
- 84 302 409
87
- 85 305 404
88
- 86 306 398
89
- 87 308 392
90
- 88 311 388
91
- 89 314 383
92
- 90 316 378
93
- 91 318 374
94
- 92 320 369
95
- 93 322 363
96
- 94 325 359
97
- 95 328 356
98
- 96 331 351
99
- 97 333 347
100
- 98 336 343
101
- 99 338 338
102
- 100 341 334
103
- 101 343 330
104
- 102 345 325
105
- 103 347 320
106
- 104 349 316
107
- 105 351 311
108
- 106 353 306
109
- 107 355 302
110
- 108 357 298
111
- 109 360 294
112
- 110 362 290
113
- 111 364 286
114
- 112 366 282
115
- 113 367 277
116
- 114 370 273
117
- 115 372 269
118
- 116 374 265
119
- 117 377 262
120
- 118 378 257
121
- 119 380 253
122
- 120 381 249
123
- 121 383 245
124
- 122 385 241
125
- 123 387 237
126
- 124 389 233
127
- 125 391 229
128
- 126 394 226
129
- 127 395 222
130
- 128 400 220
131
- 129 406 219
132
- 130 414 218
133
- 131 420 216
134
- 132 428 215
135
- 133 435 214
136
- 134 441 212
137
- 135 452 212
138
- 136 478 219
139
- 137 487 219
140
- 138 495 217
141
- 139 501 214
142
- 140 506 211
143
- 141 512 209
144
- 142 515 205
145
- 143 519 201
146
- 144 521 197
147
- 145 523 193
148
- 146 527 190
149
- 147 530 186
150
- 148 532 182
151
- 149 535 178
152
- 150 538 174
153
- 151 542 171
154
- 152 545 167
155
- 153 547 163
156
- 154 549 159
157
- 155 552 155
158
- 156 555 152
159
- 157 560 148
160
- 158 563 145
161
- 159 568 142
162
- 160 576 139
163
- 161 578 135
164
- 162 581 131
165
- 163 584 128
166
- 164 587 124
167
- 165 591 121
168
- 166 594 117
169
- 167 597 113
170
- 168 600 110
171
- 169 602 106
172
- 170 603 102
173
- 171 607 98
174
- 172 608 95
175
- 173 611 91
176
- 174 613 87
177
- 175 615 83
178
- 176 617 80
179
- 177 620 76
180
- 178 623 73
181
- 179 625 69
182
- 180 627 65
183
- 181 630 62
184
- 182 632 58
185
- 183 635 55
186
- 184 637 51
187
- 185 639 48
188
- 186 641 44
189
- 187 642 41
190
- 188 644 37
191
- 189 646 34
192
- 190 649 30
193
- 191 651 27
194
- 192 652 23
195
- 193 654 20
196
- 194 656 16
197
- 195 658 13
198
- 196 659 10
199
- 197 666 6
200
- 198 673 3
201
- 199 679 0
 
1
  iter Passed Remaining
2
+ 0 2 537
3
+ 1 4 441
4
+ 2 6 415
5
+ 3 7 389
6
+ 4 9 379
7
+ 5 11 374
8
+ 6 13 367
9
+ 7 15 365
10
+ 8 17 368
11
+ 9 19 366
12
+ 10 21 362
13
+ 11 22 356
14
+ 12 24 348
15
+ 13 26 349
16
+ 14 28 349
17
+ 15 30 348
18
+ 16 31 343
19
+ 17 33 338
20
+ 18 35 333
21
+ 19 36 331
22
+ 20 38 328
23
+ 21 40 328
24
+ 22 42 324
25
+ 23 44 322
26
+ 24 45 320
27
+ 25 47 320
28
+ 26 50 320
29
+ 27 52 321
30
+ 28 54 320
31
+ 29 56 321
32
+ 30 58 321
33
+ 31 61 320
34
+ 32 63 319
35
+ 33 65 317
36
+ 34 66 314
37
+ 35 68 311
38
+ 36 70 308
39
+ 37 71 305
40
+ 38 73 303
41
+ 39 75 300
42
+ 40 77 298
43
+ 41 78 296
44
+ 42 80 293
45
+ 43 82 290
46
+ 44 83 289
47
+ 45 85 286
48
+ 46 87 284
49
+ 47 89 282
50
+ 48 90 279
51
+ 49 92 277
52
+ 50 94 274
53
+ 51 95 272
54
+ 52 97 270
55
+ 53 99 268
56
+ 54 101 266
57
+ 55 102 263
58
+ 56 104 262
59
+ 57 106 259
60
+ 58 107 256
61
+ 59 109 254
62
+ 60 110 252
63
+ 61 112 250
64
+ 62 114 248
65
+ 63 115 246
66
+ 64 117 244
67
+ 65 119 242
68
+ 66 120 240
69
+ 67 122 237
70
+ 68 124 235
71
+ 69 125 233
72
+ 70 127 231
73
+ 71 129 229
74
+ 72 131 228
75
+ 73 133 227
76
+ 74 135 225
77
+ 75 136 222
78
+ 76 138 220
79
+ 77 140 219
80
+ 78 157 241
81
+ 79 159 239
82
+ 80 161 237
83
+ 81 163 234
84
+ 82 165 233
85
+ 83 167 230
86
+ 84 168 228
87
+ 85 170 226
88
+ 86 172 224
89
+ 87 174 221
90
+ 88 175 219
91
+ 89 177 216
92
+ 90 178 214
93
+ 91 180 212
94
+ 92 182 209
95
+ 93 183 207
96
+ 94 185 205
97
+ 95 187 202
98
+ 96 188 200
99
+ 97 190 198
100
+ 98 192 196
101
+ 99 194 194
102
+ 100 195 191
103
+ 101 197 189
104
+ 102 198 187
105
+ 103 200 185
106
+ 104 202 183
107
+ 105 203 180
108
+ 106 205 179
109
+ 107 207 176
110
+ 108 209 174
111
+ 109 211 172
112
+ 110 212 170
113
+ 111 214 168
114
+ 112 216 166
115
+ 113 217 164
116
+ 114 219 162
117
+ 115 221 160
118
+ 116 223 158
119
+ 117 225 156
120
+ 118 226 154
121
+ 119 228 152
122
+ 120 230 150
123
+ 121 231 148
124
+ 122 233 146
125
+ 123 235 144
126
+ 124 236 142
127
+ 125 238 140
128
+ 126 240 138
129
+ 127 242 136
130
+ 128 243 134
131
+ 129 245 132
132
+ 130 247 130
133
+ 131 249 128
134
+ 132 251 126
135
+ 133 253 124
136
+ 134 254 122
137
+ 135 256 120
138
+ 136 258 118
139
+ 137 259 116
140
+ 138 261 114
141
+ 139 262 112
142
+ 140 264 110
143
+ 141 266 108
144
+ 142 268 106
145
+ 143 270 105
146
+ 144 271 103
147
+ 145 273 101
148
+ 146 275 99
149
+ 147 276 97
150
+ 148 278 95
151
+ 149 280 93
152
+ 150 282 91
153
+ 151 284 89
154
+ 152 286 87
155
+ 153 288 86
156
+ 154 290 84
157
+ 155 291 82
158
+ 156 293 80
159
+ 157 295 78
160
+ 158 296 76
161
+ 159 298 74
162
+ 160 300 72
163
+ 161 301 70
164
+ 162 303 68
165
+ 163 304 66
166
+ 164 306 65
167
+ 165 308 63
168
+ 166 310 61
169
+ 167 311 59
170
+ 168 313 57
171
+ 169 315 55
172
+ 170 316 53
173
+ 171 318 51
174
+ 172 320 49
175
+ 173 322 48
176
+ 174 324 46
177
+ 175 325 44
178
+ 176 327 42
179
+ 177 329 40
180
+ 178 331 38
181
+ 179 332 36
182
+ 180 334 35
183
+ 181 336 33
184
+ 182 338 31
185
+ 183 339 29
186
+ 184 341 27
187
+ 185 343 25
188
+ 186 344 23
189
+ 187 346 22
190
+ 188 348 20
191
+ 189 350 18
192
+ 190 352 16
193
+ 191 353 14
194
+ 192 355 12
195
+ 193 357 11
196
+ 194 359 9
197
+ 195 360 7
198
+ 196 362 5
199
+ 197 364 3
200
+ 198 366 1
201
+ 199 368 0
webapp/ensemble.py CHANGED
@@ -33,7 +33,7 @@ def select_top_models(results: dict, builders: dict, task: str, n: int = 3):
33
  Only includes models that have >0.5 ROC-AUC or >0.0 RΒ².
34
  """
35
  primary = "roc_auc" if task == "classification" else "r2"
36
- threshold = -1.0 # Always include models if they didn't error
37
 
38
  ranked = []
39
  for name in builders:
@@ -67,14 +67,11 @@ def run_voting_ensemble(top_pairs: list, X: pd.DataFrame, y: pd.Series,
67
  n_classes = int(y.nunique()) if task == "classification" else None
68
  fold_results = []
69
 
70
- # Pre-fit encoders on full X
71
- X_full_p, global_encoders = prep_fn(X)
72
-
73
  for tr_idx, val_idx in splits:
74
  Xtr, Xval = X.iloc[tr_idx], X.iloc[val_idx]
75
  ytr, yval = y.iloc[tr_idx], y.iloc[val_idx]
76
- Xtr_p, _ = prep_fn(Xtr, encoders=global_encoders)
77
- Xval_p, _ = prep_fn(Xval, encoders=global_encoders)
78
 
79
  t0 = time.perf_counter()
80
 
@@ -174,14 +171,11 @@ def run_stacking_ensemble(sklearn_pairs: list, X: pd.DataFrame, y: pd.Series,
174
 
175
  fold_results = []
176
 
177
- # Pre-fit encoders on full X
178
- X_full_p, global_encoders = prep_fn(X)
179
-
180
  for tr_idx, val_idx in splits:
181
  Xtr, Xval = X.iloc[tr_idx], X.iloc[val_idx]
182
  ytr, yval = y.iloc[tr_idx], y.iloc[val_idx]
183
- Xtr_p, _ = prep_fn(Xtr, encoders=global_encoders)
184
- Xval_p, _ = prep_fn(Xval, encoders=global_encoders)
185
 
186
  estimators = [(name, builder(task)) for name, builder in sklearn_pairs]
187
 
 
33
  Only includes models that have >0.5 ROC-AUC or >0.0 RΒ².
34
  """
35
  primary = "roc_auc" if task == "classification" else "r2"
36
+ threshold = 0.50 if task == "classification" else 0.0
37
 
38
  ranked = []
39
  for name in builders:
 
67
  n_classes = int(y.nunique()) if task == "classification" else None
68
  fold_results = []
69
 
 
 
 
70
  for tr_idx, val_idx in splits:
71
  Xtr, Xval = X.iloc[tr_idx], X.iloc[val_idx]
72
  ytr, yval = y.iloc[tr_idx], y.iloc[val_idx]
73
+ Xtr_p, encoders = prep_fn(Xtr)
74
+ Xval_p, _ = prep_fn(Xval, encoders=encoders)
75
 
76
  t0 = time.perf_counter()
77
 
 
171
 
172
  fold_results = []
173
 
 
 
 
174
  for tr_idx, val_idx in splits:
175
  Xtr, Xval = X.iloc[tr_idx], X.iloc[val_idx]
176
  ytr, yval = y.iloc[tr_idx], y.iloc[val_idx]
177
+ Xtr_p, encoders = prep_fn(Xtr)
178
+ Xval_p, _ = prep_fn(Xval, encoders=encoders)
179
 
180
  estimators = [(name, builder(task)) for name, builder in sklearn_pairs]
181
 
webapp/main.py CHANGED
@@ -1,43 +1,27 @@
1
- import sys
 
 
 
2
  import io, os
3
- import logging
4
  from pathlib import Path
5
  from dotenv import load_dotenv
 
 
 
 
6
  import pandas as pd
7
- import numpy as np
8
  from fastapi import FastAPI, File, UploadFile, Form, HTTPException
9
- from fastapi.responses import JSONResponse, FileResponse
10
  from fastapi.staticfiles import StaticFiles
11
 
12
- # Flexible imports to support both HF Space (root) and local execution (inside webapp)
13
  try:
14
- from webapp.benchmark import run_benchmark, infer_task, BUILDERS, _prep, _encode_target
15
- except (ImportError, ModuleNotFoundError):
16
- from benchmark import run_benchmark, infer_task, BUILDERS, _prep, _encode_target
17
-
18
- # Setup logging
19
- logging.basicConfig(level=logging.INFO)
20
- logger = logging.getLogger(__name__)
21
-
22
- # Load .env
23
- BASE_DIR = Path(__file__).resolve().parent.parent
24
- load_dotenv(BASE_DIR / "webapp" / ".env")
25
-
26
- # Verify Secrets on startup
27
- hf_token = os.environ.get('HUGGING_FACE_HUB_TOKEN')
28
- logger.info(f"TABPFN_TOKEN status: {'SET' if os.environ.get('TABPFN_TOKEN') else 'MISSING'}")
29
- logger.info(f"HF_TOKEN status: {'SET' if hf_token else 'MISSING'}")
30
-
31
- if hf_token:
32
- try:
33
- from huggingface_hub import login
34
- login(token=hf_token, add_to_git_credential=False)
35
- logger.info("Successfully logged into Hugging Face Hub.")
36
- except Exception as e:
37
- logger.warning(f"Hugging Face login failed: {e}")
38
 
39
  # ── Config ─────────────────────────────────────────────────────────────────────
40
- MAX_FILE_BYTES = int(os.getenv("MAX_FILE_SIZE_MB", "5")) * 1024 * 1024
 
41
  app = FastAPI(title="SAP RPT-1 Benchmarking API", version="1.0.0")
42
 
43
  # ── Static files (frontend) ────────────────────────────────────────────────────
@@ -194,15 +178,9 @@ async def benchmark(
194
  feature_types[col] = "categorical"
195
  result["dataset_info"]["feature_types"] = feature_types
196
 
197
- # Add a sample row for the playground preview
198
- result["dataset_info"]["preview"] = [df.head(1).fillna("").to_dict("records")[0]]
199
-
200
  # Cache the Best Overall model for the Live Playground
201
  best_name = result["recommendation"]["recommendations"]["best_overall"]["model"]
202
- # Subsample for training the champion model if too large (Demo speed)
203
- if len(df) > 1000:
204
- df = df.sample(n=1000, random_state=42)
205
-
206
  X = df.drop(columns=[target_col])
207
  y_raw = df[target_col]
208
  task = result["dataset_info"]["task"]
@@ -229,13 +207,11 @@ async def benchmark(
229
  "name": best_name,
230
  "task": task,
231
  "features": list(X.columns),
232
- "labels": [str(c) for c in le.classes_] if le else None,
233
  "encoders": feat_encoders # Store these for the /predict endpoint!
234
  }
235
 
236
  except Exception as e:
237
- import traceback
238
- traceback.print_exc()
239
  raise HTTPException(500, f"Benchmarking failed: {e}")
240
 
241
  return JSONResponse(result)
@@ -253,19 +229,15 @@ async def predict(data: dict):
253
  try:
254
  # Convert input dict to DataFrame
255
  input_df = pd.DataFrame([data])
256
- # Ensure column order matches training, filling missing with 0/empty
257
- for col in CHAMPION_INFO["features"]:
258
- if col not in input_df.columns:
259
- input_df[col] = 0
260
  input_df = input_df[CHAMPION_INFO["features"]]
261
 
 
262
  # Use the EXACT same encoders that were used during training
263
  X_test, _ = _prep(input_df, encoders=CHAMPION_INFO.get("encoders"))
264
 
265
- logger.info(f"Predicting for {CHAMPION_INFO['name']}...")
266
-
267
  if CHAMPION_INFO["task"] == "classification":
268
- raw_pred = np.array(CHAMPION_MODEL.predict(X_test))
269
  # Flatten if nested (CatBoost/Sklearn sometimes return [[val]] or [val])
270
  pred_val = raw_pred.ravel()[0]
271
  pred_idx = int(pred_val)
@@ -286,7 +258,7 @@ async def predict(data: dict):
286
  "labels": CHAMPION_INFO["labels"]
287
  }
288
  else:
289
- raw_pred = np.array(CHAMPION_MODEL.predict(X_test))
290
  pred = float(raw_pred.ravel()[0])
291
  return {"prediction": pred}
292
 
 
1
+ """
2
+ main.py β€” FastAPI backend for the SAP RPT-1 Benchmarking Web App.
3
+ """
4
+
5
  import io, os
 
6
  from pathlib import Path
7
  from dotenv import load_dotenv
8
+
9
+ # Load .env before anything else so HF_TOKEN is available to benchmark.py
10
+ load_dotenv(Path(__file__).parent / ".env")
11
+
12
  import pandas as pd
 
13
  from fastapi import FastAPI, File, UploadFile, Form, HTTPException
14
+ from fastapi.responses import JSONResponse
15
  from fastapi.staticfiles import StaticFiles
16
 
 
17
  try:
18
+ from benchmark import run_benchmark, infer_task
19
+ except ImportError:
20
+ from webapp.benchmark import run_benchmark, infer_task
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  # ── Config ─────────────────────────────────────────────────────────────────────
23
+ MAX_FILE_BYTES = int(os.getenv("MAX_FILE_SIZE_MB", "5")) * 1024 * 1024 # default 5 MB
24
+
25
  app = FastAPI(title="SAP RPT-1 Benchmarking API", version="1.0.0")
26
 
27
  # ── Static files (frontend) ────────────────────────────────────────────────────
 
178
  feature_types[col] = "categorical"
179
  result["dataset_info"]["feature_types"] = feature_types
180
 
 
 
 
181
  # Cache the Best Overall model for the Live Playground
182
  best_name = result["recommendation"]["recommendations"]["best_overall"]["model"]
183
+ from benchmark import BUILDERS, _prep, _encode_target
 
 
 
184
  X = df.drop(columns=[target_col])
185
  y_raw = df[target_col]
186
  task = result["dataset_info"]["task"]
 
207
  "name": best_name,
208
  "task": task,
209
  "features": list(X.columns),
210
+ "labels": list(le.classes_) if le else None,
211
  "encoders": feat_encoders # Store these for the /predict endpoint!
212
  }
213
 
214
  except Exception as e:
 
 
215
  raise HTTPException(500, f"Benchmarking failed: {e}")
216
 
217
  return JSONResponse(result)
 
229
  try:
230
  # Convert input dict to DataFrame
231
  input_df = pd.DataFrame([data])
232
+ # Ensure column order matches training
 
 
 
233
  input_df = input_df[CHAMPION_INFO["features"]]
234
 
235
+ from benchmark import _prep
236
  # Use the EXACT same encoders that were used during training
237
  X_test, _ = _prep(input_df, encoders=CHAMPION_INFO.get("encoders"))
238
 
 
 
239
  if CHAMPION_INFO["task"] == "classification":
240
+ raw_pred = CHAMPION_MODEL.predict(X_test)
241
  # Flatten if nested (CatBoost/Sklearn sometimes return [[val]] or [val])
242
  pred_val = raw_pred.ravel()[0]
243
  pred_idx = int(pred_val)
 
258
  "labels": CHAMPION_INFO["labels"]
259
  }
260
  else:
261
+ raw_pred = CHAMPION_MODEL.predict(X_test)
262
  pred = float(raw_pred.ravel()[0])
263
  return {"prediction": pred}
264
 
webapp/requirements.txt CHANGED
@@ -6,9 +6,7 @@ xgboost>=2.0.0
6
  lightgbm>=4.0.0
7
  catboost>=1.2.0
8
  scikit-learn>=1.3.0
9
- scipy>=1.10.0
10
  pandas>=2.0.0
11
  numpy>=1.24.0
12
- tabpfn>=2.0.0
13
  huggingface_hub
14
- sentence-transformers
 
6
  lightgbm>=4.0.0
7
  catboost>=1.2.0
8
  scikit-learn>=1.3.0
 
9
  pandas>=2.0.0
10
  numpy>=1.24.0
11
+ tabpfn>=7.1.1
12
  huggingface_hub
 
webapp/sap_rpt1.egg-info/SOURCES.txt DELETED
@@ -1,15 +0,0 @@
1
- README.md
2
- setup.py
3
- webapp/models/__init__.py
4
- webapp/models/autogluon_wrapper.py
5
- webapp/models/base_wrapper.py
6
- webapp/models/baseline_wrappers.py
7
- webapp/models/sap_rpt1_hf_wrapper.py
8
- webapp/models/sap_rpt1_wrapper.py
9
- webapp/models/tabicl_wrapper.py
10
- webapp/models/tabpfn_wrapper.py
11
- webapp/sap_rpt1.egg-info/PKG-INFO
12
- webapp/sap_rpt1.egg-info/SOURCES.txt
13
- webapp/sap_rpt1.egg-info/dependency_links.txt
14
- webapp/sap_rpt1.egg-info/requires.txt
15
- webapp/sap_rpt1.egg-info/top_level.txt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
webapp/sap_rpt1.egg-info/top_level.txt DELETED
@@ -1 +0,0 @@
1
- models
 
 
webapp/static/app.js CHANGED
@@ -502,8 +502,7 @@ function renderPlayground(datasetInfo, bestOverall, task) {
502
  if (!form || !bestOverall) return;
503
  form.innerHTML = "";
504
 
505
- const targetCol = String(datasetInfo.target_col || "").trim().toLowerCase();
506
- const features = (datasetInfo.columns || []).filter(c => String(c).trim().toLowerCase() !== targetCol);
507
  const preview = datasetInfo.preview ? datasetInfo.preview[0] : {};
508
 
509
  features.forEach(f => {
@@ -553,7 +552,7 @@ function renderPlayground(datasetInfo, bestOverall, task) {
553
  }
554
 
555
  if (task === "classification") {
556
- valueEl.textContent = (res.prediction !== undefined && res.prediction !== null) ? res.prediction : "β€”";
557
  subEl.textContent = `Most likely class (via ${bestOverall.model})`;
558
 
559
  if (res.probabilities && res.labels) {
 
502
  if (!form || !bestOverall) return;
503
  form.innerHTML = "";
504
 
505
+ const features = datasetInfo.columns || [];
 
506
  const preview = datasetInfo.preview ? datasetInfo.preview[0] : {};
507
 
508
  features.forEach(f => {
 
552
  }
553
 
554
  if (task === "classification") {
555
+ valueEl.textContent = res.prediction || "β€”";
556
  subEl.textContent = `Most likely class (via ${bestOverall.model})`;
557
 
558
  if (res.probabilities && res.labels) {