Spaces:
Runtime error
A newer version of the Streamlit SDK is available: 1.59.2
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.csvis generated bygenerate_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/.