Example #1
0
def revise_forecasts(
    method: str,
    forecasts: Dict[str, numpy.ndarray],
    errors: Optional[Dict[str, numpy.ndarray]] = None,
    residuals: Optional[Dict[str, numpy.ndarray]] = None,
    summing_matrix: numpy.ndarray = None,
    nodes: NAryTreeT = None,
    transformer: TransformT = None,
):
    """
    Convenience function to get revised forecast for pre-computed base forecasts

    Parameters
    ----------
    method : str
        The reconciliation method to use
    forecasts : Dict[str, numpy.ndarray]
        A dict mapping key name to its forecasts (including in-sample forecasts). Required.
    errors : Dict[str, numpy.ndarray]
        A dict mapping key name to the in-sample errors. Required for methods: ``OLS``, ``WLSS``, ``WLSV``
    residuals : Dict[str, numpy.ndarray]
        A dict mapping key name to the residuals of in-sample forecasts. Required for methods: OLS, WLSS, WLSV
    summing_matrix : numpy.ndarray
        Not required if ``nodes`` argument is passed, or if using ``BU`` approach
    nodes : NAryTreeT
        The tree of nodes as specified in :py:class:`HierarchyTree <hts.hierarchy.HierarchyTree>`. Required if not
        if using ``AHP``, ``PHA` ``FP`` methods, or if using  passing the ``OLS``, ``WLSS``, ``WLSV`` methods
          and not passing the ``summing_matrix`` parameter
    transformer : TransformT
        A transform with the method: ``inv_func`` that will be applied to the forecasts

    Returns
    -------
    revised forecasts : pandas.DataFrame
        The revised forecasts
    """

    if nodes:
        summing_matrix = to_sum_mat(nodes)

    if method in [MethodT.AHP.name, MethodT.PHA.name, MethodT.FP.name
                  ] and not nodes:
        raise ValueError(f"Method {method} requires an NAryTree to be passed")

    if method in [MethodT.OLS.name, MethodT.WLSS.name, MethodT.WLSV.name]:
        if not (all([forecasts, errors, residuals]) or (not summing_matrix)):
            raise ValueError(
                f"Method {method} requires forecasts, errors, and residuals to be passed, as "
                f"well as an NAryTree or a summing matrix")

    revision = RevisionMethod(name=method,
                              sum_mat=summing_matrix,
                              transformer=transformer)

    revised = revision.revise(forecasts=forecasts, mse=errors, nodes=nodes)

    return pandas.DataFrame(revised, columns=list(forecasts.keys()))
Example #2
0
def test_instantiate_revision(load_df_and_hier_visnights):
    hierarchical_visnights_data, visnights_hier = load_df_and_hier_visnights

    for method in ['OLS', 'FP', 'WLSS', 'WLSV', 'PHA', 'AHP', 'NONE']:
        ht = HTSRegressor(model='holt_winters', revision_method=method)
        ht.fit(df=hierarchical_visnights_data, nodes=visnights_hier)

        rm = RevisionMethod(method,
                            sum_mat=ht.sum_mat,
                            transformer=ht.transform)

        _ = ht.predict(steps_ahead=3)
        revised = rm.revise(forecasts=ht.hts_result.forecasts,
                            mse=ht.hts_result.errors,
                            nodes=ht.nodes)
        assert isinstance(revised, numpy.ndarray)
        assert revised.shape == (11, len(ht.hts_result.forecasts))
Example #3
0
 def _init_revision(self):
     self.revision_method = RevisionMethod(sum_mat=self.sum_mat,
                                           transformer=self.transform,
                                           name=self.method)
Example #4
0
def revise_forecasts(
    method: str,
    forecasts: Dict[str, ArrayLike],
    errors: Optional[Dict[str, float]] = None,
    residuals: Optional[Dict[str, ArrayLike]] = None,
    summing_matrix: numpy.ndarray = None,
    nodes: NAryTreeT = None,
    transformer: TransformT = None,
):
    """
    Convenience function to get revised forecast for pre-computed base forecasts

    Parameters
    ----------
    method : str
        The reconciliation method to use
    forecasts : Dict[str, ArrayLike]
        A dict mapping key name to its forecasts (including in-sample forecasts). Required, can be
        of type ``numpy.ndarray`` of ``ndim == 1``, ``pandas.Series``, or single columned ``pandas.DataFrame``
    errors : Dict[str, float]
        A dict mapping key name to the in-sample errors. Required for methods: ``OLS``, ``WLSS``, ``WLSV`` if
        ``residuals`` is not passed
    residuals : Dict[str, ArrayLike]
        A dict mapping key name to the residuals of in-sample forecasts. Required for methods: ``OLS``, ``WLSS``,
        ``WLSV``, can be of type ``numpy.ndarray`` of ndim == 1, ``pandas.Series``, or single columned
        ``pandas.DataFrame``. If passing residuals, ``errors`` dict is not required and will instead be calculated
        using MSE metric: ``numpy.mean(numpy.array(residual) ** 2)``
    summing_matrix : numpy.ndarray
        Not required if ``nodes`` argument is passed, or if using ``BU`` approach
    nodes : NAryTreeT
        The tree of nodes as specified in :py:class:`HierarchyTree <hts.hierarchy.HierarchyTree>`. Required if not
        if using ``AHP``, ``PHA``, ``FP`` methods, or if using  passing the ``OLS``, ``WLSS``, ``WLSV`` methods
        and not passing the ``summing_matrix`` parameter
    transformer : TransformT
        A transform with the method: ``inv_func`` that will be applied to the forecasts

    Returns
    -------
    revised forecasts : ``pandas.DataFrame``
        The revised forecasts
    """

    if nodes:
        summing_matrix, sum_mat_labels = to_sum_mat(nodes)

    if method in [MethodT.AHP.name, MethodT.PHA.name, MethodT.FP.name
                  ] and not nodes:
        raise ValueError(f"Method {method} requires an NAryTree to be passed")

    if method in [MethodT.OLS.name, MethodT.WLSS.name, MethodT.WLSV.name]:
        errors = _calculate_errors(method=method,
                                   errors=errors,
                                   residuals=residuals)
        if not (all([forecasts, errors]) or (not summing_matrix)):
            raise ValueError(
                f"Method {method} requires forecasts, errors, and residuals to be passed, as "
                f"well as an NAryTree or a summing matrix")

    revision = RevisionMethod(name=method,
                              sum_mat=summing_matrix,
                              transformer=transformer)
    sanitized_forecasts = _sanitize_forecasts_dict(forecasts)
    revised = revision.revise(forecasts=sanitized_forecasts,
                              mse=errors,
                              nodes=nodes)

    return pandas.DataFrame(revised, columns=list(sanitized_forecasts.keys()))