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

Limited Holiday Calendar Functionality in autots FBProphet for Time Series Prediction #197

Open
vamsiMaple opened this issue Sep 4, 2023 · 3 comments

Comments

@vamsiMaple
Copy link

Hello.
I spent some time with autots ,FBProphet for my time series prediction task. It seems it is only take "name of the country" to include holiday calender , it does not consider holiday value , and also doesn't take custom-made holiday calender dataframe . I am not sure it is possible send holiday calender dataframe with holiday value , but I am curious about it.

Thanks in advance.

@winedarksea
Copy link
Owner

There are two ways of using holidays with Prophet in AutoTS:

  • holiday country
  • the 'holiday detector' params where it will automatically detect and pass in holidays

There is a third option that might work for you as well: using the future_regressor to pass in the holidays. It will be a multiple column dataframe, each column being a holiday (say, New Year's Day) and then a 0 or 1 value for whether that holiday occurs for that day. For training future_regressor, pass for all dates of training, and for future, pass for all dates for the prediction period.
This will be nearly identical to how Prophet internally utilizes a holiday calendar, and so should match your needs.

@vamsiMaple
Copy link
Author

@winedarksea

While creating an Autots class object there is no way to pass holiday param that is inturn passed to FBProphet class. If I am trying to pass holiday param into the autots class this is the error I am facing as there is no holiday param in the Autots class

model = AutoTS(
forecast_length=3,
frequency='D',
ensemble=None,
model_list=['FBProphet'],
no_negatives=True,
holiday=True
)
TypeError: AutoTS.init() got an unexpected keyword argument 'holiday'

@winedarksea
Copy link
Owner

winedarksea commented Sep 4, 2023

the AutoTS() class is only meant for doing an automatic parameter search. It would be impossible to intelligently handle custom inputs for all the dozens of models here. model_forecast is the tool for just running a single model with your own parameters.
You can pass a future_regressor as I mentioned to either AutoTS or model_forecast. This is really the proper way to handle this situation and should not be ignored. Below should give you an example of what these future regressors can look like for holidays.

import pandas as pd
from autots import load_daily, model_forecast, create_regressor
df = load_daily(long=False)  # long or non-numeric data won't work with this function
forecast_length = 28

holiday_detector_params = {
    "threshold": 0.9, "splash_threshold": None, "use_dayofmonth_holidays": True, "use_wkdom_holidays": False, "use_wkdeom_holidays": False, "use_lunar_holidays": False, "use_lunar_weekday": False, "use_islamic_holidays": False, "use_hebrew_holidays": False, "anomaly_detector_params": {
    "method": "nonparametric", "transform_dict": {"fillna": "pad", "transformations": {"0": "RegressionFilter", "1": "Log"}, "transformation_params": {"0": {"sigma": 2, "rolling_window": 90, "run_order": "trend_first",
    "regression_params": {"regression_model": {"model": "DecisionTree", "model_params": {"max_depth": 3, "min_samples_split": 1.0}}, "datepart_method": "expanded", "polynomial_degree": None, "transform_dict": None, "holiday_countries_used": False}, "holiday_params": None}, "1": {}}},
    "forecast_params": None, "method_params": {"p": None, "z_init": 2.0, "z_limit": 10, "z_step": 0.25, "inverse": False, "max_contamination": 0.25, "mean_weight": 25, "sd_weight": 25, "anomaly_count_weight": 1.0}}}

# future regressor, you can emulate this with your own data for holidays instead of the auto ones here.
regr_train, regr_fcst = create_regressor(
    df,
    forecast_length=forecast_length,
    frequency="infer",
    drop_most_recent=0,
    scale=True,
    summarize="mean",
    backfill="bfill",
    fill_na="spline",
    holiday_countries={"US": None},  # requires holidays package
    encode_holiday_type=True,
    datepart_method=None,
    holiday_detector_params=holiday_detector_params,
)
regr_train  # passed to train
regr_fcst  # passed to predict

But since you are insistent, here is a way to pass in holidays just as the Prophet package can handle.
https://facebook.github.io/prophet/docs/seasonality,_holiday_effects,_and_regressors.html
You also need to add a 'series' column to the holidays df here to handle the multivariate expectations of AutoTS

this builds off run of previous code

# fake dates, modified from prophet tutorial to handle the dates of the samples
playoffs = pd.DataFrame({
  'holiday': 'playoff',
  'ds': pd.to_datetime(['2017-01-13', '2019-01-03', '2010-01-16',
                        '2020-01-24', '2021-02-07', '2022-01-08',
                        '2023-01-12', '2024-01-12', '2025-01-19']),
  'lower_window': 0,
  'upper_window': 1,
})
superbowls = pd.DataFrame({
  'holiday': 'superbowl',
  'ds': pd.to_datetime(['2020-02-07', '2021-02-02', '2022-02-07']),
  'lower_window': 0,
  'upper_window': 1,
})
holidays = pd.concat((playoffs, superbowls))
# as written in AutoTS it expects a long df of holidays with a 'series' column dennoting what series to use for thos holidays, this uses for just last series
holidays['series'] = df.iloc[:, -1]
df_forecast = model_forecast(
    model_name="FBProphet",
    model_param_dict={
        'holiday': holidays,
         'regression_type': None,
         'changepoint_prior_scale': 50,
         'seasonality_prior_scale': 1.0,
         'holidays_prior_scale': 10.0,
         'seasonality_mode': 'multiplicative',
         'changepoint_range': 0.9,
         'growth': 'linear',
         'n_changepoints': 25
     },
    model_transform_dict={
        'fillna': 'akima',
        'transformations': {},
        'transformation_params': {},
    },
    df_train=df,
    forecast_length=forecast_length,
    frequency='infer',
    prediction_interval=0.9,
    no_negatives=False,
    # future_regressor_train=regr_train,
    # future_regressor_forecast=regr_fcst,
    random_seed=321,
    verbose=-1,
    n_jobs="auto",
)
df_forecast.forecast.head(5)
df_forecast.plot_grid(df)

and here is an example of automatic holiday detection, using holiday detector params defined in the first example above:

params = {"holiday": holiday_detector_params,
          "regression_type": None, "growth": "linear", "n_changepoints": 30, "changepoint_prior_scale": 0.01, "seasonality_mode": "additive", "changepoint_range": 0.8, "seasonality_prior_scale": 15, "holidays_prior_scale": 10.0}
df_forecast = model_forecast(
    model_name="FBProphet",
    model_param_dict=params,
    model_transform_dict={
        'fillna': 'akima',
        'transformations': {},
        'transformation_params': {},
    },
    df_train=df,
    forecast_length=12,
    frequency='infer',
    prediction_interval=0.9,
    no_negatives=False,
    # future_regressor_train=regr_train,
    # future_regressor_forecast=regr_fcst,
    random_seed=321,
    verbose=-1,
    n_jobs="auto",
)
df_forecast.plot_grid(df)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants