ML
Restaurant Demand Model
Source: hotelmind-ml/docs/models/restaurant.md
Model Card: Restaurant Demand Forecasting
Purpose
Forecast per-meal (breakfast/lunch/dinner) revenue and estimated order quantity for a branch/date, to support F&B staffing and inventory decisions.
⚠️ Trained entirely on synthetic data — see Known Assumptions below before using this model's output for any real decision.
Input Features
FEATURE_COLS (src/pipelines/restaurant_pipeline.py):
| Feature | Source |
|---|---|
| month, quarter, day_of_week, is_weekend, is_holiday, is_event | src/features/calendar_features.py |
| total_orders_lag_1, total_orders_lag_7 | src/features/time_series_features.py |
| total_orders_rolling_mean_7 | same module |
Target Variable
Three independent targets, one per meal: breakfast_revenue,
lunch_revenue, dinner_revenue (float) — all synthetic (see below).
Algorithm
3 independent XGBoost models (RestaurantDemandModel, one per meal
period; XGBRegressor, n_estimators=250, max_depth=4, learning_rate=0.05,
subsample=0.8, colsample_bytree=0.8, random_state=42). One model per meal
rather than one shared model, since meal-period demand patterns are treated
as independent (per the model's own docstring).
Training Dataset
data/features/restaurant_features.parquet — 1,605 rows, generated by
src/pipelines/synthetic_data.py::generate_restaurant_daily from
data/raw/restaurant_daily_synthetic.csv. Chronological 80/20 train/test
split per meal.
Evaluation Metrics
| Meal | MAE | RMSE | MAPE |
|---|---|---|---|
| Breakfast | 112.79 | 150.91 | 61.4% |
| Lunch | 88.47 | 116.50 | 65.2% |
| Dinner | 161.14 | 212.86 | 60.8% |
Source: reports/latest_restaurant.json. These metrics measure how well
each model fits the synthetic generator's own occupancy-driven signal plus
injected noise — not real-world predictive accuracy.
Strengths
- Demonstrates a complete, working per-meal demand-forecasting pipeline
(feature engineering → training → evaluation → API) that would function
identically against real restaurant order data if it ever becomes
available — only
load_data()would need to change. - Quantity estimation includes an internal cross-check
(
derive_meal_quantities) between two independent formulas, logging divergence >20% — a real-data-quality safeguard, not just a synthetic artifact.
Limitations
- No real restaurant order data exists anywhere in this project — not in the raw Kaggle CSVs, not in the Phase 3 warehouse. Every value this model was trained on is fabricated.
expected_quantityin the API response is a simple derived ratio (predicted_revenue / avg_item_value), not a separately-trained quantity model.
Known Assumptions
- Synthetic generation formula: `revenue = base_rate[meal] * occupied_rooms
- day_of_week_multiplier * (1 + seeded_noise)
, deterministic vianp.random.default_rng(seed=42)— reproducible, not pure random noise, but still fabricated data (seereports/final_phase4/known_limitations.md` items 1 and 9).
- day_of_week_multiplier * (1 + seeded_noise)
avg_item_valueper meal is a fixed constant in the generator, not a measured value.
Future Improvements
- Replace the synthetic seed with real F&B transaction data if a POS/ restaurant-ordering data source is ever integrated into the warehouse.
- Consider a single multi-output model across meals if real data reveals shared demand drivers, rather than 3 fully independent models.