BEACON_FORECAST / README.md
Darkweb007's picture
Fix emoji field for HF Space validation
d31f070
|
Raw
History Blame Contribute Delete
4.89 kB

A newer version of the Streamlit SDK is available: 1.59.2

Upgrade
metadata
title: BEACON FORECAST
emoji: πŸ“ˆ
colorFrom: yellow
colorTo: gray
sdk: streamlit
sdk_version: 1.38.0
python_version: '3.10'
app_file: app.py
pinned: false

Beacon Forecast β€” Adaptive Demand Forecaster with Drift Detection

Portfolio project 5 of 5 β€” a demo response to the "edge case breakage" problem retail forecasting faces: rigid models that assume tomorrow looks like yesterday break when a supply shock, economic shift, or extreme weather event changes the underlying demand pattern, causing over-stocking or shortages until someone notices and manually retrains.

⚠️ All data in this project is synthetic. data/sku_demand.csv is generated by generate_synthetic_data.py: 4 SKUs, 2 years of daily data, with trend, weekly seasonality, and yearly seasonality. One SKU (SKU-004-ELECTRONICS) has an injected supply-shock event at day 500 (a sudden ~42% demand drop with a slow, partial 70-day recovery) to exercise the drift-detection pipeline. No real Walmart, retailer, or sales data is used.

Why this exists

A forecaster that's accurate on stable historical data can still be dangerously wrong the week a real disruption hits, because it keeps predicting off stale assumptions until someone manually intervenes. This project closes that loop automatically: the pipeline watches its own forecast errors day by day, and the moment they drift from what's normal for that model, it retrains itself on the newest data window without waiting for a human to notice.

Architecture

daily SKU demand (synthetic, walked forward day by day)
    |
    v
Forecaster                    <- forecasting/model.py
    trend + weekly seasonality + yearly Fourier terms, fit with Ridge
    regression (regularized to stay stable when retrained on short windows --
    a real bug caught during testing: plain OLS produced wildly unstable
    trend coefficients that exploded on extrapolation)
    |
    v
One-step-ahead forecast, day by day
    |
    v
Drift monitor                 <- forecasting/drift.py
    every 5 days, z-test comparing the last 14 days of forecast error
    against the baseline error distribution from right after the last
    (re)training; a Kolmogorov-Smirnov test is also computed as a
    secondary check on error *shape*, not just mean
    |
    v
    |z| > 4.0 ? ---- no ----> keep current model, keep monitoring
        |
       yes
        v
    Automatic retrain on the most recent 120 days
    <- stand-in for an Airflow DAG / AWS Lambda retrain trigger

Try it

pip install -r requirements.txt
streamlit run app.py

Pick a SKU in the sidebar. Three tabs: actual vs. forecast over the full 2-year walk-forward simulation (with retrain events marked), the drift monitor's z-score history, and a log of every automatic retrain with its triggering statistics.

Compare SKU-004-ELECTRONICS (has the injected shock) against any other SKU: the shock triggers a retrain within days, with a clearly larger z-score than routine periodic retrains. The other SKUs also retrain periodically as ordinary forecast staleness accumulates from a lightweight linear model β€” a legitimate, expected MLOps pattern, not just noise: even without an external shock, a simple model drifts stale over time and benefits from periodic refitting.

Project structure

demand-forecaster/
β”œβ”€β”€ app.py                        # Streamlit UI
β”œβ”€β”€ pipeline.py                   # walk-forward simulation + drift-triggered retraining
β”œβ”€β”€ generate_synthetic_data.py    # produces data/sku_demand.csv
β”œβ”€β”€ forecasting/
β”‚   β”œβ”€β”€ model.py                  # trend + seasonality forecaster (Ridge regression)
β”‚   └── drift.py                  # z-test + KS-test drift detection
β”œβ”€β”€ data/
β”‚   └── sku_demand.csv            # SYNTHETIC daily SKU demand, 4 SKUs x 2 years
└── requirements.txt

Production upgrade path

Demo component Production equivalent
Trend + Fourier + Ridge regression Prophet and/or a Temporal Fusion Transformer, per the original architecture brief
In-process walk-forward loop Apache Airflow scheduled runs, containerized with Docker
z-test + KS-test on residuals Evidently AI or Great Expectations for full data-drift reporting (feature drift, not just target/residual drift)
Direct in-process retrain AWS Lambda triggered by the drift-monitoring step, writing a new model version to a registry

Project landing page

docs/index.html is a standalone, single-file static landing page (no build step) summarizing the project's results, method, and findings. To host it live on GitHub Pages: repo Settings β†’ Pages β†’ Source: Deploy from a branch β†’ Branch: main, folder: /docs β†’ Save. It'll be live within a minute or two at https://data-geek-astronomy.github.io/BEACON_FORECAST/.