Bike sharing: demand forecasts that admit what they do not know
Difficulty
★★★☆☆
Time
3-4 hours
Data
Capital Bikeshare (Washington DC) daily rental counts 2011-2012 with weather and calendar covariates
Skills
Count likelihoods and the log link · diagnosing a predictive distribution that is far too confident · non-linear effects with splines · index variables and ZeroSumNormal · LOO model comparison · pointwise LOO and Pareto-$k$ as an anomaly detector · out-of-sample forecasting with pm.Data · interval coverage · turning a predictive distribution into a capacity decision
The operations team of a bike-sharing scheme plans two things a day ahead: how many vans
and staff to put on rebalancing (moving bikes from full docks to empty ones), and how
many bikes to have in service. Both scale with the number of rentals they must be able to
serve tomorrow. Plan too low and customers find empty docks; plan too high and vans and
people stand idle.
They have a weather forecast for tomorrow and two years of history. What they ask for:
"Give us tomorrow's demand with a range we can trust. If you say 90%, we want to be
inside it nine days out of ten. And tell us how much capacity to plan so that we can
cover demand on 95% of days."
From conversations with the team you know that a typical day sees a few thousand rentals,
that a busy summer day can reach eight thousand, and that the system is growing fast.
A point forecast is the easy half of this. The brief is about the spread: a predictive
distribution whose stated probabilities can be taken at face value. Sampler diagnostics
will not tell you whether you have one.
One row per day, 1 January 2011 to 31 December 2012. cnt is the total number of rentals
(casual + registered). Calendar columns: yr (0 = 2011, 1 = 2012), mnth, weekday
(an integer - find out which day is 0), holiday, workingday (neither weekend nor
holiday). weathersit is the day's weather situation: 1 = clear or partly cloudy,
2 = mist or overcast, 3 = light rain or snow, thunderstorm.
The UCI file stores the continuous weather variables normalised - each was divided by
a constant so that it lies between 0 and 1:
column
meaning
divided by
temp
mean temperature, °C
41
atemp
"feels-like" temperature, °C
50
hum
relative humidity, %
100
windspeed
wind speed, km/h
67
Nobody on the operations team thinks in units of "0.34 of 41 °C".
A data frame with the weather in physical units (°C, %, km/h) and readable labels for
weekday and weather situation. Verify the weekday coding rather than guessing it.
train (before HOLDOUT_START) and test (the rest).
Plots of the training data that show what a demand model will have to reproduce: the
series over time, demand against temperature, demand by weather situation and by weekday.
Write down the three or four features you consider essential. Do you need both temp
and atemp?
Rentals are counts, so start where every textbook starts: a Poisson regression with a log
link. Use the weather only - temperature, humidity and wind speed, each entering linearly
on the log scale.
Deliver
Priors you can defend, shown with a prior predictive check on the scale the
operations team thinks in: rentals per day.
A fit with clean sampler diagnostics. Look at how precisely the model claims to know its
coefficients.
A verdict: is this model's predictive distribution fit for the brief? Back it with at
least one graphical posterior predictive check that could embarrass the model, and one
number: the share of training days that fall inside the model's central 90% predictive
interval.
Your verdict should have been damning, and "the sampler is fine" is no defence.
Deliver
The diagnosis in one sentence: which assumption of the Task 1 model do the data
violate, and by roughly what factor? (A number, please.)
A repaired model that changes only what the diagnosis demands - same predictors, same
priors for the coefficients. Explain what its new parameter means in words the
operations team would understand.
The same checks as in Task 1, now passed (or not?).
Put the posterior standard deviations of the coefficients from both models side by
side. What happened, and what would it have cost someone who believed the first model?
A straight line on the log scale says every extra degree multiplies demand by the same
factor, for ever. Washington summers disagree.
Deliver
Evidence from the Task 2 model that the linear temperature effect is wrong (a residual
plot will do).
A model in which temperature enters through a smooth function instead. Everything
else stays as in Task 2.
A plot of the estimated temperature effect as a multiplier on expected demand, with a
credible band, across the observed temperature range.
Two numbers with uncertainty: the temperature at which demand peaks, and how much lower
(in %) expected demand is at 35 °C than at the peak.
Your turn Work this task in the notebook.
#Task 4 · Calendar, weather situation, growth - and a scoreboard
The operations team knows that demand depends on the day of the week, on public
holidays, on the weather situation (rain is worse than humidity alone suggests), and
that the system grew between 2011 and 2012. Add all four to the Task 3 model.
Deliver
A model in which the categorical effects have no arbitrary reference level: every
weekday and every weather situation is treated symmetrically by the prior, and the
intercept keeps its meaning. Clean diagnostics. The file also offers workingday -
explain why you should not simply add it as well.
The effects in units the team can use: by what percentage does a wet day change demand
relative to a clear one? How much did demand grow from 2011 to 2012? Which weekday is
busiest? Do not forget the uncertainty.
A PSIS-LOO comparison of all four models so far (az.compare, az.plot_compare) and
your reading of it: which steps mattered, judged by elpd_diff against dse? Read the
warnings - you will come back to them in Task 5.
LOO is not only a scoreboard. It computes, for every single day, how well the model predicts
that day when it has not seen it - and how much the posterior leans on it.
Deliver
For your best model so far: the pointwise elpd and the Pareto-$k$ value of every
training day, plotted against the date, and a table of the six most surprising days.
For the worst of them: what happened? (You have the date and the internet.) Is it the
kind of day the brief asks you to forecast? Look at the other five as well - is any of
them a data problem rather than a demand problem?
A decision on how to handle what you found, with a justification an auditor would
accept, and a refit. What changed in the dispersion and in the width of the predictive
intervals - and why does one day out of 675 have that much leverage?
Time to find out whether "90%" means 90%. Forecast the 56 hold-out days with the model from
Task 5, using the weather that actually occurred (a perfect weather forecast - the best
case).
Deliver
Forecasts produced without refitting: swap the inputs of the fitted model and sample
the posterior predictive.
A plot of the 50% and 90% predictive intervals against the actual counts, plus the
empirical coverage of both intervals and the mean error (forecast median minus actual).
If the forecasts are biased: find out why - not by tuning against the hold-out, but
by asking what your growth term assumes about November 2012, and checking that assumption
on the training data. Fix the model, compare old and new with LOO, and forecast again.
A list of the hold-out days that still fall outside the 90% interval. What do they have in
common? Could the training data have warned you? (Task 5 again.) Which direction is the
error, and how much does that direction hurt the operations team?
The team plans three days in the coming weeks and hands you the weather forecast for each.
(None is a public holiday.)
scenarios=pd.DataFrame({"date":pd.to_datetime(["2012-11-16","2012-11-18","2012-11-20"]),"temp_c":[14.0,8.0,11.0],"hum_pct":[50.0,70.0,90.0],"wind_kmh":[10.0,20.0,15.0],"weather":["clear","mist","wet"],},index=["mild clear Friday","cold misty Sunday","wet Tuesday"],)COST_LOST_RENTAL=4.0# $ per rental the system could not serve (lost fare and goodwill)COST_IDLE=0.5# $ per unit of capacity planned but not used (vans, staff, bikes standing by)scenarios
date
temp_c
hum_pct
wind_kmh
weather
mild clear Friday
2012-11-16
14.0
50.0
10.0
clear
cold misty Sunday
2012-11-18
8.0
70.0
20.0
mist
wet Tuesday
2012-11-20
11.0
90.0
15.0
wet
Deliver
For each scenario the capacity (in rentals per day) that covers demand with probability
95%, from your final model - and, next to it, the number you would get if you
(wrongly) used only the uncertainty about the expected demand. How big is the gap?
Management's 95% is a rule of thumb. With the two costs above, find the capacity that
minimises expected cost for each scenario, numerically from the predictive draws.
Which quantile of the predictive distribution does it correspond to? What ratio of the
two costs would make the 95% rule optimal?
Three sentences for the operations team: what to plan, how far to trust it, and when
not to.
Holiday seasons. The final model over-forecasts Thanksgiving weekend and the week after
Christmas. Give it a way to learn that from 2011 (one Christmas is not much - what prior
keeps the estimate honest?) and check whether hold-out coverage improves.
Two populations.casual and registered riders have opposite weekday patterns and
different sensitivity to weather. Model them separately (or jointly, with shared growth)
and add the predictive draws. Does the total forecast get sharper?
A Gaussian process instead of a spline. Replace the temperature spline with
pm.gp.HSGP, and the linear trend with a slowly-varying HSGP in time. Does the
temperature curve change where data are sparse? What happens to forecasts when the trend
is a GP that reverts to its mean?
The weather forecast is uncertain too. Tomorrow's temperature is known to within a
couple of degrees and "wet" is a probability. Propagate that through the capacity
decision by sampling scenarios. When does it matter?
h.progress()
C03: 0/23 hints used, 18/18 checks passed.
Reference solution
A complete, executed solution with commentary on every task — including the ways the obvious model fails. Try the hint ladder first.