MODULE REFERENCE
reconciliation
anomx.data.processing.transformers.reconciliationHierarchical 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.
| Parameter | Type | Default |
|---|---|---|
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 |
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 to1(sequential). Setting the parameter to-1means 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 byparallel_paramsare assumed to be aSequenceof values that should be used for that parameter in each parallel job; the length of thisSequenceshould equal the number of parallel jobs. Ifparallel_params=True, every fixed parameter will take on a different value for each parallel job. Ifparallel_params=False, every fixed parameter will take on the same value for each parallel job. Ifparallel_paramsis aSequenceof 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 theTimeSeriesinputs passed totransform,fit,inverse_transform, orfit_transform. IfTrue, any specifiedcomponent_maskwill be applied to each input timeseries before passing them to the called method; the masked components will also be automatically 'unmasked' in the returnedTimeSeries. IfFalse, thencomponent_mask(if provided) will be passed as a keyword argument, but won't automatically be applied to the input timeseries. Seeapply_component_maskfor 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 ifcolumnsis provided, themask_componentsattribute must be set toTrue.- uses_insample
Whether the transformer requires the in-sample (historic) series during inverse transformation. If
True,inverse_transformwill use theinsampleargument to pass the transformed historic series tots_inverse_transform. This is needed when inverse transforming a partial series (e.g. a forecast) requires information from earlier times (e.g. foranomx.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)| Parameter | Type | Default |
|---|---|---|
series | — | required |
ts_transformstaticmethod
ts_transform(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> TimeSeries| Parameter | Type | Default |
|---|---|---|
series | TimeSeries | required |
params | Mapping[str, Any] | required |
*args | — | — |
**kwargs | — | — |
Returns TimeSeries
MinTReconciliator
MinTReconciliator(method = 'ols')Bases: FittableDataTransformer
| Parameter | Type | Default |
|---|---|---|
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
Wof the forecast errors is estimated (corresponding toWhin [2]_):olsusesW = I. This option looks only at the hierarchy but ignores the values of the series provided tofit().wls_structusesW = diag(S1), whereS1is a vector of sizenwith values between 0 andm, representing the number of base components composing each of thencomponents. This options looks only at the hierarchy but ignores the values of the series provided tofit().wls_varusesW = diag(W1), whereW1is the temporal average of the variance of the forecasting residuals. This method assumes that the series provided tofit()contain the forecast residuals (deterministic series).mint_covcomputesWas the empirical covariance matrix of the residuals for each component, with residuals samples taken over time. This method assumes that the series provided tofit()contain the forecast residuals (deterministic series), and it requires the residuals to be linearly independent.wls_valusesW = diag(V1), whereV1is the temporal average of the component values. This method assumes that the series provided tofit()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| Parameter | Type | Default |
|---|---|---|
series | TimeSeries | required |
params | Mapping[str, Any] | required |
*args | — | — |
**kwargs | — | — |
Returns np.ndarray
ts_transformstaticmethod
ts_transform(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> TimeSeries| Parameter | Type | Default |
|---|---|---|
series | TimeSeries | required |
params | Mapping[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.
| Parameter | Type | Default |
|---|---|---|
series | TimeSeries | None | required |
method | str | required |
Inherited members
fitFittableDataTransformertransformFittableDataTransformerfit_transformFittableDataTransformerset_verboseBaseDataTransformerset_n_jobsBaseDataTransformerapply_component_maskBaseDataTransformerunapply_component_maskBaseDataTransformerstack_samplesBaseDataTransformerunstack_samplesBaseDataTransformernameBaseDataTransformerTopDownReconciliator
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.
| Parameter | Type | Default |
|---|---|---|
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 |
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 differentTimeSeries. Defaults to1(sequential). Setting the parameter to-1means 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 byparallel_paramsare assumed to be aSequenceof values that should be used for that parameter in each parallel job; the length of thisSequenceshould equal the number of parallel jobs. Ifparallel_params=True, every fixed parameter will take on a different value for each parallel job. Ifparallel_params=False, every fixed parameter will take on the same value for each parallel job. Ifparallel_paramsis aSequenceof 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 theTimeSeriesinputs passed totransform,fit,inverse_transform, orfit_transform. IfTrue, any specifiedcomponent_maskwill be applied to each input timeseries before passing them to the called method; the masked components will also be automatically 'unmasked' in the returnedTimeSeries. IfFalse, thencomponent_mask(if provided) will be passed as a keyword argument, but won't automatically be applied to the input timeseries. Seeapply_component_maskmethod ofBaseDataTransformerfor 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
BaseDataTransformerdocumentation. 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
TimeSeriespassed to thefit()method should be used to fit a *single* set of parameters, or if a different set of parameters should be independently fitted to each providedTimeSeries. IfTrue, then aSequence[TimeSeries]is passed tots_fitand a single set of parameters is fitted using all providedTimeSeries. IfFalse, then eachTimeSeriesis individually passed tots_fit, and a different set of fitted parameters if yielded for each of these fitting operations. Seets_fitfor further details.- uses_insample
Whether the transformer requires the in-sample (historic) series during inverse transformation. If
True,inverse_transformwill use theinsampleargument to pass the transformed historic series tots_inverse_transform. This is needed when inverse transforming a partial series (e.g. a forecast) requires information from earlier times (e.g. foranomx.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| Parameter | Type | Default |
|---|---|---|
series | TimeSeries | required |
params | Mapping[str, Any] | required |
*args | — | — |
**kwargs | — | — |
Returns np.ndarray
ts_transformstaticmethod
ts_transform(series: TimeSeries, params: Mapping[str, Any], *args, **kwargs) -> TimeSeries| Parameter | Type | Default |
|---|---|---|
series | TimeSeries | required |
params | Mapping[str, Any] | required |
*args | — | — |
**kwargs | — | — |
Returns TimeSeries
get_projection_matrixstaticmethod
get_projection_matrix(series)| Parameter | Type | Default |
|---|---|---|
series | — | required |
Inherited members
fitFittableDataTransformertransformFittableDataTransformerfit_transformFittableDataTransformerset_verboseBaseDataTransformerset_n_jobsBaseDataTransformerapply_component_maskBaseDataTransformerunapply_component_maskBaseDataTransformerstack_samplesBaseDataTransformerunstack_samplesBaseDataTransformernameBaseDataTransformer