def seasonal_error( self, time_series: Union[pd.Series, pd.DataFrame], forecast: Forecast ) -> float: r""" .. math:: seasonal_error = mean(|Y[t] - Y[t-m]|) where m is the seasonal frequency https://www.m4.unic.ac.cy/wp-content/uploads/2018/03/M4-Competitors-Guide.pdf """ # Remove the prediction range # If the prediction range is not in the end of the time series, # everything after the prediction range is truncated forecast_date = pd.Timestamp(forecast.start_date, freq=forecast.freq) date_before_forecast = forecast_date - 1 * forecast_date.freq ts = time_series[:date_before_forecast] # Check if the length of the time series is larger than the seasonal frequency seasonality = ( self.seasonality if self.seasonality else get_seasonality(forecast.freq) ) if seasonality < len(ts): forecast_freq = seasonality else: # edge case: the seasonal freq is larger than the length of ts # revert to freq=1 # logging.info('The seasonal frequency is larger than the length of the time series. Reverting to freq=1.') forecast_freq = 1 y_t = np.ma.masked_invalid(ts.values[:-forecast_freq]) y_tm = np.ma.masked_invalid(ts.values[forecast_freq:]) seasonal_mae = np.mean(abs(y_t - y_tm)) return seasonal_mae if seasonal_mae is not np.ma.masked else np.nan
def seasonal_error(self, past_data: np.ndarray, forecast: Forecast) -> float: r""" .. math:: seasonal_error = mean(|Y[t] - Y[t-m]|) where m is the seasonal frequency https://www.m4.unic.ac.cy/wp-content/uploads/2018/03/M4-Competitors-Guide.pdf """ # Check if the length of the time series is larger than the seasonal frequency seasonality = ( self.seasonality if self.seasonality else get_seasonality(forecast.freq) ) if seasonality < len(past_data): forecast_freq = seasonality else: # edge case: the seasonal freq is larger than the length of ts # revert to freq=1 # logging.info('The seasonal frequency is larger than the length of the time series. Reverting to freq=1.') forecast_freq = 1 y_t = past_data[:-forecast_freq] y_tm = past_data[forecast_freq:] seasonal_mae = np.mean(abs(y_t - y_tm)) return seasonal_mae if seasonal_mae is not np.ma.masked else np.nan
def __init__(self, loss_function: str, freq: str, *args, **kwargs) -> None: super(NBEATSTrainingNetwork, self).__init__(*args, **kwargs) self.loss_function = loss_function self.freq = freq self.periodicity = get_seasonality(self.freq) if self.loss_function == "MASE": assert self.periodicity < self.context_length + self.prediction_length, ( "If the 'periodicity' of your data is less than 'context_length' + 'prediction_length' " "the seasonal_error cannot be calculated and thus 'MASE' cannot be used for optimization." )
def test_get_seasonality(freq, expected_seasonality): assert get_seasonality(freq) == expected_seasonality