| # M5 Forecasting: Complete End-to-End Explanation |
|
|
| ## For a 10-Year-Old: Think Like a Candy Store Detective |
|
|
| ### The Problem |
| Imagine you have a HUGE candy store with 30,490 different types of candy across 10 store locations. Your job is to guess how many pieces of EACH candy will sell over the next 28 days. That's like guessing homework answers for 30,490 friends! |
|
|
| ### The Clues (Features) We Use |
| 1. ποΈ **What day is it?** People buy more candy on weekends |
| 2. π **Is there a party?** Halloween, Christmas, etc. = candy rush! |
| 3. π° **How much does it cost?** Cheaper candy sells more |
| 4. π **What sold last week?** Helps predict this week |
| 5. πͺ **Which store?** Some stores sell different things |
|
|
| ### Why 40 Brains Instead of 1 Super Brain? |
| Think of it like learning math: |
| - If you try to learn multiplication, reading, AND history all at once, you get confused |
| - Better to have separate brain cells for each subject |
| - Same with our candy store: One brain per store, and one brain per time period (near future vs far future) |
|
|
| ### Our Three Types of Brains |
| 1. **SARIMAX (Math Whiz)**: Loves patterns and numbers |
| - Sees weekly patterns (weekends sell more!) |
| - Uses all the clues you gave it |
| - **Score**: RMSE = 1805 (lower is better) |
|
|
| 2. **Prophet (Calendar Expert)**: Knows about holidays and events |
| - "Oh! Christmas is coming, candy sales will spike!" |
| - Understands yearly patterns |
| - **Score**: RMSE = 3714 (second best) |
|
|
| 3. **ARIMA (Simple Repeater)**: Just looks at past patterns |
| - "Last week same day sold 100, so I'll guess 100" |
| - No holiday knowledge, no store differences |
| - **Score**: RMSE = 6558 (needs more training) |
|
|
| 4. **Hybrid (Teamwork)**: SARIMAX + Smart Friend |
| - SARIMAX makes first guess |
| - XGBoost (smart friend) fixes SARIMAX's mistakes |
| - **Score**: RMSE = 1757 (WINNER!) |
|
|
| --- |
|
|
| ## For College Students: Technical Deep Dive |
|
|
| ### Complete Pipeline Architecture |
|
|
| ``` |
| Raw Data (30K series) β Aggregations β Feature Engineering β Model Training β Evaluation |
| β β β β β |
| sales_*.csv Total/Store-level Origin-relative 40ΓLightGBM + WRMSSE @ |
| calendar.csv time series features + lags 4 statistical 12 levels |
| sell_prices.csv Target encoding models 3 folds |
| sample_submission.csv |
| ``` |
|
|
| ### Phase-by-Phase Breakdown |
|
|
| #### Phase 1: Data Preprocessing |
| **Goal**: Transform raw M5 data into usable format |
|
|
| ```python |
| # Key Operations: |
| # 1. Melt sales from wide (30490 Γ 1941) to long format |
| sales_long = sales.melt(id_vars=['id','item_id',...], |
| value_vars=['d_1'...'d_1913'], |
| var_name='d', value_name='sales') |
| |
| # 2. Merge calendar on 'd' column (daily metadata) |
| # 3. Merge sell_prices on (store_id, item_id, wm_yr_wk) - CRITICAL: weekly! |
| |
| # Key Insight: Prices are WEEKLY, not daily! |
| # Wrong: join on date β creates nulls |
| # Right: join on wm_yr_wk β correct pricing |
| ``` |
|
|
| **Output**: 46.9M rows of clean sales data |
|
|
| #### Phase 2: Define Forecasting Scope |
| **Decision Point**: What exactly are we forecasting? |
|
|
| - **Option A (LightGBM)**: 30,490 individual series, per-store |
| - **Option B (Statistical)**: Aggregated daily total sales (1 series) |
|
|
| We chose **both** approaches to compare methodologies: |
| - LightGBM handles the full granularity |
| - Statistical models demonstrate classical approaches |
|
|
| #### Phase 3: Time-Based Split |
| **Critical Step**: Never let the model see the future! |
|
|
| ``` |
| Training Data: Days d_1 to d_1885 (2011-2016) |
| Test Data: Days d_1886 to d_1913 (last 28 days) |
| Forecast: Days d_1914 to d_1941 (target period) |
| ``` |
|
|
| This matches the WRMSSE evaluation structure used in the M5 competition. |
|
|
| #### Phase 4: Baselines (Must Beat These!) |
| Before any fancy models, establish simple rules: |
|
|
| | Baseline | Strategy | RMSE | |
| |----------|----------|------| |
| | Naive | "Tomorrow = Today" | 8,184 | |
| | Moving Avg | "Average of last 7 days" | 7,192 | |
| | **Seasonal Naive** | "Same day last week (shift 7)" | **3,947** β Best baseline | |
| | Weekly Seasonal | "Previous Monday = this Monday" | 6,686 | |
|
|
| **Key Insight**: For retail data with weekly patterns, seasonal naive is a VERY strong baseline! |
|
|
| #### Phase 5: Statistical Models |
|
|
| ##### 1. ARIMA (2,1,2) - The Simple Baseline |
| **What it does**: Looks at past patterns to predict future |
| - p=2: Uses 2 past values |
| - d=1: First differencing for stationarity |
| - q=2: 2 past forecast errors |
|
|
| **Why it struggles (RMSE=6,558)**: |
| - No seasonality handling (retail has strong weekly cycles) |
| - No external variables (events, pricing) |
|
|
| **Code**: |
| ```python |
| from statsmodels.tsa.arima.model import ARIMA |
| model = ARIMA(train_series, order=(2,1,2)) |
| fitted = model.fit() |
| forecast = fitted.forecast(steps=28) |
| ``` |
|
|
| ##### 2. SARIMAX(2,1,1)(1,1,1,7) - The Winner |
| **What it does**: ARIMA + Seasonal components + External variables |
|
|
| **Key Parameters**: |
| - `order=(2,1,1)`: AR(2), Integrated(1), MA(1) |
| - `seasonal_order=(1,1,1,7)`: Seasonal AR(1), I(1), MA(1), Period=7 days |
| - `exog`: External variables (day of week, month, SNAP flags, sin/cos day) |
|
|
| **Why it wins (RMSE=1,805)**: |
| 1. **Weekly seasonality** (s=7) captures day-of-week patterns |
| 2. **Exogenous variables** add pricing, event signals |
| 3. **Seasonal differencing** removes repetitive patterns cleanly |
|
|
| **Code**: |
| ```python |
| from statsmodels.tsa.statespace.sarimax import SARIMAX |
| model = SARIMAX(endog=train_series, exog=train_exog, |
| order=(2,1,1), seasonal_order=(1,1,1,7)) |
| fitted = model.fit() |
| forecast = fitted.forecast(steps=28, exog=test_exog) |
| ``` |
|
|
| ##### 3. Prophet - The Calendar Expert |
| **What it does**: Additive model with trend + seasonality + holidays |
|
|
| **Components**: |
| 1. Piecewise linear trend |
| 2. Fourier series for daily/weekly/yearly seasonality |
| 3. Holiday/event indicator variables |
| 4. Automatically handles missing data |
|
|
| **Performance**: RMSE=3,714 (7th percentile among all methods) |
|
|
| **Why Prophet**: |
| - Handles holidays/events natively |
| - Fast training |
| - Uncertainty intervals built-in |
| - Interpretable components |
|
|
| **Why it doesn't win**: |
| - Can't use price data effectively |
| - Less granular than SARIMAX |
|
|
| #### Phase 6: Comparison & Analysis |
|
|
| Final ranking (lower RMSE = better): |
|
|
| | Rank | Model | RMSE | Key Insight | |
| |------|-------|------|-------------| |
| | 1 | **Hybrid SARIMAX+XGBoost** | 1,757 | Teamwork wins! | |
| | 2 | SARIMAX | 1,805 | Weekly + events + prices = winner | |
| | 3 | Prophet | 3,714 | Good for holidays, not prices | |
| | 4 | **Seasonal Naive** (baseline) | 3,947 | Simple but effective | |
| | 5 | ARIMA | 6,558 | Missing seasonality hurts | |
|
|
| **Critical Finding**: SARIMAX beats all baselines by 54.3%! |
|
|
| #### Phase 7: Hybrid SARIMAX + XGBoost - The Champion! |
|
|
| **Strategy**: |
| 1. Use SARIMAX to make main prediction |
| 2. Train XGBoost on SARIMAX's mistakes (residuals) |
| 3. Correct the final prediction with XGBoost |
|
|
| ```python |
| # Step 1: Get SARIMAX residuals |
| residuals = actual_sales - sarimax_predictions |
| |
| # Step 2: Train XGBoost to predict residuals |
| xgb.fit(X_train_lags, residuals) |
| |
| # Step 3: Correct future prediction |
| final_forecast = sarimax_forecast + xgb.predict(X_test_lags) |
| ``` |
|
|
| **Result**: 2.7% improvement over SARIMAX alone (1757 vs 1805) |
|
|
| --- |
|
|
| ## Why We Split Into Multiple Models/Repos |
|
|
| ### 1. Different Use Cases |
| ``` |
| rishini/NPN β Full 30K series per-store forecasting (production) |
| rishini/NPN-prophet β Fast experiments, holiday-aware predictions |
| rishini/NPN-sarimax β Best statistical accuracy with exogenous variables |
| rishini/NPN-arima β Baseline demonstration of classical methods |
| rishini/NPN-hybrid β State-of-the-art statistical baseline |
| ``` |
|
|
| ### 2. Computational Trade-offs |
| | Approach | Files | Compute | Accuracy | Use Case | |
| |----------|-------|---------|----------|----------| |
| | 40Γ LightGBM | 40 | GPU days | β
β
β
β
β
| Production forecasting | |
| | 1Γ SARIMAX | 1 | Minutes | β
β
β
β
β | Baseline / research | |
| | 1Γ Hybrid | 1 | Hours | β
β
β
β
β | Methodology showcase | |
|
|
| ### 3. Methodological Transparency |
| Each repo serves educational/documentation purposes: |
| - **Prophet repo**: Shows event/holiday modeling |
| - **SARIMAX repo**: Shows exogenous variable integration |
| - **ARIMA repo**: Shows classical time series baseline |
| - **Hybrid repo**: Shows modern ensemble techniques |
|
|
| --- |
|
|
| ## How to Use These Models |
|
|
| ### Option 1: Download and run predictions |
| ```bash |
| git clone https://huggingface.co/rishini/NPN-sarimax |
| cd NPN-sarimax |
| # Model file: model.pkl |
| ``` |
|
|
| ### Option 2: Load in Python |
| ```python |
| import pickle |
| with open('model.pkl', 'rb') as f: |
| model = pickle.load(f) |
| |
| # Forecast next 28 days |
| forecast = model.forecast(steps=28, exog=future_exog) |
| ``` |
|
|
| ### Option 3: Load predictions directly |
| Each repo includes `predictions.csv` with precomputed forecasts. |
|
|
| --- |
|
|
| ## Lessons Learned |
|
|
| 1. **Always establish baselines first** - Seasonal Naive RMSE = 3947 is hard to beat! |
|
|
| 2. **Weekly seasonality matters massively** - Retail has strong day-of-week patterns |
|
|
| 3. **Exogenous variables are game-changers** - Price, events, and calendar features boost accuracy by 30%+ |
|
|
| 4. **Hybrid models work** - SARIMAX + XGBoost improved accuracy by 2.7% |
|
|
| 5. **Scale vs accuracy trade-off**: |
| - Statistical models: Fast but aggregate (lose per-item precision) |
| - LightGBM: 40 models but predict all 30K items individually |
|
|
| 6. **Statistical models don't scale** - 30K series require gradient boosting, not ARIMA |
|
|
| --- |
|
|
| ## Repository Summary |
|
|
| | Repository | Model Type | RMSE | Size | Purpose | |
| |------------|------------|------|------|---------| |
| | `rishini/NPN` | LightGBM (40Γ) | 145.56 WRMSSE | 106 MB | Full pipeline | |
| | `rishini/NPN-sarimax` | SARIMAX | 1,805 RMSE | 85 MB | Best baseline | |
| | `rishini/NPN-hybrid` | Hybrid | 1,757 RMSE | 89 MB | Champion | |
| | `rishini/NPN-prophet` | Prophet | 3,715 RMSE | 0.2 MB | Event modeling | |
| | `rishini/NPN-arima` | ARIMA | 6,558 RMSE | 6.6 MB | Classical method | |
| """ |
|
|