Forecast Tomorrow’s Water Demand Without Seeing Tomorrow
Build lagged inputs, compare an autoregressive model with persistence, and evaluate both through a sequence of later forecast origins.
15 sections · 4 questions · 4 coding challenges
The arrow keys move between sections too.
Evaluating Predictions at the Time They Could Have Been Made
BOTIE
Our demand sequence is synthetic and intentionally simple. It provides a testable implementation of the boundary, not evidence that a one-lag linear model is sufficient for real water planning.
Sources for this history
How Much Water Should Botie Prepare for the Next Day?
Botie needs a forecast before tomorrow’s water demand is known. A model that sees tomorrow while constructing today’s input can look excellent in a notebook and be impossible to use.
We will replay the forecast at successive dates. At each date, the model gets only the history available then. A persistence forecast gives us a simple comparison for the fitted autoregression. After saving both predictions, we can look at the later demand and measure their errors on the same target.
The water-demand project uses invented daily readings, in time order.
Step 1 of 3
Stop the data at the origin
Only the first five observations are available.
Recorded history → prediction time → future
- Recorded
Day 1
2litres
- Recorded
Day 2
4litres
- Recorded
Day 3
6litres
- Recorded
Day 4
8litres
- Recorded
Day 5
10litres
- Predict this day
Day 6
?not observed yet
Keep out of the inputs
Step 2 of 3
Fit on earlier-to-later pairs
A lagged input predicts the next observed value.
| Target day | Inputs | Targets |
|---|---|---|
| Day 2 | 2 | 4 |
| Day 3 | 4 | 6 |
| Day 4 | 6 | 8 |
| Day 5 | 8 | 10 |
Day 2
- Inputs
- 2
- Targets
- 4
Day 3
- Inputs
- 4
- Targets
- 6
Day 4
- Inputs
- 6
- Targets
- 8
Day 5
- Inputs
- 8
- Targets
- 10
Step 3 of 3
Compare two forecasts
The model and baseline must target the same unseen day.
| Method | Day 6 prediction | Later observation | Absolute error |
|---|---|---|---|
| Persistence | 10 | 12 | 2 |
| Fitted autoregression | 12 | 12 | 0 |
Persistence
- Day 6 prediction
- 10
- Later observation
- 12
- Absolute error
- 2
Fitted autoregression
- Day 6 prediction
- 12
- Later observation
- 12
- Absolute error
- 0
A forecast project needs an honest baseline and a time-respecting comparison
Matching targets makes the comparison reflect forecast errors rather than different evaluation days.
Which forecasting procedure helped on the same future days?
Each row contains one method's previously recorded forecasts. Compare it with the matching later totals and decide whether its errors justify using that procedure.
Make the forecast before revealing the next day
BOTIE
Smoothing starts at the first observation, then moves its level halfway toward each newly revealed value. Changing the rule restarts the comparison on the same sequence.
Known days: 1 to 1
Forecast for day 2: 8
BOTIE
Mean absolute error for each forecasting procedure
- 02
- 10
Follow the operations
1. Rows of matched procedure forecasts
10 12 12 14 2. Later observed outcomes
- 012
- 114
3. Subtract a shared reference row
-2 -2 0 0 4. Absolute value
2 2 0 0 5. Mean within each row
- 02
- 10
6. Result
- 02
- 10
Forecasts must be stored before targets are observed. This workshop evaluates supplied predictions; fitting happens in the project code.
1. Specify Origin, Horizon, and Units
The origin is the last moment whose readings are available. The horizon is one day in this project, and each value is demand in the same units. Decide when daily totals become available; a total published late cannot be used before publication.
Use earlier origins for method selection and reserve later origins for final comparison. Do not choose model settings from the final error table.
A row is not automatically a day. Keep a date beside every measurement, then check that the dates are unique, ordered and consecutive before making lag pairs. If Tuesday is missing, the row before Wednesday is Monday; treating it as yesterday changes the question without telling the model. The calendar challenge below deliberately refuses that sequence. Repairing or imputing a missing measurement requires a separate, stated rule using only information available at the forecast origin.
Every fitting call below receives only the prefix ending before its target.
2. Build a Baseline and a Small Learned Model
Persistence predicts the most recent observation. The autoregression fits an intercept and one lag coefficient with least squares. Its design matrix contains a constant column and earlier demand; targets contain the following demand.
Use a numerical least-squares solver rather than forming an inverse. Check whether the available pairs contain enough variation to identify both coefficients.
Training inputs = [2,4,6,8]
Training targets = [4,6,8,10]
Fitted intercept = 2; lag coefficient = 1
Next forecast = 2 + 1 × 10 = 12The exact fit follows from this invented sequence and should not be expected in real records.
3. Advance the Origin Without Borrowing the Target
After evaluating one prediction, the newly observed demand can enter the next origin’s history. Refit using that enlarged prefix if that is the chosen deployment procedure.
The same preprocessing, fitting, and forecast code must run at every origin. If a scaler is used, fit it within the prefix too. Store each prediction before inspecting its target.
A chronological split alone does not prevent leakage inside feature preparation.
Make a baseline at one forecast origin
The history stops before the unknown target day. Save the persistence prediction first, then compare it with the observation when it arrives.
import numpy as np
history = np.array([3., 6., 9., 12.])
prediction = float(history[-1])
later_observation = 15.0
print(prediction)
print(abs(later_observation - prediction))12.0
3.0The increasing sequence leaves persistence behind here. A fitted alternative still needs an honest comparison across several origins, which is the work of the project challenge.
4. Compare Matched Errors
Calculate errors for both methods on the same target days. Report the individual errors as well as a mean, since one average can hide a costly shortage. Choose an error measure aligned with planning needs.
Absolute error treats overprediction and underprediction symmetrically. If water shortage costs more, evaluate a stated asymmetric decision cost rather than pretending MAE already represents it.
Targets = [12,14]
Persistence predictions = [10,12]; MAE = 2
Autoregressive predictions = [12,14]; MAE = 0The comparison supports only these synthetic evaluation cases.
5. Describe What Would Break the Procedure
Seasonal patterns, weather changes, demand caps, missing days, and delayed records can all violate this simple setup. Test those conditions separately and compare seasonal baselines when repetition is present.
For deployment, save schema and preparation with the chosen model and record forecast timestamps. Monitor errors after actual demand arrives, without silently changing the evaluation window.
Explain what information the forecast could use at prediction time, show where it failed, and compare its score with the baseline. That gives someone else enough context to judge the result.
6. Try a Record That Does Not Follow Our Rule Exactly
A short, tidy record can make a fitted rule look more useful than it is. Now give Botie daily water measurements with both an upward trend and days that interrupt it. Keep the last five days for successive one-day forecasts. At each origin, train only on the prefix that would have existed then.
Compare the learned lag rule with persistence on exactly the same dates. Keep every error before taking an average. If the learned model loses, report that result. The purpose of this project is to discover whether fitting helped, not to arrange a victory for the fitted model.
Litres by day: [8,10,9,13,12,16,14,19,13,18]
First forecast: index 5, using indices 0 through 4
Next forecast: index 6, using indices 0 through 5These are invented measurements. A result on this sequence is an implementation check, not evidence of performance at a real greenhouse.
7. Make the Information Boundary Part of the Function
Write rolling_report so the function receives the complete sequence but slices a fresh training prefix inside each iteration. That makes the boundary visible in one place. Pair each previous reading with the following reading inside that prefix; never pair the final training reading with the hidden target while fitting.
Return a dictionary of named lists: origins, actual, predicted and baseline. Their matching positions describe the same forecast. Add the two mean absolute errors in the stated order. A dictionary is useful here because an unnamed tuple makes it easy to mistake actual values for predictions.
Change only the very last observation and run the function again. All predictions should stay unchanged, while the last actual value and measured error can change. This test checks the procedure rather than whether one printed answer looks plausible.
8. Save Enough to Reproduce a Forecast
For the final evaluation date, save the intercept, lag coefficient, previous-day reading and final training index. Record feature order, units and a format version alongside the parameters. These values let another program reproduce that particular forecast.
The downloadable JSON report also contains all forecast origins, predictions, targets and baseline errors. JSON represents a dictionary as named fields and NumPy arrays as ordinary lists. Convert values to Python numbers before serializing. Do not include a Python object that only the original process knows how to reconstruct.
saved prediction = intercept + lag_coefficient × last_inputThis saved model was fitted before the final evaluation target. A deployment model might later be refitted on more observations; give that model a new record rather than silently replacing the evaluated one.
9. Decide What the Errors Tell Us to Try Next
Inspect the largest date-level errors. Did both rules miss a sudden change, or did the fitted rule amplify a temporary increase? A weather measurement might explain a change, but only use a weather value that would have been available when the forecast was made.
Keep a later period untouched while choosing features and settings. Repeatedly choosing whichever rule wins on these five dates turns this small evaluation into training feedback. The final report should state the time boundary, the baseline comparison and a specific next experiment, including a disappointing result when that is what the measurements show.
Check yourself
Questions on Parts 1 to 9
Question 1 of 4
Which records may be used for fitting at that origin?
Use the information below.
Forecast target is day 6; days 1 to 5 are available.Try it with Botie
Build with Botie
Write and run Python