Forecasting and Uncertainty
This page collects the forecasting and uncertainty tutorials into a single, repeatable sequence.
Table of contents
Explore Demand Data and Define the Forecast Grain
Start by looking at the demand pattern at two grains.
- Start from a session with the 1-echelon 2017 dataset.
- Paste the script and run it.
- You should now see daily and weekly demand line charts.
read "/sample/Lokad_Orders.tsv.gz" as Orders expect [date] with
"Date" as date : date
Quantity : number
Day.Demand = sum(Orders.Quantity)
Week.Demand = sum(Day.Demand)
show linechart "Daily demand" with
Day.Demand
show linechart "Weekly demand" with
Week.Demand
You should now have a quick sense of which grain is smoother and easier to forecast.
Fit First Point Forecast Model with Autodiff
Fit a small trend model to a short demand series.
- Paste the script and run it.
- You should now see the fitted base and slope plus a table of the trend values.
- Adjust one demand value and re-run to see the fit change.
table History[date] = with
[| as date, as Demand |]
[| date(2024, 1, 1), 120 |]
[| date(2024, 1, 2), 118 |]
[| date(2024, 1, 3), 125 |]
[| date(2024, 1, 4), 130 |]
[| date(2024, 1, 5), 128 |]
[| date(2024, 1, 6), 132 |]
History.Index = rank() scan date
autodiff History epochs:40 learningRate:0.05 with
params base auto
params slope auto
Pred = base + slope * History.Index
err = Pred - History.Demand
return (err^2, mae: abs(err))
History.Trend = base + slope * History.Index
show summary "Fitted trend" with
base
slope
show table "Demand vs trend" with
History.date
History.Demand
History.Trend
You should now have a first point-forecast model in place.
Turn a Point Forecast into a Quantile Forecast
Convert a point forecast into a set of quantiles you can act on.
- Paste the script and run it.
- You should now see a table with P10, P50, and P90 bands.
- Increase the dispersion to widen the bands.
start = date(2024, 3, 1)
keep span date = [start .. start + 13]
Day.t = date - start
Day.Point = 120 + 2 * Day.t
Day.Dist = negativeBinomial(Day.Point, 2)
Day.P10 = quantile(Day.Dist, 0.10)
Day.P50 = quantile(Day.Dist, 0.50)
Day.P90 = quantile(Day.Dist, 0.90)
show table "Quantile forecast" with
date
Day.Point
Day.P10
Day.P50
Day.P90
You should now see how uncertainty bands wrap the point forecast.
Simulate Demand Paths with Monte Carlo
Use Monte Carlo sampling to capture variability in demand.
- Paste the script and run it.
- You should now see median and P90 demand for each day index.
- Increase the number of simulations for a smoother curve.
table Horizon = extend.range(14)
Horizon.Day = Horizon.N
montecarlo 200 with
Horizon.Demand = random.poisson(20 into Horizon)
sample Horizon.Dist = ranvar(Horizon.Demand)
Horizon.P50 = quantile(Horizon.Dist, 0.50)
Horizon.P90 = quantile(Horizon.Dist, 0.90)
show table "Monte Carlo demand" with
Horizon.Day
Horizon.P50
Horizon.P90
You should now have a simple distribution view of demand paths.
Compute Demand Over Lead Time
Combine variable demand and variable lead time into a single lead-time demand distribution.
- Paste the script and run it.
- You should now see a lead-time demand P50 and P95 per SKU.
- Change the daily demand or lead time means to see the distribution shift.
table Items[id] = with
[| as id, as DailyMean, as LeadTimeMean |]
[| "A-100", 5, 7 |]
[| "B-200", 8, 12 |]
[| "C-300", 3, 5 |]
table Days max 1000 = extend.range(Items.LeadTimeMean * 4)
montecarlo 300 with
Items.LeadTimeSample = 1 + random.poisson(Items.LeadTimeMean into Items)
Days.DailySample =
if Days.N <= Items.LeadTimeSample then
random.poisson(Items.DailyMean into Days)
else
0
Items.LeadTimeDemand = sum(Days.DailySample)
sample Items.LeadTimeDist = ranvar(Items.LeadTimeDemand)
Items.LeadTimeP50 = quantile(Items.LeadTimeDist, 0.50)
Items.LeadTimeP95 = quantile(Items.LeadTimeDist, 0.95)
show table "Lead-time demand" with
Items.id
Items.LeadTimeMean
Items.LeadTimeP50
Items.LeadTimeP95
You should now have a lead-time demand distribution that accounts for both sources of variability.
Visualize Forecast Uncertainty for Decision-Making
Plot uncertainty bands so decisions can account for risk.
- Paste the script and run it.
- You should now see P10, P50, and P90 lines on the chart.
- Widen the standard deviation to see the band spread.
start = date(2024, 4, 1)
keep span date = [start .. start + 20]
Day.t = date - start
Day.Point = 80 + Day.t
Day.Dist = normal(Day.Point, 12)
Day.P10 = quantile(Day.Dist, 0.10)
Day.P50 = quantile(Day.Dist, 0.50)
Day.P90 = quantile(Day.Dist, 0.90)
show linechart "Forecast bands" with
Day.P10 as "P10"
Day.P50 as "P50"
Day.P90 as "P90"
You should now see a clear uncertainty band for decision-making.