Tech Tuesday: Predicting customer orders

How Restaurants Know What You’ll Crave Before You Do

The Future of Food Forecasting

Imagine walking into your favorite café, and the daily special is exactly what you were craving—even though you never said a word. That’s not magic; it’s predictive ordering, powered by AI. Restaurants are starting to harness the same algorithms used in e‑commerce and logistics to forecast customer demand before it’s voiced. This isn’t just shaping menus—it’s transforming supply chains, staffing, and kitchen prep.



The Data Behind Your Dinner

Predictive ordering begins with demand forecasting models that ingest:

  • Historical sales (SKU × store × day)
  • External factors (weather, holidays, sports/events)
  • Menu & pricing (promotions, price elasticity)
  • Availability (stock‑on‑hand, supplier lead times)
  • Local signals (regional tastes, search trends)

Classical time‑series (ARIMA/SARIMAX) captures seasonality; tree‑boosting (LightGBM/quantile loss) and deep models (LSTM/Transformers) capture nonlinear shifts—like sudden surges in iced drinks during heat waves or wings on game days.


A Credible End‑to‑End Pipeline

Minimum viable schema

store_id, sku_id, date, units_sold, price, promo_flag, stock_on_hand, weather_*, event_flags, dow, month, social_index?, lead_time_days?

Feature engineering

  • Calendar features: DOW/holiday one‑hots; seasonal Fourier terms
  • Lags/rolls: lag_1, lag_7, lag_28; rolling mean/std (7/28 days)
  • Interactions: temp × iced_drink_flag, game_day × wings_category
  • Price/promo elasticity features
  • Mask stockouts (don’t learn from truncated demand)

Hierarchical, probabilistic forecasting

  • Forecast at SKU × store, optionally reconcile to store/chain totals (bottom‑up or MinT)
  • Train models that output quantiles (P10/P50/P90) for safety‑stock planning
  • Backtest with rolling origins; metrics: sMAPE/MASE (point), Pinball loss (quantiles)

Simple Math Sketch (Newsvendor Logic)

For a single SKU/day, choose order quantity q to balance waste vs. stockout costs:

Minimize:  c_w · E[(q − D)_+]  +  c_s · E[(D − q)_+]
Where:     D ~ random demand, c_w = waste cost, c_s = stockout cost
Optimal service level (single-period approximation):
           q* = F_D^{-1}( c_s / (c_s + c_w) )
I.e., order to the demand quantile set by your relative costs.

For multi‑day horizons, apply per day or solve as a coupled LP/MILP with storage and budget constraints.

Realistic Pseudocode (Production‑ish)

# DATA PREP
data = load_sales_weather_events()       # multi-store, multi-sku
data = mask_stockouts(data)              # remove/flag truncated demand
data = add_calendar_features(data)       # DOW, holidays, Fourier seasonality
data = add_lags_rolls(data, lags=[1,7,28], rolls=[7,28])
data = add_interactions(data, ["temp*iced", "game_day*wings"])

# TRAIN/VALIDATE by STORE × SKU (hierarchical)
models = {}
for store in STORES:
  for sku in SKUS[store]:
    ds = data.filter(store, sku)
    folds = time_series_folds(ds, horizon=28, n_folds=4)

    best_model, best_score = None, +inf
    for candidate in [SARIMAX_X, LGBM_Quantile, TFT]:
      scores = []
      for train, valid in folds:
        m = candidate.fit(train.X, train.y)
        q_fore = m.predict(valid.X, quantiles=[0.1, 0.5, 0.9])
        scores.append(pinball_loss(valid.y, q_fore))
      if mean(scores) < best_score:
        best_model, best_score = m, mean(scores)

    models[(store, sku)] = best_model

# FORECAST (probabilistic)
forecasts = {}
for key, model in models.items():
  X_future = build_future_features(key, horizon=28, latest_weather, events)
  forecasts[key] = model.predict(X_future, quantiles=[0.1, 0.5, 0.9])

# OPTIONAL: RECONCILE HIERARCHY (e.g., MinT)
forecasts = reconcile_hierarchy(forecasts, levels=["sku_store","store","chain"])

# INVENTORY / MENU OPTIMIZATION (one store)
for store in STORES:
  F = forecasts[store]   # dict: sku → daily quantiles
  # Decision: order_qty[sku] ≥ 0
  minimize Σ_s [ waste_cost[s]·E[max(q_s − D_s, 0)] + stockout_cost[s]·E[max(D_s − q_s, 0)] ]
  subject to:
    Σ_s (q_s·unit_cost[s]) ≤ budget_store
    Σ_s (q_s·storage_vol[s]) ≤ cold_storage_cap
    0 ≤ q_s ≤ supplier_limit[s]
  solve → order plan + menu highlights

Minimal, Realistic Code Fragment (Python‑style)

# LightGBM quantile models (per SKU/store) + simple newsvendor decision
import numpy as np, lightgbm as lgb

q_models = {q: lgb.LGBMRegressor(objective='quantile', alpha=q) for q in [0.1, 0.5, 0.9]}
for q, m in q_models.items():
    m.fit(X_train, y_train)
q_preds = {q: q_models[q].predict(X_future) for q in q_models}  # arrays over horizon

# Choose order quantity by cost-weighted service level
service = cs / (cs + cw)   # cs=stockout cost, cw=waste cost
# Use quantile interpolation across predicted distributions
stacked = np.vstack([q_preds[0.1], q_preds[0.5], q_preds[0.9]]).T
order_qty = np.quantile(stacked, service, axis=1)

# If many SKUs/constraints: send to LP/MILP (e.g., OR-Tools) using piecewise expectation
from ortools.linear_solver import pywraplp
solver = pywraplp.Solver.CreateSolver('GLOP')
q = {s: solver.NumVar(0, supplier_limit[s], f"q_{s}") for s in SKUS}
solver.Add(sum(q[s]*unit_cost[s] for s in SKUS) <= budget)
solver.Add(sum(q[s]*storage_vol[s] for s in SKUS) <= cold_storage_cap)
# Objective: Σ_s approx_expected_cost(q[s], quantile_scenarios[s])
# (Implement with piecewise linearization or scenario expansion)
solver.Minimize(sum(approx_expected_cost(s, q[s], scenarios[s]) for s in SKUS))
solver.Solve()

Innovation in Action (Real‑World Examples)

Real examples, not endorsements: Starbucks has publicly discussed using its Deep Brew AI for inventory/personalization. Chains like Domino’s have reported demand forecasting to improve delivery and reduce waste. These cases show predictive systems are operational today; specifics vary by brand and are evolving.

What This Means for Your Kitchen

  • Restaurants: Lower waste, fewer stockouts, better labor and prep planning.
  • Home cooks: Meal‑planning apps increasingly use lightweight forecasting—try apps that learn your patterns and suggest “next best” recipes.

Looking Ahead

Next‑gen systems will fuse probabilistic forecasts with real‑time sensors (smart fridges, prep‑station scales), auto‑replenishment, and dynamic menus. The more connected kitchens become, the more predictive ordering will quietly run in the background—so the right dish appears at the right time.

Question for readers: If an algorithm suggested tomorrow’s special or your next home‑cooked meal, would you follow it—or trust your gut?

Comments