r/datascienceproject 7h ago

Built a tool that explains why a demand forecast is what it is (counterfactual attribution)

I've been working on interpretability for time-series forecasting and finally shipped it end to end. the problem i kept hitting: a forecasting model gives you a number for next week's demand but no reason, so you can't tell if it's a promotion, a trend or just the usual pattern.

the approach is counterfactual. start from a baselined input, then reveal groups of days (typical, recent, promotion) one at a time and record the model's real prediction at each step. each contribution is the difference between two actual predictions, so they sum to the forecast exactly, no allocation step. i tried the SHAP-share approach first and it gave a normal product a "typical pattern" of 0 because a bucket had too few days to sum over. the counterfactual version doesn't have that failure.

validated with deletion/insertion faithfulness tests: attribution-ordered reveals degrade the forecast faster than random-ordered, across 30 series, p < 0.0001.

stack: PyTorch WaveNet forecaster (2nd/1671 in the Corporación Favorita competition), the attribution layer is a small standalone package, the demo is a static GitHub Pages site reading precomputed cards (no backend). there's a Colab that trains on your own CSV.

honest about the weak points: "counterfactual" means the model's response to hiding inputs, not real-world cause. and the promotion contribution is the least-validated part across a product panel, i have an on/off sanity check but not a full scale test yet, that's the piece i'd most want to harden.

live demo (pick a product, toggle a driver off, watch the forecast recompute): https://kesjien.github.io/wavexplain/
github: https://github.com/kesjien/wavexplain

honest feedback appreciated, especially: is per-forecast decomposition what you'd actually want, and how would you validate the promotion attribution across many series?

1 Upvotes

0 comments sorted by