MODULE REFERENCE

reconciliation

anomx.data.processing.transformers.reconciliation

Hierarchical Reconciliation

A set of posthoc hierarchical reconciliation transformers. These transformers work on any TimeSeries (e.g., a forecast) that contain a hierarchy.

A hierarchy is a dict that maps each component to their parent(s) in the hierarchy. It can be added to a TimeSeries using e.g., the anomx.data.timeseries.TimeSeries.with_hierarchy method.

BottomUpReconciliator

BottomUpReconciliator(name: str = 'BaseDataTransformer', n_jobs: int = 1, verbose: bool = False, parallel_params: bool | Sequence[str] = False, mask_components: bool = True, columns: str | list[str] | None = None, uses_insample: bool = False)

Bases: BaseDataTransformer

Performs bottom up reconciliation, as defined here.

Signature parameters
ParameterTypeDefault
namestr'BaseDataTransformer'
n_jobsint1
verboseboolFalse
parallel_paramsbool | Sequence[str]False
mask_componentsboolTrue
columnsstr | list[str] | NoneNone
uses_insampleboolFalse

Abstract class for data transformers.

All the deriving classes have to implement the static method ts_transform; this implemented method can then be applied to TimeSeries or Sequence[TimeSeries] inputs by calling the transform() method. Internally, transform() parallelizes func:ts_transform over all of the TimeSeries inputs passed to it. See the func:ts_transform method documentation for further details on how to implement this method in a user-defined class.

Data transformers requiring to be fit first before calling transform should derive from anomx.data.processing.transformers.FittableDataTransformer instead. Data transformers that are invertible should derive from anomx.data.processing.transformers.InvertibleDataTransformer instead. Transformers which are both fittable and invertible should inherit from both anomx.data.processing.transformers.FittableDataTransformer and anomx.data.processing.transformers.InvertibleDataTransformer.

All Data Transformers can store *fixed parameters* that are automatically passed to func:ts_transform; the fixed parameters of a data transformer object are taken to be all those attributes defined in the __init__ method of the child-most class *before* super().__init__ is called. The fixed parameter values can then be accessed within the func:ts_transform method through the params dictionary argument. More specifically, params['fixed'] stores a dictionary with all of the fixed parameter values, where the keys are simply the attribute names of each fixed parameter (e.g. the self._my_param fixed parameter attribute is accessed through params['fixed']['_my_param']).

Data Transformers which inherit from anomx.data.processing.transformers.FittableDataTransformer can also store fitted parameters alongside fixed parameters; please refer to the anomx.data.processing.transformers.FittableDataTransformer documentation for further details.

Note: the ts_transform method is designed to be a static method instead of a instance method to allow an efficient parallelisation also when the scaler instance is storing a non-negligible amount of data. Using an instance method would imply copying the instance's data through multiple processes, which can easily introduce a bottleneck and nullify parallelisation benefits.

Parameters

name

The data transformer's name

n_jobs

The number of jobs to run in parallel. Parallel jobs are created only when a Sequence[TimeSeries] is passed as input to a method, parallelising operations regarding different TimeSeries. Defaults to 1 (sequential). Setting the parameter to -1 means using all the available processors. Note: for a small amount of data, the parallelisation overhead could end up increasing the total required amount of time.

verbose

Optionally, whether to print operations progress

parallel_params

Optionally, specifies which fixed parameters (i.e. the attributes initialized in the child-most class's __init__) take on different values for different parallel jobs. Fixed parameters specified by parallel_params are assumed to be a Sequence of values that should be used for that parameter in each parallel job; the length of this Sequence should equal the number of parallel jobs. If parallel_params=True, every fixed parameter will take on a different value for each parallel job. If parallel_params=False, every fixed parameter will take on the same value for each parallel job. If parallel_params is a Sequence of fixed attribute names, only those attribute names specified will take on different values between different parallel jobs.

mask_components

Optionally, whether to automatically apply any provided component_masks to the TimeSeries inputs passed to transform, fit, inverse_transform, or fit_transform. If True, any specified component_mask will be applied to each input timeseries before passing them to the called method; the masked components will also be automatically 'unmasked' in the returned TimeSeries. If False, then component_mask (if provided) will be passed as a keyword argument, but won't automatically be applied to the input timeseries. See apply_component_mask for further details.

columns

Optionally, a string or list of strings specifying the names of the components (columns) to transform. If specified, only these components will be transformed, and the remaining components will be kept untouched. If None, all components are transformed. Note that if columns is provided, the mask_components attribute must be set to True.

uses_insample

Whether the transformer requires the in-sample (historic) series during inverse transformation. If True, inverse_transform will use the insample argument to pass the transformed historic series to ts_inverse_transform. This is needed when inverse transforming a partial series (e.g. a forecast) requires information from earlier times (e.g. for anomx.data.processing.transformers.diff.Diff).

Example

>>> from anomx.data.processing.transformers import BaseDataTransformer
>>> from anomx._series_utils.timeseries_generation import linear_timeseries
>>>
>>> class SimpleTransform(BaseDataTransformer):
>>>     def __init__(self, a):
>>>         self._a = a
>>>         super().__init__()
>>>
>>>     @staticmethod
>>>     def ts_transform(series, params, **kwargs):
>>>         a = params['fixed']['_a']
>>>         b = kwargs.pop('b')
>>>         return a*series + b
>>>
>>> series = linear_timeseries(length=5)
>>> print(series.values())
[[0.  ]
 [0.25]
 [0.5 ]
 [0.75]
 [1.  ]]
>>> series = SimpleTransform(a=2).transform(series, b=3)
>>> print(series.values())
[[3. ]
 [3.5]
 [4. ]
 [4.5]
 [5. ]]

Members

get_projection_matrixstaticmethod
get_projection_matrix(series)
Signature parameters
ParameterTypeDefault
series—required
ts_transformstaticmethod
ts_transform(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> TimeSeries
Signature parameters
ParameterTypeDefault
seriesTimeSeriesrequired
paramsMapping[str, Any]required
*args——
**kwargs——

Returns TimeSeries

MinTReconciliator

MinTReconciliator(method = 'ols')

Bases: FittableDataTransformer

Signature parameters
ParameterTypeDefault
method—'ols'

MinT Reconcilator.

This implements the MinT reconciliation approach presented in [1]_ and summarised in [2]_.

Parameters

method

This parameter can take four different values, determining how the covariance matrix W of the forecast errors is estimated (corresponding to Wh in [2]_):

  • ols uses W = I. This option looks only at the hierarchy but ignores the values of the series provided to fit().
  • wls_struct uses W = diag(S1), where S1 is a vector of size n with values between 0 and m, representing the number of base components composing each of the n components. This options looks only at the hierarchy but ignores the values of the series provided to fit().
  • wls_var uses W = diag(W1), where W1 is the temporal average of the variance of the forecasting residuals. This method assumes that the series provided to fit() contain the forecast residuals (deterministic series).
  • mint_cov computes W as the empirical covariance matrix of the residuals for each component, with residuals samples taken over time. This method assumes that the series provided to fit() contain the forecast residuals (deterministic series), and it requires the residuals to be linearly independent.
  • wls_val uses W = diag(V1), where V1 is the temporal average of the component values. This method assumes that the series provided to fit() contains an example of the actual values (e.g., either the training series or the forecasts). This method is not presented in [2]_.

References

.. [1] Optimal forecast reconciliation for hierarchical and grouped time series through trace minimization .. [2] https://otexts.com/fpp3/reconciliation.html#the-mint-optimal-reconciliation-approach

Members

ts_fitstaticmethod
ts_fit(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> np.ndarray
Signature parameters
ParameterTypeDefault
seriesTimeSeriesrequired
paramsMapping[str, Any]required
*args——
**kwargs——

Returns np.ndarray

ts_transformstaticmethod
ts_transform(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> TimeSeries
Signature parameters
ParameterTypeDefault
seriesTimeSeriesrequired
paramsMapping[str, Any]required
*args——
**kwargs——

Returns TimeSeries

get_matricesstaticmethod
get_matrices(series: TimeSeries | None, method: str)

Returns the G matrix given a specified reconciliation method.

Signature parameters
ParameterTypeDefault
seriesTimeSeries | Nonerequired
methodstrrequired

TopDownReconciliator

TopDownReconciliator(name: str = 'FittableDataTransformer', n_jobs: int = 1, verbose: bool = False, parallel_params: bool | Sequence[str] = False, mask_components: bool = True, columns: str | list[str] | None = None, global_fit: bool = False, uses_insample: bool = False)

Bases: FittableDataTransformer

Performs top down reconciliation, as defined here.

This estimator computes the proportions (of the base components w.r.t. the top component) based on the TimeSeries provided to the method fit(). If the historical series is provided, then the historical proportions will be used.

Signature parameters
ParameterTypeDefault
namestr'FittableDataTransformer'
n_jobsint1
verboseboolFalse
parallel_paramsbool | Sequence[str]False
mask_componentsboolTrue
columnsstr | list[str] | NoneNone
global_fitboolFalse
uses_insampleboolFalse

Base class for fittable transformers.

All the deriving classes have to implement the static methods ts_transform() and ts_fit(). The fitting and transformation functions must be passed during the transformer's initialization. This class takes care of parallelizing operations involving multiple TimeSeries when possible.

Parameters

name

The data transformer's name

n_jobs

The number of jobs to run in parallel. Parallel jobs are created only when a Sequence[TimeSeries] is passed as input to a method, parallelising operations regarding different TimeSeries. Defaults to 1 (sequential). Setting the parameter to -1 means using all the available processors. Note: for a small amount of data, the parallelisation overhead could end up increasing the total required amount of time.

verbose

Optionally, whether to print operations progress

parallel_params

Optionally, specifies which fixed parameters (i.e. the attributes initialized in the child-most class's __init__) take on different values for different parallel jobs. Fixed parameters specified by parallel_params are assumed to be a Sequence of values that should be used for that parameter in each parallel job; the length of this Sequence should equal the number of parallel jobs. If parallel_params=True, every fixed parameter will take on a different value for each parallel job. If parallel_params=False, every fixed parameter will take on the same value for each parallel job. If parallel_params is a Sequence of fixed attribute names, only those attribute names specified will take on different values between different parallel jobs.

mask_components

Optionally, whether to automatically apply any provided component_masks to the TimeSeries inputs passed to transform, fit, inverse_transform, or fit_transform. If True, any specified component_mask will be applied to each input timeseries before passing them to the called method; the masked components will also be automatically 'unmasked' in the returned TimeSeries. If False, then component_mask (if provided) will be passed as a keyword argument, but won't automatically be applied to the input timeseries. See apply_component_mask method of BaseDataTransformer for further details.

columns

Optionally, a string or list of strings specifying the names of the components (columns) to transform. If specified, only these components will be transformed, and the remaining components will be kept untouched. For more information refer to the BaseDataTransformer documentation. In case the transformer is applied on multiple TimeSeries, it is expected that all series have the same column order.

global_fit

Optionally, whether all TimeSeries passed to the fit() method should be used to fit a *single* set of parameters, or if a different set of parameters should be independently fitted to each provided TimeSeries. If True, then a Sequence[TimeSeries] is passed to ts_fit and a single set of parameters is fitted using all provided TimeSeries. If False, then each TimeSeries is individually passed to ts_fit, and a different set of fitted parameters if yielded for each of these fitting operations. See ts_fit for further details.

uses_insample

Whether the transformer requires the in-sample (historic) series during inverse transformation. If True, inverse_transform will use the insample argument to pass the transformed historic series to ts_inverse_transform. This is needed when inverse transforming a partial series (e.g. a forecast) requires information from earlier times (e.g. for anomx.data.processing.transformers.diff.Diff).

Notes

If global_fit is False and fit is called with a Sequence containing n different TimeSeries, then n sets of parameters will be fitted. When transform and/or inverse_transform is subsequently called with a Series[TimeSeries], the ith set of fitted parameter values will be passed to ts_transform/ts_inverse_transform to transform the ith TimeSeries in this sequence. Conversely, if global_fit is True, then only a single set of fitted values will be produced when fit is provided with a Sequence[TimeSeries]. Consequently, if a Sequence[TimeSeries] is then passed to transform/inverse_transform, each of these TimeSeries will be transformed using the exact same set of fitted parameters.

Note that if an invertible *and* fittable data transformer is to be globally fitted, the data transformer class should first inherit from FittableDataTransformer and then from InvertibleDataTransformer. In other words, MyTransformer(FittableDataTransformer, InvertibleDataTransformer) is correct, but MyTransformer(InvertibleDataTransformer, FittableDataTransformer) is not. If this is not implemented correctly, then the global_fit parameter will not be correctly passed to FittableDataTransformer's constructor.

The ts_transform() and ts_fit() methods are designed to be static methods instead of instance methods to allow an efficient parallelisation also when the scaler instance is storing a non-negligible amount of data. Using instance methods would imply copying the instance's data through multiple processes, which can easily introduce a bottleneck and nullify parallelisation benefits.

Example

>>> from anomx.data.processing.transformers import FittableDataTransformer
>>> from anomx._series_utils.timeseries_generation import linear_timeseries
>>>
>>> class SimpleRangeScaler(FittableDataTransformer):
>>>
>>>     def __init__(self, scale, position):
>>>         self._scale = scale
>>>         self._position = position
>>>         super().__init__()
>>>
>>>     @staticmethod
>>>     def ts_transform(series, params):
>>>         vals = series.all_values(copy=False)
>>>         fit_params = params['fitted']
>>>         unit_scale = (vals - fit_params['position'])/fit_params['scale']
>>>         fix_params = params['fixed']
>>>         rescaled = fix_params['_scale'] * unit_scale + fix_params['_position']
>>>         return series.from_values(rescaled)
>>>
>>>     @staticmethod
>>>     def ts_fit(series, params):
>>>         vals = series.all_values(copy=False)
>>>         scale = vals.max() - vals.min()
>>>         position = vals[0]
>>>         return {'scale': scale, 'position': position}
>>>
>>> series = linear_timeseries(length=5, start_value=1, end_value=5)
>>> print(series.values())
[[1.]
 [2.]
 [3.]
 [4.]
 [5.]]
>>> series = SimpleRangeScaler(scale=2, position=-1).fit_transform(series)
>>> print(series.values())
[[-1. ]
 [-0.5]
 [ 0. ]
 [ 0.5]
 [ 1. ]]

Members

ts_fitstaticmethod
ts_fit(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> np.ndarray
Signature parameters
ParameterTypeDefault
seriesTimeSeriesrequired
paramsMapping[str, Any]required
*args——
**kwargs——

Returns np.ndarray

ts_transformstaticmethod
ts_transform(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> TimeSeries
Signature parameters
ParameterTypeDefault
seriesTimeSeriesrequired
paramsMapping[str, Any]required
*args——
**kwargs——

Returns TimeSeries

get_projection_matrixstaticmethod
get_projection_matrix(series)
Signature parameters
ParameterTypeDefault
series—required