Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trend parameter not consistent between Holt-Winters and ETS models #8100

Closed
enricogandini opened this issue Feb 6, 2022 · 3 comments
Closed

Comments

@enricogandini
Copy link

enricogandini commented Feb 6, 2022

The trend attribute of an HoltWintersResults stores a time series with the trend component of the model.
On the other end, the trend attribute of an ETSResults stores the value of the trend option passed during the creation
of the ETSModel.

The behaviour is not consistent with other attributes of HoltWintersResults and ETSResults, such as the season, level,
and resid attributes, that store the seasonal and level components, and the model residuals, respectively.
The ETSResults should store the trend component in its trend attribute.

On the same note, I think that the params attribute of ETSResults instances is not correct. It should be a dictionary containing the values of the model parameters: this is the case for the HoltWintersResults instances.
For ETSResults instances, the params attribute stores a pd.Series, and I do not know what kind of information it contains!

Sample code

from datetime import datetime

import pandas as pd
import numpy as np

from statsmodels.tsa.holtwinters import ExponentialSmoothing
from statsmodels.tsa.exponential_smoothing.ets import ETSModel


# Generate data
n_samples = 200

np.random.seed(1)
y_seasonal = np.sin(np.linspace(0, 7*np.pi, n_samples))
y_resid = np.random.normal(loc=0, scale=0.1, size=n_samples)

y_train = y_seasonal + y_resid

start_day = datetime(2021, 1, 1)
index = pd.date_range(
    start=start_day,
    freq='1H',
    periods=n_samples,
)

y_train = pd.Series(data=y_train, index=index)

# Build models
kwargs = dict(seasonal='add', trend='add')

hw_model = ExponentialSmoothing(endog=y_train, **kwargs)
ets_model = ETSModel(endog=y_train, **kwargs)

hw_result = hw_model.fit()
ets_result = ets_model.fit()

# Inspect results

# The `level` attribute contains the
# time series of the level component.
assert pd.Series == type(hw_result.level)
assert pd.Series == type(ets_result.level)

# The `resid` attribute contains the
# residuals.
assert pd.Series == type(hw_result.resid)
assert pd.Series == type(ets_result.resid)

# The `season` attribute contains the
# time series of the seasonal component.
assert pd.Series == type(hw_result.season)
assert pd.Series == type(ets_result.season)

# The `trend` attribute contains the
# time series of the trend component of
# the HoltWintersResults,
# but it contains
# the input `trend` attribute given
# to the ETSModel instance for the ETSResults object.
assert pd.Series == type(hw_result.trend)
assert kwargs['trend'] == ets_result.trend

# The HoltWintersResults `params` attribute
# is a dictionary with the model parameters.
# The ETSResults object stores a pd.Series
# in the `params` attribute: what is it?
assert dict == type(hw_result.params)
assert pd.Series == type(ets_result.params)

Output of import statsmodels.api as sm; sm.show_versions()

INSTALLED VERSIONS
------------------
Python: 3.9.7.final.0
OS: Linux 4.15.0-167-generic #175-Ubuntu SMP Wed Jan 5 01:56:07 UTC 2022 x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8

statsmodels
===========

Installed: 0.13.0 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/statsmodels)

Required Dependencies
=====================

cython: Not installed
numpy: 1.21.2 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/numpy)
scipy: 1.7.3 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/scipy)
pandas: 1.3.5 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/pandas)
    dateutil: 2.8.2 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/dateutil)
patsy: 0.5.2 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/patsy)

Optional Dependencies
=====================

matplotlib: 3.5.0 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/matplotlib)
    backend: QtAgg 
cvxopt: Not installed
joblib: 1.1.0 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/joblib)

Developer Tools
================

IPython: 7.31.1 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/IPython)
    jinja2: 3.0.2 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/jinja2)
sphinx: Not installed
    pygments: 2.10.0 (/home/enrico/anaconda3/envs/datascience/lib/python3.9/site-packages/pygments)
pytest: Not installed
virtualenv: Not installed
@ChadFulton
Copy link
Member

The statsmodels.tsa.holtwinters module is an older version of exponential smoothing that doesn't always follow the modern patterns of Statsmodels, and there is no plan to make ETSModel consistent with results of statsmodels.tsa.holtwinters.

The behaviour is not consistent with other attributes of HoltWintersResults and ETSResults, such as the season, level,
and resid attributes, that store the seasonal and level components, and the model residuals, respectively.
The ETSResults should store the trend component in its trend attribute.

The ETSResults stores the estimated trend component as the slope attribute. This is because the attributes error, trend, and seasonal are reserved for the corresponding model arguments.

On the same note, I think that the params attribute of ETSResults instances is not correct. It should be a dictionary containing the values of the model parameters: this is the case for the HoltWintersResults instances.
For ETSResults instances, the params attribute stores a pd.Series, and I do not know what kind of information it contains!

For most Statsmodels models, the params attribute of a results object holds the estimated parameters of the model. If the input data series is Pandas (as it is in your example), then the params attribute is a Pandas series, otherwise it is a numpy array.

@ChadFulton
Copy link
Member

Closing as answered, but feel free to follow up if you have questions.

@enricogandini
Copy link
Author

Thank you for your answer @ChadFulton ! Everything is clear.

@bashtage bashtage added this to the 0.13.2 milestone Feb 8, 2022
@bashtage bashtage modified the milestones: 0.13.2, 0.14 Apr 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants