graphtoolbox.aggregation.aggregation¶
Online and batch expert aggregation (Opera-style robust prediction).
This module provides Aggregation, a self-contained implementation of
sequential expert aggregation in the spirit of the R package opera
(Gaillard & Goude). Given a matrix of expert forecasts and the corresponding
observations, the class combines the experts into a single forecast whose
weights adapt over time so as to track, and provably compete with, the best
expert (or the best fixed convex combination) in hindsight.
Implemented aggregation rules¶
"EWA"Exponentially Weighted Average (Hedge). Fixed learning rate,calibrated automatically when observations are available.
"MLpol"ML-Poly with the polynomial potential of Gaillard, Stoltz &van Erven (2014). Fully parameter-free (per-expert adaptive learning rate); the robust default.
"BOA"Bernstein Online Aggregation (Wintenberger, 2017). Second-orderupdate with an exponential potential.
"uniform": Static uniform mean of the experts (baseline)."best"Oracle constant weight on the single best expert over the wholehorizon (baseline; requires observations).
References
Cesa-Bianchi, N. & Lugosi, G. (2006). Prediction, Learning, and Games.
Gaillard, P., Stoltz, G. & van Erven, T. (2014). A second-order bound with excess losses. COLT.
Wintenberger, O. (2017). Optimal learning with Bernstein online aggregation. Machine Learning.
Gaillard, P. & Goude, Y. opera: Online Prediction by Expert Aggregation (R package).
- class graphtoolbox.aggregation.aggregation.Aggregation(model: str = 'MLpol', loss: str = 'square', learning_rate: float | None = None, gradient: bool = True, prior: ndarray | Tensor | None = None)[source][source]¶
Bases:
objectSequential aggregation of expert forecasts.
The estimator consumes a matrix of expert predictions of shape
[T, K](Ttime steps,Kexperts) and, when observationsyof shape[T]are available, produces an aggregated forecast whose weights are updated online. The full trajectory of weights is exposed inweights_, and the final convex weight vector incoefficients_, so that the fitted mixture can be reused as a static combiner on out-of-sample experts throughpredict().- Parameters:
model ({"MLpol", "EWA", "BOA", "uniform", "best"}, default "MLpol") – Aggregation rule.
"MLpol"is parameter-free and is a robust default.loss ({"square", "absolute", "percentage"}, default "square") – Loss used both to evaluate experts and to drive the weight updates.
learning_rate (float or None, default None) – Learning rate
etafor"EWA"and"BOA". WhenNoneand observations are provided, it is calibrated automatically by replaying the sequence over a logarithmic grid and keeping the value with the lowest cumulative loss (seelearning_rate_). Ignored by"MLpol","uniform"and"best".gradient (bool, default True) – If
True, updates use the linearised (gradient) pseudo-lossg_t * x_{t,k}, as inopera. This guarantees bounded, convex regrets. IfFalse, updates use the raw per-expert losses.prior (numpy.ndarray or None, default None) – Optional prior weights of shape
[K](non-negative, summing to one). Defaults to the uniform prior.
- weights_¶
Weight trajectory of shape
[T, K]; rowtholds the weights used to form the forecast at timet(before observingy_t).- Type:
numpy.ndarray
- coefficients_¶
Final weight vector of shape
[K](the weights that would be applied to the next, unseen time step).- Type:
numpy.ndarray
- prediction_¶
Aggregated forecast of shape
[T]from the last online run.- Type:
numpy.ndarray
- experts_loss_¶
Per-expert cumulative loss of shape
[K].- Type:
numpy.ndarray
- loss_¶
Cumulative loss of the aggregated forecast.
- Type:
float
- learning_rate_¶
Learning rate actually used (relevant for
"EWA"/"BOA").- Type:
float
Examples
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> T, K = 500, 4 >>> y = np.sin(np.linspace(0, 20, T)) >>> experts = y[:, None] + rng.normal(0, [0.1, 0.3, 0.6, 1.0], size=(T, K)) >>> agg = Aggregation(model="MLpol").run(experts, y) >>> agg.loss_ < (experts - y[:, None]).__pow__(2).mean(0).min() * T True
- run(experts: ndarray | Tensor, y: ndarray | Tensor, block_size: int = 1) Aggregation[source][source]¶
Run the online aggregation over a full sequence.
- Parameters:
experts (array-like of shape [T, K]) – Expert forecasts (numpy array or torch tensor).
y (array-like of shape [T]) – Observations.
block_size (int, default 1) – Forecast-commitment granularity, following
opera’spredict/updatesplit. Withblock_size=1the weights are updated at every step. Withblock_size=hthe forecast for a whole block ofhsteps is committed with the weights known at the block’s start; once the block is observed the internal weights still advance one step at a time within it, asoperaloops over the block insideupdate. For a day-ahead forecast served in daily batches of 48 half-hours, setblock_size=48.
- Returns:
self, withweights_,prediction_,coefficients_,experts_loss_andloss_set.- Return type:
- fit(experts: ndarray | Tensor, y: ndarray | Tensor, block_size: int = 1) Aggregation[source][source]¶
Alias of
run()that returnsself(scikit-style).
- predict(experts: ndarray | Tensor) ndarray[source][source]¶
Apply the fitted static weights (
coefficients_) to new experts.Use this for out-of-sample combination once the mixture has been fitted on a history via
run(). For time-varying online weights on a fresh sequence, callrun()again with the new observations.- Parameters:
experts (array-like of shape [T, K]) – New expert forecasts.
- Returns:
Aggregated forecast of shape
[T].- Return type:
numpy.ndarray
- reset(n_experts: int) Aggregation[source][source]¶
Initialise streaming state for
n_expertsexperts.After
reset, alternatepartial_fit()(to get the forecast for the current step) andupdate()(to feed back the observation).- Parameters:
n_experts (int) – Number of experts
K.- Returns:
self.- Return type:
- partial_fit(expert_row: ndarray | Tensor) float[source][source]¶
Return the aggregated forecast for the current step.
- Parameters:
expert_row (array-like of shape [K]) – The experts’ forecasts for the current time step.
- Returns:
Aggregated forecast.
- Return type:
float
- update(y_t: float) None[source][source]¶
Feed back the observation for the step served by
partial_fit().- Parameters:
y_t (float) – Observation for the current time step.
- property streaming_weights_: ndarray¶
Weight trajectory accumulated through the streaming interface.
- summary() Dict[str, float][source][source]¶
Return a compact performance summary of the fitted mixture.
- Returns:
Keys:
model,loss(mean aggregated loss),best_expert_loss(mean loss of the best single expert),mean_expert_loss(average over experts of their mean loss) andlearning_rate.- Return type:
dict