0
# Probabilistic Methods
1
2
Probabilistic reconciliation methods that generate prediction intervals and samples from hierarchically coherent distributions. These methods extend point forecasts to probabilistic forecasts while maintaining coherence across all hierarchy levels.
3
4
## Capabilities
5
6
### Normality Method
7
8
Leverages Gaussian distribution linearity to generate hierarchically coherent prediction distributions under normality assumptions.
9
10
```python { .api }
11
class Normality:
12
"""
13
Normality Probabilistic Reconciliation Class.
14
15
Generates hierarchically coherent prediction distributions assuming
16
base forecasts follow normal distributions. Uses analytical formulas
17
to derive reconciled distributions.
18
"""
19
20
def __init__(
21
self,
22
S: np.ndarray,
23
P: np.ndarray,
24
y_hat: np.ndarray,
25
sigmah: np.ndarray,
26
W: np.ndarray,
27
seed: int = 0
28
):
29
"""
30
Initialize Normality reconciliation.
31
32
Parameters:
33
- S: summing matrix of size (base, bottom)
34
- P: reconciliation matrix of size (bottom, base)
35
- y_hat: point forecasts of size (base, horizon)
36
- sigmah: forecast standard deviations of size (base, horizon)
37
- W: hierarchical covariance matrix of size (base, base)
38
- seed: random seed for reproducibility
39
"""
40
41
def get_samples(self, num_samples: int) -> np.ndarray:
42
"""
43
Generate coherent samples from normal distribution.
44
45
Parameters:
46
- num_samples: number of samples to generate
47
48
Returns:
49
Coherent samples of size (num_samples, base, horizon)
50
"""
51
52
def get_prediction_quantiles(
53
self,
54
results: dict,
55
quantiles: np.ndarray
56
) -> dict:
57
"""
58
Calculate prediction quantiles for given confidence levels.
59
60
Parameters:
61
- results: dict containing mean forecasts
62
- quantiles: array of quantile levels (0-1)
63
64
Returns:
65
Updated results dict with quantile forecasts
66
"""
67
```
68
69
### Bootstrap Method
70
71
Goes beyond normality assumptions by simulating future sample paths and reconciling them to generate probabilistic forecasts.
72
73
```python { .api }
74
class Bootstrap:
75
"""
76
Bootstrap Probabilistic Reconciliation Class.
77
78
Simulates future sample paths using residual bootstrap from
79
in-sample errors, then reconciles the paths to generate
80
coherent probabilistic forecasts.
81
"""
82
83
def __init__(
84
self,
85
S: np.ndarray,
86
P: np.ndarray,
87
y_hat: np.ndarray,
88
y_insample: np.ndarray,
89
y_hat_insample: np.ndarray,
90
num_samples: int,
91
seed: int = 0
92
):
93
"""
94
Initialize Bootstrap reconciliation.
95
96
Parameters:
97
- S: summing matrix of size (base, bottom)
98
- P: reconciliation matrix of size (bottom, base)
99
- y_hat: point forecasts of size (base, horizon)
100
- y_insample: historical data for residual calculation
101
- y_hat_insample: in-sample forecasts for residual calculation
102
- num_samples: number of bootstrap samples
103
- seed: random seed for reproducibility
104
"""
105
106
def get_samples(self, num_samples: int) -> np.ndarray:
107
"""
108
Generate bootstrap samples of reconciled forecasts.
109
110
Parameters:
111
- num_samples: number of bootstrap samples
112
113
Returns:
114
Bootstrap samples of size (num_samples, base, horizon)
115
"""
116
117
def get_prediction_quantiles(
118
self,
119
results: dict,
120
quantiles: np.ndarray
121
) -> dict:
122
"""
123
Calculate empirical quantiles from bootstrap samples.
124
125
Parameters:
126
- results: dict containing mean forecasts
127
- quantiles: array of quantile levels (0-1)
128
129
Returns:
130
Updated results dict with bootstrap quantiles
131
"""
132
```
133
134
### PERMBU Method
135
136
Uses empirical bottom-level marginal distributions with rank permutation copulas to generate hierarchically coherent distributions via bottom-up aggregation.
137
138
```python { .api }
139
class PERMBU:
140
"""
141
PERMBU (Permutation Bootstrap) Probabilistic Reconciliation Class.
142
143
Leverages empirical bottom-level marginal distributions with
144
estimated rank permutation copulas to generate coherent
145
aggregate-level distributions using bottom-up aggregation.
146
"""
147
148
def __init__(
149
self,
150
S: np.ndarray,
151
P: np.ndarray,
152
y_hat: np.ndarray,
153
tags: dict,
154
y_insample: np.ndarray,
155
y_hat_insample: np.ndarray,
156
sigmah: np.ndarray,
157
num_samples: int,
158
seed: int = 0
159
):
160
"""
161
Initialize PERMBU reconciliation.
162
163
Parameters:
164
- S: summing matrix of size (base, bottom)
165
- P: reconciliation matrix of size (bottom, base)
166
- y_hat: point forecasts of size (base, horizon)
167
- tags: hierarchy tags for bottom-level identification
168
- y_insample: historical data for distribution estimation
169
- y_hat_insample: in-sample forecasts for residual estimation
170
- sigmah: forecast standard deviations
171
- num_samples: number of permutation samples
172
- seed: random seed for reproducibility
173
"""
174
175
def get_samples(self, num_samples: int) -> np.ndarray:
176
"""
177
Generate PERMBU samples using rank permutation copulas.
178
179
Parameters:
180
- num_samples: number of samples to generate
181
182
Returns:
183
PERMBU samples of size (num_samples, base, horizon)
184
"""
185
186
def get_prediction_quantiles(
187
self,
188
results: dict,
189
quantiles: np.ndarray
190
) -> dict:
191
"""
192
Calculate quantiles from PERMBU samples.
193
194
Parameters:
195
- results: dict containing mean forecasts
196
- quantiles: array of quantile levels (0-1)
197
198
Returns:
199
Updated results dict with PERMBU quantiles
200
"""
201
```
202
203
## Usage Examples
204
205
### Normality Method
206
207
```python
208
from hierarchicalforecast.probabilistic_methods import Normality
209
import numpy as np
210
211
# Initialize normality method
212
normality = Normality(
213
S=summing_matrix,
214
P=reconciliation_matrix,
215
y_hat=point_forecasts,
216
sigmah=forecast_stds,
217
W=covariance_matrix,
218
seed=42
219
)
220
221
# Generate samples
222
samples = normality.get_samples(num_samples=1000)
223
224
# Calculate prediction intervals
225
results = {'mean': reconciled_forecasts}
226
quantiles = np.array([0.1, 0.9]) # 80% prediction intervals
227
results_with_intervals = normality.get_prediction_quantiles(results, quantiles)
228
```
229
230
### Bootstrap Method
231
232
```python
233
from hierarchicalforecast.probabilistic_methods import Bootstrap
234
235
# Initialize bootstrap method
236
bootstrap = Bootstrap(
237
S=summing_matrix,
238
P=reconciliation_matrix,
239
y_hat=point_forecasts,
240
y_insample=historical_data,
241
y_hat_insample=insample_forecasts,
242
num_samples=1000,
243
seed=42
244
)
245
246
# Generate bootstrap samples
247
samples = bootstrap.get_samples(num_samples=500)
248
249
# Calculate bootstrap intervals
250
results = {'mean': reconciled_forecasts}
251
quantiles = np.array([0.05, 0.95]) # 90% prediction intervals
252
bootstrap_intervals = bootstrap.get_prediction_quantiles(results, quantiles)
253
```
254
255
### PERMBU Method
256
257
```python
258
from hierarchicalforecast.probabilistic_methods import PERMBU
259
260
# Initialize PERMBU method
261
permbu = PERMBU(
262
S=summing_matrix,
263
P=reconciliation_matrix,
264
y_hat=point_forecasts,
265
tags=hierarchy_tags,
266
y_insample=historical_data,
267
y_hat_insample=insample_forecasts,
268
sigmah=forecast_stds,
269
num_samples=1000,
270
seed=42
271
)
272
273
# Generate PERMBU samples
274
samples = permbu.get_samples(num_samples=800)
275
276
# Calculate PERMBU intervals
277
results = {'mean': reconciled_forecasts}
278
quantiles = np.array([0.025, 0.975]) # 95% prediction intervals
279
permbu_intervals = permbu.get_prediction_quantiles(results, quantiles)
280
```
281
282
### Method Comparison
283
284
```python
285
# Compare different probabilistic methods
286
methods = {
287
'Normality': Normality(S, P, y_hat, sigmah, W, seed=42),
288
'Bootstrap': Bootstrap(S, P, y_hat, y_insample, y_hat_insample, 1000, seed=42),
289
'PERMBU': PERMBU(S, P, y_hat, tags, y_insample, y_hat_insample, sigmah, 1000, seed=42)
290
}
291
292
# Generate samples from each method
293
samples_dict = {}
294
for name, method in methods.items():
295
samples_dict[name] = method.get_samples(num_samples=500)
296
297
# Calculate intervals for comparison
298
quantiles = np.array([0.1, 0.9])
299
results = {'mean': reconciled_forecasts}
300
301
interval_results = {}
302
for name, method in methods.items():
303
interval_results[name] = method.get_prediction_quantiles(results.copy(), quantiles)
304
```