Nixtla/hierarchicalforecast

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

edgBR opened this issue · 2 comments

edgBR commented

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.

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.

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.