Nixtla / hierarchicalforecast

Probabilistic Hierarchical forecasting đź‘‘ with statistical and econometric methods.
https://nixtlaverse.nixtla.io/hierarchicalforecast
Apache License 2.0
572 stars 70 forks source link

hierarchicalforecast.core - 'list' object has no attribute 'insample' - #227

Closed edgBR closed 1 year ago

edgBR commented 1 year ago

What happened + What you expected to happen

Hi,

I am trying to reconciliate different set of models for a time series with the following hierarchy:

{'top_level/unique_id': 
['b/AA',
  'b/AP',
  'b/L']
}

Code is as follows:

Y_hier_df, S_df, tags = aggregate(df=df_aggregated_all_by_channel, spec=[['top_level', 'unique_id']])
Y_hier_df = Y_hier_df.reset_index()
Y_test_df = Y_hier_df.groupby('unique_id').tail(48)
Y_train_df = Y_hier_df.drop(Y_test_df.index)
Y_test_df = Y_test_df.set_index('unique_id')
Y_train_df.set_index('unique_id')
models_segment = [
    AutoARIMA(season_length=12, nmodels=90),
    AutoETS(),
    MSTL(season_length=12,  trend_forecaster=AutoARIMA(), alias='MSTL-ARIMA'),
    MSTL(season_length=12),
    SeasonalNaive(season_length=12),
    AutoTheta(season_length=12), 
    AutoCES(season_length=12),
    SeasonalWindowAverage(window_size=2, season_length=12, alias='SeasWA212'),
    SeasonalWindowAverage(window_size=1, season_length=12, alias='SeasWA112'),
    SeasonalWindowAverage(window_size=4, season_length=12, alias='SeasWA412'),
    RandomWalkWithDrift()
]
hier_sf = StatsForecast(
    df=Y_train_df, 
    models=models_segment,
    freq='M', 
    n_jobs=-1,
    fallback_model = SeasonalNaive(season_length=12),
    verbose=True
)

horizon = 48
#level = [95]

Y_hat_df = hier_sf.forecast(df=Y_train_df, h=horizon, fitted=True)
Y_fitted_df =  hier_sf.forecast_fitted_values()

The models fit properly:

image

But when trying to reconciliate them:

recon_methods = [BottomUp(), MinTrace(method='mint_shrink'),
                MinTrace(method='ols')], # OptimalCombination(
                    #method='wls_struct', nonnegative=True),

                #ERM(method='reg_bu')]
hrec = HierarchicalReconciliation(reconcilers=recon_methods)
Y_rec_df = hrec.reconcile(Y_hat_df=Y_hat_df, Y_df=Y_train_df, 
                          S=S_df, tags=tags)

I get the following error:


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[574], line 1
----> 1 hrec = HierarchicalReconciliation(reconcilers=recon_methods)
      2 Y_rec_df = hrec.reconcile(Y_hat_df=Y_hat_df[["ds", "AutoARIMA"]], Y_df=Y_train_df, 
      3                           S=S_df, tags=tags)

