Model Playground¶
playground
¶
Local model-dev loop — try any model on sample data, offline.
This is the on-ramp for a data scientist opening the repo: pick a model, get a small
sample dataset, run the real worker cell, and read the prediction frame + metric panel —
no GCP, no config files. The notebook (notebooks/00_model_playground.ipynb) and the CLI
(python -m scale_forecasting.playground) are both thin skins over the functions here,
so the dev loop and production run the identical code path: sample → validate →
worker.run_cell.
Adding a model needs no change here — available_models reads the factory registry,
so a new file under models/ that ends in register(...) appears automatically.
Public surface: available_models, model_catalog, metric_catalog, sample_data,
build_config, run_model, summarize.
BakeOff
dataclass
¶
A local multi-model bake-off on one series: the leaderboard + everything to plot it.
leaderboard is one row per model — base models and the ensemble pseudo-models —
ranked by the decision metric. predictions is the long-format future forecast for
every model (base + ensemble) so the notebook can overlay them. series is the history
they were fit on; config is the frozen RunConfig that drove the whole thing; oof
holds the combined base + ensemble out-of-fold rows for FVA, horizon-decay, and bias audits.
bias_df
¶
bias_report_df
¶
Audit each bake-off model for directional bias and Trigg Tracking Signal.
Source code in src/scale_forecasting/playground.py
exceptions_df
¶
Build the Top-N exception triage queue across all models in this bake-off.
Source code in src/scale_forecasting/playground.py
export_report
¶
Export a self-contained interactive .html report for this bake-off.
Source code in src/scale_forecasting/playground.py
fva_df
¶
Compute Forecast Value Added (FVA) and Diebold–Mariano p-values across models.
Source code in src/scale_forecasting/playground.py
horizon_decay_df
¶
Compute lead-time accuracy decay by horizon step across all bake-off models.
Source code in src/scale_forecasting/playground.py
inventory_policy_df
¶
inventory_policy_df(
*,
inventory_df=None,
model_name=None,
model_type=None,
lead_time=7.0,
lead_time_std=0.0,
review_period=0.0,
service_level=0.95,
fill_rate=None,
on_hand=0.0,
on_order=0.0,
backorders=0.0,
holding_cost=1.0,
stockout_cost=9.0,
min_order_qty=0.0,
order_multiple=0.0,
)
Translate bake-off forecasts across all models into operational inventory policies.
Source code in src/scale_forecasting/playground.py
plot_inventory_policy
¶
plot_inventory_policy(
*,
inventory_df=None,
model_name=None,
model_type=None,
lead_time=7.0,
lead_time_std=0.0,
review_period=0.0,
service_level=0.95,
fill_rate=None,
on_hand=0.0,
on_order=0.0,
backorders=0.0,
holding_cost=1.0,
stockout_cost=9.0,
min_order_qty=0.0,
order_multiple=0.0,
max_rows=15,
ax=None,
title=None,
)
Plot Reorder Points (ROP), Safety Stock (SS), and Order Quantities across models.
Source code in src/scale_forecasting/playground.py
rollup_time
¶
Aggregate bake-off future predictions to coarser calendar periods with AR(1) bounds.
Source code in src/scale_forecasting/playground.py
simulate_scenarios
¶
Run counterfactual covariate scenarios across this bake-off's series and models.
Source code in src/scale_forecasting/playground.py
PlaygroundRun
dataclass
¶
One model run on one series — the CellResult plus the series it ran on.
bias_df
¶
bias_report_df
¶
Compute directional bias and Trigg Tracking Signal for this run's backtest OOF.
Source code in src/scale_forecasting/playground.py
exceptions_df
¶
Return the exception triage queue for this playground run.
Source code in src/scale_forecasting/playground.py
export_report
¶
Export a self-contained .html report for this playground run.
Source code in src/scale_forecasting/playground.py
horizon_decay_df
¶
Compute lead-time error decay across horizon steps for this run's backtest OOF.
Source code in src/scale_forecasting/playground.py
inventory_policy_df
¶
inventory_policy_df(
*,
inventory_df=None,
lead_time=7.0,
lead_time_std=0.0,
review_period=0.0,
service_level=0.95,
fill_rate=None,
on_hand=0.0,
on_order=0.0,
backorders=0.0,
holding_cost=1.0,
stockout_cost=9.0,
min_order_qty=0.0,
order_multiple=0.0,
)
Translate this run's calibrated forecasts into an operational inventory policy.
Source code in src/scale_forecasting/playground.py
plot_inventory_policy
¶
plot_inventory_policy(
*,
inventory_df=None,
lead_time=7.0,
lead_time_std=0.0,
review_period=0.0,
service_level=0.95,
fill_rate=None,
on_hand=0.0,
on_order=0.0,
backorders=0.0,
holding_cost=1.0,
stockout_cost=9.0,
min_order_qty=0.0,
order_multiple=0.0,
ax=None,
title=None,
)
Plot Reorder Point (ROP), Safety Stock (SS), and Order Quantity for this run.
Source code in src/scale_forecasting/playground.py
rollup_time
¶
Aggregate this run's future predictions to coarser calendar buckets with AR(1) bounds.
Source code in src/scale_forecasting/playground.py
simulate_scenarios
¶
Run counterfactual future covariate scenarios on this single-series run.
Source code in src/scale_forecasting/playground.py
available_models
¶
Registered model names, sorted (the factory is the source of truth).
BigQuery-native models run as SQL in BigQuery, not in a local cell, so they're
excluded by default — the playground runs the Python models offline. Pass
installed_only=True to filter out models whose optional Python package is
not installed in the current environment.
Source code in src/scale_forecasting/playground.py
bakeoff
¶
bakeoff(
data=None,
*,
ts_id=None,
models=None,
freq="D",
horizon=28,
n_folds=3,
calculated="inverse_error",
learned="nnls",
with_exog=False,
future_covariates=None,
past_covariates=None,
static_covariates=None,
include_univariate_baselines=False,
ablation_modes=None,
ablation_models=None,
variant_policy="best_per_base_model",
model_params=None,
floor=None,
cap=None,
integer_rounding="none",
quantiles=None,
)
Run several models head-to-head on one series and add two ensembles — via the framework.
The playground's showcase of the whole pipeline offline: it runs every model in
models on one series with backtesting on (worker.run_cell, the same cell a
100k run executes), then builds one calculated and one learned ensemble by calling
the exact framework functions the real ensemble stage uses — no reimplementation:
- calculated (default
inverse_error):ensembler.combine_calculatedblends the base future forecasts, weighting by1/decision_metricfrom the backtest. - learned (default
nnls):ensembler.fit_learnedtrains the meta-learner on the base backtest OOF, thenensemble_run._apply_weightsapplies the weights. - scoring:
ensembler.combine_oof+metrics.compute_metrics/worker.rollup_metricsscore every ensemble on the OOF window — the identical pathensemble_run.run_ensemblesuses, minus the BigQuery I/O.
Because it drives real framework code, the leaderboard here is what a scaled run would
produce for the same series. models defaults to a fast, reliable subset; pass your own
(see available_models) to compare any Python models. Returns a BakeOff.
Source code in src/scale_forecasting/playground.py
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | |
build_config
¶
build_config(
model,
*,
freq="D",
horizon=28,
backtest=False,
with_exog=False,
static_covariates=None,
future_covariates=None,
past_covariates=None,
floor=None,
cap=None,
integer_rounding="none",
quantiles=None,
)
A minimal RunConfig for running model on sample_data.
Wires the generator's column names (ts_id/ds/y, and price_index as the
exog role when with_exog=True) so the config matches the sample panel out of the box.
backtest turns on a small 3-fold CV so the metric panel is populated (otherwise metrics
are NaN by design — full-fit runs don't score themselves).
Source code in src/scale_forecasting/playground.py
metric_catalog
¶
Every registered evaluation metric with its direction and input requirements.
Columns: metric, kind, direction, needs_intervals, needs_train_history,
needs_seasonal_period, mean_optimal.
Source code in src/scale_forecasting/playground.py
model_catalog
¶
Every registered model with the runtimes it can run on — the whole suite, one table.
One row per model (Python, Vertex AI AutoML, and BigQuery-native), so the story is
complete: which model runs where, what covariates it accepts, and whether it emits
two-tier feature attributions (explainability). The flags are derived from the model's
class metadata, not a hand-maintained list, so a new model file shows up here automatically:
- Python-runtime models run the identical cell code (
worker.run_cell) on every Python compute —local(this playground),spark(Dataproc fan-out),ray(Ray on Vertex or GKE),vertex(Vertex CustomJob),gce(GCE Single-VM), andgke(GKE Indexed Jobs). - Vertex AI AutoML models (
runtime == "vertex_automl") run global cross-series Tabular Workflows or AutoML training jobs in the cloud (engines/automl_engine) and also provide an offline panel ridge approximation for local sandbox testing. - BigQuery-native models run only as SQL in
bigquery(engines/bigquery_engine); they can't run in a local/Spark/Ray Python cell (their in-process fit/predict raise).
Columns: model, family, runtime, package, package_url, available, local, spark, ray, gpu,
vertex_automl, bigquery, exog, future_covariates, past_covariates, static_covariates,
explainability, global_mode, hybrid_mode.
Source code in src/scale_forecasting/playground.py
run_model
¶
run_model(
model,
data=None,
*,
ts_id=None,
freq="D",
horizon=28,
backtest=False,
with_exog=False,
future_covariates=None,
floor=None,
cap=None,
integer_rounding="none",
quantiles=None,
)
Run one model on one series and return the result (validates first).
data defaults to a fresh sample_data panel (matching freq/with_exog).
The whole panel is validated up front (validation.validate_panel) so a shape
problem fails fast with a clear message — the same guard a real run uses. Then a single
series (ts_id, or the first one) is handed to worker.run_cell, exactly as an
engine would. run_cell never raises: a model failure comes back as an error cell.
Source code in src/scale_forecasting/playground.py
sample_data
¶
sample_data(
*,
n_series=3,
history=730,
freq="D",
with_exog=False,
with_hierarchy=False,
seed=_SAMPLE_SEED,
)
A small deterministic sample panel from the real generator.
Same code path as the shipped 100k dataset, so what you see locally is what runs at
scale. Columns: ts_id, archetype, ds, y (+ region, category when with_hierarchy
or with_exog, and promo_flag, price_index, temperature when with_exog).
Defaults to 3 series × 2 years daily — enough to show trend + seasonality + intervals.
Source code in src/scale_forecasting/playground.py
summarize
¶
A compact human-readable summary of a run — for the CLI and notebook printout.