ML
Synthetic Data
Training-data provenance per model.
Source: hotelmind-ml/docs/datasets/synthetic_data.md
Synthetic Data
Two of this project's five ML domains — Restaurant and Staffing — have no real underlying data anywhere in this repository or its inputs. This document explains why, and exactly how the synthetic substitute was built.
Why synthetic data was necessary
- The canonical booking dataset (
hotel_bookings.csv) contains only reservation-level fields — no F&B transactions, no staff attendance records. - The Phase 3 warehouse's
fact_restaurant_saleandfact_staff_attendancetables were never populated — no source data exists to populate them from (seedocs/datasets/warehouse.md). - The task required Restaurant and Staffing models to be actually
trained, with real (non-placeholder) evaluation metrics — which is
impossible without some training data. The alternative (leaving these two
domains as untrained scaffolds) was explicitly rejected in favor of
generating clearly-labeled synthetic data, following the same pattern as
two pre-existing synthetic seeds in this project (
room_type_dim.csv,events_holiday_calendar.csv).
Design principle: driven by real signal, not pure noise
Both generators (src/pipelines/synthetic_data.py) are seeded from the
real, derived daily occupancy (occupied_rooms, itself computed from
actual fact_booking check-in/check-out ranges — not synthetic). This
means synthetic Restaurant/Staffing values still correlate sensibly with
real booking activity (busier days → more meals served, more staff
present), rather than being pure random numbers disconnected from any
signal.
Synthetic restaurant data
data/raw/restaurant_daily_synthetic.csv, generated by
generate_restaurant_daily():
revenue[meal] = base_rate[meal] * occupied_rooms * day_of_week_multiplier * (1 + noise)
items_sold = total_revenue / avg_item_valuebase_rate: breakfast $8/room, lunch $6/room, dinner $12/room (fixed constants, not measured)day_of_week_multiplier: 1.15× on weekends, 1.0× on weekdaysnoise:N(0, 0.05)per meal per day, seeded (np.random.default_rng(42))avg_item_value: fixed constant (mean of per-meal item values, $9.5/$14/$22)
Synthetic staffing data
data/raw/staffing_daily_synthetic.csv, generated by
generate_staffing_daily():
present_employees[dept] ≈ ceil(ratio[dept] * occupied_rooms * day_of_week_multiplier) + noiseratio: Reception 0.03, Kitchen 0.05, Housekeeping 0.08 (fixed constants, not derived from any real staffing policy)noise: integer{-1, 0, +1}, seeded
Determinism
Both generators use np.random.default_rng(seed=42) — identical input
(the derived daily occupancy DataFrame) always produces byte-identical
synthetic output. Regenerating the seed files is a reproducible no-op, not
a source of drift. Verified in tests/test_synthetic_data.py.
Known limitations
- Every Restaurant/Staffing prediction is illustrative, not a real business forecast. Do not present these models' output to stakeholders as measuring real demand or real staffing needs.
- Evaluation metrics for these two domains measure how well each model fits the synthetic generator's own signal-plus-noise, not real-world accuracy.
- If real F&B or staff-attendance data ever becomes available, only
load_data()inRestaurantPipeline/StaffingPipelineneeds to change — the model classes, feature engineering, and API layer are data-source agnostic.
See reports/final_phase4/known_limitations.md (items 1, 9, 10) and
reports/model_discovery/feature_quality.md §1 for further detail.