File [c:\Users\ebr\miniconda3\envs\seasonal_model\lib\site-packages\hierarchicalforecast\core.py:89](file:///C:/Users/ebr/miniconda3/envs/seasonal_model/lib/site-packages/hierarchicalforecast/core.py:89), in HierarchicalReconciliation.__init__(self, reconcilers)
     87 self.reconcilers = reconcilers
     88 self.orig_reconcilers = copy.deepcopy(reconcilers) # TODO: elegant solution
---> 89 self.insample = any([method.insample for method in reconcilers])

File [c:\Users\ebr\miniconda3\envs\seasonal_model\lib\site-packages\hierarchicalforecast\core.py:89](file:///C:/Users/ebr/miniconda3/envs/seasonal_model/lib/site-packages/hierarchicalforecast/core.py:89), in (.0)
     87 self.reconcilers = reconcilers
     88 self.orig_reconcilers = copy.deepcopy(reconcilers) # TODO: elegant solution
---> 89 self.insample = any([method.insample for method in reconcilers])

AttributeError: 'list' object has no attribute 'insample'

Versions / Dependencies

adagio==0.2.4 aiohttp==3.8.4 aiosignal==1.3.1 alembic==1.11.1 ansi2html==1.8.0 antlr4-python3-runtime==4.11.1 antropy==0.1.5 appdirs==1.4.4 arch==6.1.0 asttokens==2.2.1 async-timeout==4.0.2 attrs==23.1.0 backcall==0.2.0 bottle==0.12.25 certifi==2023.5.7 charset-normalizer==3.2.0 click==8.1.4 cmaes==0.9.1 colorama==0.4.6 colorlog==6.7.0 comm==0.1.3 contourpy==1.1.0 cramjam==2.6.2 cycler==0.11.0 dash==2.11.1 dash-core-components==2.0.0 dash-html-components==2.0.0 dash-table==5.0.0 datasetsforecast==0.0.8 debugpy==1.6.7 decorator==5.1.1 executing==1.2.0 fastjsonschema==2.17.1 fastparquet==2023.7.0 filelock==3.12.2 Flask==2.2.5 fonttools==4.41.0 frozenlist==1.4.0 fs==2.4.16 fsspec==2023.6.0 fugue==0.8.5 fugue-sql-antlr==0.1.6 greenlet==2.0.2 grpcio==1.51.3 hierarchicalforecast==0.3.0 idna==3.4 ipykernel==6.24.0 ipython==8.14.0 itsdangerous==2.1.2 jedi==0.18.2 Jinja2==3.1.2 joblib==1.3.1 jsonschema==4.18.2 jsonschema-specifications==2023.6.1 jupyter_client==8.3.0 jupyter_core==5.3.1 kiwisolver==1.4.4 lightgbm==3.3.5 lightning-utilities==0.9.0 llvmlite==0.40.1 Mako==1.2.4 MarkupSafe==2.1.3 matplotlib==3.7.2 matplotlib-inline==0.1.6 mlforecast==0.7.4 mpmath==1.3.0 msgpack==1.0.5 multidict==6.0.4 nbformat==5.9.1 nest-asyncio==1.5.6 networkx==3.1 neuralforecast==1.6.0 numba==0.57.1 numpy==1.23.5 optuna==3.2.0 optuna-dashboard==0.10.3 orjson==3.9.2 packaging==23.1 pandas==2.0.3 parso==0.8.3 patsy==0.5.3 pickleshare==0.7.5 Pillow==10.0.0 platformdirs==3.8.1 plotly==5.15.0 plotly-resampler==0.9.0 polars==0.18.7 prompt-toolkit==3.0.39 protobuf==4.23.4 psutil==5.9.5 pure-eval==0.2.2 pyarrow==6.0.1 Pygments==2.15.1 pyodbc==4.0.39 pyparsing==3.0.9 python-dateutil==2.8.2 pytorch-lightning==2.0.5 pytz==2023.3 pywin32==306 PyYAML==6.0 pyzmq==25.1.0 qpd==0.4.4 quadprog==0.1.11 ray==2.5.1 referencing==0.29.1 requests==2.31.0 retrying==1.3.4 rpds-py==0.8.10 scikit-learn==1.3.0 scipy==1.11.1 seaborn==0.12.2 six==1.16.0 SQLAlchemy==2.0.18 sqlglot==17.4.1 stack-data==0.6.2 statsforecast==1.5.0 statsmodels==0.14.0 stochastic==0.7.0 supersmoother==0.4 sympy==1.12 tenacity==8.2.2 tensorboardX==2.6.1 threadpoolctl==3.1.0 torch==2.0.1 torchmetrics==1.0.1 tornado==6.3.2 tqdm==4.65.0 trace-updater==0.0.9.1 traitlets==5.9.0 triad==0.9.1 tsdownsample==0.1.2 tsfeatures==0.4.5 typing_extensions==4.7.1 tzdata==2023.3 urllib3==2.0.3 wcwidth==0.2.6 Werkzeug==2.2.3 window-ops==0.0.14 xgboost==1.7.6 xlrd==2.0.1 yarl==1.9.2

Reproduction script

Y_hier_df, S_df, tags = aggregate(df=df_aggregated_all_by_channel, spec=[['top_level', 'unique_id']])
Y_hier_df = Y_hier_df.reset_index()
Y_test_df = Y_hier_df.groupby('unique_id').tail(48)
Y_train_df = Y_hier_df.drop(Y_test_df.index)
Y_test_df = Y_test_df.set_index('unique_id')
Y_train_df.set_index('unique_id')
models_segment = [
    AutoARIMA(season_length=12, nmodels=90),
    AutoETS(),
    MSTL(season_length=12,  trend_forecaster=AutoARIMA(), alias='MSTL-ARIMA'),
    MSTL(season_length=12),
    SeasonalNaive(season_length=12),
    AutoTheta(season_length=12), 
    AutoCES(season_length=12),
    SeasonalWindowAverage(window_size=2, season_length=12, alias='SeasWA212'),
    SeasonalWindowAverage(window_size=1, season_length=12, alias='SeasWA112'),
    SeasonalWindowAverage(window_size=4, season_length=12, alias='SeasWA412'),
    RandomWalkWithDrift()
]
hier_sf = StatsForecast(
    df=Y_train_df, 
    models=models_segment,
    freq='M', 
    n_jobs=-1,
    fallback_model = SeasonalNaive(season_length=12),
    verbose=True
)

horizon = 48
#level = [95]

Y_hat_df = hier_sf.forecast(df=Y_train_df, h=horizon, fitted=True)
Y_fitted_df =  hier_sf.forecast_fitted_values()
recon_methods = [BottomUp(), MinTrace(method='mint_shrink'),
                MinTrace(method='ols')], # OptimalCombination(
                    #method='wls_struct', nonnegative=True),

                #ERM(method='reg_bu')]
hrec = HierarchicalReconciliation(reconcilers=recon_methods)
Y_rec_df = hrec.reconcile(Y_hat_df=Y_hat_df, Y_df=Y_train_df, 
                          S=S_df, tags=tags)

Issue Severity

High: It blocks me from completing my task.

jmoralez commented 1 year ago

Hey @edgBR, thanks for the detailed example. I believe the issue is in your definition of the methods:

recon_methods = [BottomUp(), MinTrace(method='mint_shrink'),
                MinTrace(method='ols')], # OptimalCombination(
                    #method='wls_struct', nonnegative=True),

                #ERM(method='reg_bu')]

As you may notice there's a trailing comma, so you're defining recon_methods as a one element tuple where its only element is a list. Deleting that trailing comma should fix the issue. Please let us know if you run into other problems.

github-actions[bot] commented 1 year ago

This issue has been automatically closed because it has been awaiting a response for too long. When you have time to to work with the maintainers to resolve this issue, please post a new comment and it will be re-opened. If the issue has been locked for editing by the time you return to it, please open a new issue and reference this one.