Search code examples
pythontime-seriesforecastingu8darts

Why do I get "AttributeError: 'str' object has no attribute 'value'" when trying to use darts ExponentialSmoothing with a "trend" argument?


Here is the code I have:

# Define models
models = {
   'ExponentialSmoothing': [
       ExponentialSmoothing(trend='add', seasonal='add', seasonal_periods=52),
       ExponentialSmoothing(trend='add', seasonal='mul', seasonal_periods=12)
   ],
   'SeasonalARIMA': [
        ARIMA(p=1, d=1, q=1, seasonal_order=(1, 1, 1, 52)),
        ARIMA(p=1, d=1, q=1, seasonal_order=(1, 1, 1, 12))
   ],
   'FFT': [
       FFT(nr_freqs_to_keep=10),
       FFT(nr_freqs_to_keep=5)
   ]
}

def evaluate_models(train, test, model_list):
   performance = []
   for model in model_list:
       start_time = time.time()
       model.fit(train)
       forecast = model.predict(len(test))
       end_time = time.time()
       # Ensure forecast and test are TimeSeries objects
       if not isinstance(forecast, TimeSeries):
           raise ValueError(f"Forecast is not a TimeSeries object: {forecast}")
       if not isinstance(test, TimeSeries):
           raise ValueError(f"Test is not a TimeSeries object: {test}")
       performance.append({
           'Model': type(model).__name__,
           'MAE': mae(test, forecast),
           'MSE': mse(test, forecast),
           'MASE': mase(test, forecast, train),
           'Forecast Bias': (forecast.mean() - test.mean()).values()[0],
           'Time Elapsed (s)': end_time - start_time
       })
   return pd.DataFrame(performance)

# Evaluate weekly data
performance_weekly = {}
for name, model_list in models.items():
   performance_weekly[name] = evaluate_models(train_weekly, test_weekly, model_list)

# Evaluate monthly data
performance_monthly = {}
for name, model_list in models.items():
   performance_monthly[name] = evaluate_models(train_monthly, test_monthly, model_list)

# Display results
display(pd.concat(performance_weekly.values()))
display(pd.concat(performance_monthly.values()))

I get an error like this:

 AttributeError: 'str' object has no attribute 'value'
File <command-3594900232608958>, line 42
     40 performance_weekly = {}
     41 for name, model_list in models.items():
---> 42    performance_weekly[name] = evaluate_models(train_weekly, test_weekly, model_list)
     44 # Evaluate monthly data
     45 performance_monthly = {}
File /local_disk0/.ephemeral_nfs/cluster_libraries/python/lib/python3.11/site-packages/darts/models/forecasting/exponential_smoothing.py:123, in ExponentialSmoothing.fit(self, series)
    118 if self.seasonal_periods is None and series.has_range_index:
    119     seasonal_periods_param = 12
    121 hw_model = hw.ExponentialSmoothing(
    122     series.values(copy=False),
--> 123     trend=self.trend if self.trend is None else self.trend.value,
    124     damped_trend=self.damped,
    125     seasonal=self.seasonal if self.seasonal is None else self.seasonal.value,
    126     seasonal_periods=seasonal_periods_param,
    127     freq=series.freq if series.has_datetime_index else None,

The context:

I do timeseries forecasting.

Is this because of the methodology I have in splitting the training and test dataset?


Solution

  • Is this because of the methodology I have in splitting the training and test dataset?

    No, it is because in your code you have

    ExponentialSmoothing(trend='add', ...)
    

    which means that inside ExponentialSmoothing, when trend=self.trend if self.trend is None else self.trend.value is evaluated, self.trend is a string and self.trend.value is not valid.

    You need to read the (appropriate) documentation to find out what you really should pass as trend to ExponentialSmoothing:

    It seems you are using ExponentialSmoothing from darts (evidenced by the file path .../site-packages/darts/models/forecasting/exponential_smoothing.py shown in the error traceback) and you confused it with ExponentialSmothing from statsmodels.

    While in statsmodels, there is a trend argument which accepts the string 'add' as parameter, in darts, the trend argument is expected to be a ModelMode. It looks like ModelMode.ADDITIVE is what you intended.