Skip to content

anshulg954/TabAdjust

Repository files navigation

TabAdjust

Adjuster This! — Learning to correct PV power forecasts with TabPFN and XGBoost, benchmarked against a rule-based OCF adjuster.

This repository provides a modular pipeline to load and audit PV data, engineer features (including TabPFN-TS), train adjusters, and evaluate Mean Absolute Error (MAE) across dates, hours, and horizons. It supports transductive daily retraining (past-week -> current-day) and fixed historical splits.


📑 Key Features

  • Models: TabPFN (time-series & tabular/Reg), XGBoost, AutoGluon (optional), and an OCF-style baseline.
  • Evaluation: Per-date, per-hour, per-horizon MAE; overall summaries; export helpers for fixed windows.
  • Data Audits: Duplicate & missing (timestamp, horizon) grid checks; optional grid filling.
  • Modularity: Clean separation of data loading, preprocessing, feature selection, splits, modeling, and evaluation.
  • CLI: run.py to reproduce rolling evaluations with a few flags.

🔖 Project Structure

TabAdjust/
├─ core/
│ ├─ feature_selection.py # Permutation importance & selectors (XGB-backed)
│ ├─ preprocessing.py # Model-specific prep; lag/time features
│ └─ splits.py # Holdout builders (rolling & fixed helpers)
│
├─ data/
│ ├─ load.py # CSV loader + duplicate/missing grid audit
│ └─ preprocess.py # High-level preprocessing → ts_data + df
│
├─ evaluation/
│ ├─ export_fixed.py # Helpers to export MAE tables for fixed splits
│ ├─ metrics.py # evaluate_adjusted_forecast / evaluate_ocf_adjuster
│ ├─ runner.py # Main rolling evaluator (daily, TabPFN-TS etc.)
│ └─ final_results/ # Plots & MAE tables produced during studies
│
├─ models/
│ ├─ autogluon_tabular.py # (optional) AG Tabular wrappers
│ ├─ tabadjust.py # Unified dispatcher (TabPFN / XGB / OCF)
│ ├─ tabadjust_ts.py # TS variant glue (TabPFN-TS)
│ ├─ tabpfn_reg.py # TabPFN (Regressor) per-horizon/day runs
│ └─ xgb_reg.py # XGB regressor wrappers & tuned configs
│
├─ utils/
│ └─ utils.py # Pretty tables, diagnostics (optional)
│
├─ outputs/ # Run artifacts (created at runtime)
├─ run.py # CLI entrypoint
├─ .gitattributes # LFS settings (large artifacts)
├─ .gitignore # Ignore AutogluonModels/, checkpoints, etc.
└─ adjuster_dataset_gsoc_v2.csv # Example dataset (schema described below)

Tip: Large training directories (e.g., AutogluonModels/) are ignored by Git; re-train as needed.


🧾 Data Description (schema)

Minimum expected columns (UTC timestamps):

  • forecast_period_start_datetime_utc (datetime, 30-min cadence)
  • forecast_horizon_minutes ∈ {30, 60, …, 480}
  • forecasted_pv_generation_MW
  • actual_pv_generation_MW
  • forecast_error_MW = actual − forecasted (if not present, compute)
  • Optional: creation/end timestamps, calendar fields (day-of-week, etc.)

Audits: data/load.py parses timestamps, coerces horizon to Int64, reports exact duplicate (time, horizon) pairs, builds the full half-hour × horizon grid to flag missing keys, and (optionally) appends NaN rows so downstream transforms see a complete key space.


🚀 Usage

1) Clone and Export

git clone https://github.com/anshulg954/TabAdjust.git
cd TabAdjust

2) Create & activate a virtual environment and install dependencies

python -m venv adjuster_env
source adjuster_env/bin/activate
pip install -r requirements.txt

It is recommened to use TabPFN-TS or GPU TabPFN(Reg), install a compatible PyTorch build for your platform or using TabPFN-Client from Priorlabs can also serve as an alternative.

3) Running the pipeline : Rolling (daily) evaluation — TabPFN-TS / XGBoost

Runs the transductive setup (past-week → current-day) across a date range, producing per-date MAE tables.

TabPFN-TS (past-week → current-day)

python run.py \
  --input_csv example.csv \
  --test_start_date 2024-08-01 \
  --test_end_date   2025-05-31 \
  --model_type tabpfn \
  --train_days 7 \
  --use_tabpfn_ts

XGBoost with TabPFN-TS features (same split)

python run.py \
  --input_csv example.csv \
  --test_start_date 2024-08-01 \
  --test_end_date   2025-05-31 \
  --model_type xgboost \
  --train_days 7 \
  --use_tabpfn_ts

Useful flags (rolling mode)

--start_time HH:MM --end_time HH:MM to limit hours (e.g., 04:30–21:00 daylight only)

--max_lag_days 7 adds 7-day lags on top of TS features (if you want hybrid features)

--output_dir outputs controls where artifacts are written

Outputs (rolling mode)

Results are saved to:

outputs/
└─ results/TIMESTAMP/model_type/test_start_date_YYYYMMDD/
   ├─ avg_errors_all_dates.csv
   ├─ avg_errors_per_date.csv
   ├─ avg_errors_per_horizon.csv
   ├─ avg_errors_per_hour.csv
   └─ avg_errors_per_horizon_hour.csv

4) Fixed-window studies — TabAdjust (XGB / TabPFN(Reg) / OCF / AutoGluon)

Use this mode to use fixed historical split for XGB/AG; TabPFN(Reg) uses a rolling lookback per day inside the test period.

In this mode, omit --use_tabpfn_ts. The script will:

  • Preprocess raw features,
  • Build a fixed train/test split from your date arguments,
  • Run the models you select via --models (or --model_type if --models is not provided).

Example usage for XGB + OCF for Jan–Feb 2025 (train: Aug–Dec 2024)

python run.py \
  --input_csv example.csv \
  --train_start_date 2024-08-01 \
  --train_end_date   2024-12-31 \
  --test_start_date  2025-01-01 \
  --test_end_date    2025-02-28 \
  --models xgboost ocf \
  --train_days 15 \
  --max_lag_days 7

Using Add TabPFN(Reg) (rolling 15-day lookback inside the test range)

python run.py \
  --input_csv example.csv \
  --train_start_date 2024-08-01 \
  --train_end_date   2024-12-31 \
  --test_start_date  2025-01-01 \
  --test_end_date    2025-02-28 \
  --models xgboost tabpfn ocf \
  --train_days 15 \
  --tabpfn_min_train_rows 100 \
  --tabpfn_max_train_rows 10000

Using AutoGluon (optional)

python run.py \
  --input_csv example.csv \
  --train_start_date 2024-08-01 \
  --train_end_date   2024-12-31 \
  --test_start_date  2025-01-01 \
  --test_end_date    2025-02-28 \
  --models autogluon ocf \
  --ag_use_gpu \
  --ag_time_limit 1800 \
  --ag_train_path outputs/ag_model \
  --ag_load_path  outputs/ag_model

Daylight-only variant can be used by setting the start-time and the end time

python run.py \
  ... \
  --start_time 04:30 \
  --end_time   21:00

Outputs (fixed-window mode)

Results are saved to:

outputs/
└─ results/TIMESTAMP>/train_daysd/
   ├─ mae____by_date.csv
   ├─ mae____by_hour.csv
   ├─ mae____by_horizon.csv
   ├─ mae____overall.csv
   └─ rows___.csv        # per-row dump for custom plots

Where is a hyphen-joined list (e.g., xgboost-ocf, xgboost-tabpfn-ocf).

Notable Experiments

As a part of this project, I ran 12 experiments varying (i) feature space, (ii) train/test policy for XGB/AG, (iii) TabPFN(Reg) lookback, and (iv) daylight filtering (04:30–21:00) using the similar functions in the pipeline.

  • Experiments 1–2 (Transductive, daily retrain):
    Both TabPFN-TS and XGB retrain each day on the past week, tested on the current day.
    Features: TabPFN-TS only (Exp. 1), then TabPFN-TS + classical TS + 7-day lags (Exp. 2).

  • Experiments 3–12 (Fixed splits for XGB/AG):
    XGB/AG train on a fixed historical split (72/28 → 90/10 in later experiments), tested on a future window;
    TabPFN(Reg) always uses a rolling 15-day lookback and predicts the current day within the same evaluation period.
    Even-numbered experiments apply time filtering (04:30–21:00).
    Features: basic TS + 7-day lags (no TabPFN-TS).

Most important findings (from analysis):

  • OCF consistently improves on Baseline across all windows — a robust default.
  • TabPFN(Reg) with 15–30 day lookbacks is the most reliable winner in Jan–Apr windows, often 5–9% better than OCF by MAE, especially around midday peaks and across most horizons.
  • XGB (Tuned) becomes competitive/winning in May windows (Exp. 11–12), with ~5–6% gains over OCF; earlier windows show higher variance and several OCF wins.
  • AutoGluon (default presets) trails in this dataset/split; targeted presets or feature constraints may be needed.

🖼️ Visual Summary

Improvement % over OCF per Experiment (Best TabPFN vs Best XGB)

Improvement over OCF

TabPFN (blue) delivers positive improvements in many experiments; XGB (orange) improves in late windows but underperforms OCF in several early ones.

For more detailed description about experiments and results, please refer to analysis.md


Conclusion

Across a broad set of splits and seasons, OCF reliably improves over Baseline. TabPFN(Reg) with 15–30 day lookbacks is the most dependable, delivering meaningful daytime and horizon-wise MAE reductions. XGB (Tuned) can perform well in the latest windows, however requires large amount of historical data. The pipeline here provides a modular framework to compare, diagnose, and deploy the best adjuster for any PV Forecasting Adjust.

📚 References

  • PVNet (Open Climate Fix)
    Primary repository and documentation for OCF’s multimodal PV forecasting model (NWP + satellite + metadata).
    • PVNet main repo: openclimatefix/PVNet.

  • TabPFN-TS (Time-Series wrapper around TabPFN)
    Time-series package that frames forecasting as tabular regression with lightweight feature engineering.
    • Official code: PriorLabs/tabpfn-ts

  • TabPFN (Tabular Prior-Data Fitted Networks)
    Foundation model for small/medium tabular tasks; in-context learning via a pretrained Transformer.
    • Original paper: TabPFN: A Transformer That Solves Small Tabular Classification Problems in a Second (arXiv:2207.01848).
    • Nature paper: Accurate predictions on small data with a tabular foundation model (Nature).
    • Official code: Priorlabs/tabpfn.


Happy Adjusting!

About

Adjuster This! TabPFN for Solar Forecast Error Adjustment

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published