def fit(self, Z, X=None): """Fit to data. Parameters ---------- Z : pd.Series X : pd.DataFrame Returns ------- self : an instance of self """ self._is_fitted = False z = check_series(Z, enforce_univariate=True) self._set_y_index(z) sp = check_sp(self.sp) # apply seasonal decomposition self.seasonal_ = seasonal_decompose( z, model=self.model, period=sp, filt=None, two_sided=True, extrapolate_trend=0, ).seasonal.iloc[:sp] self._is_fitted = True return self
def _fit(self, y, X=None, fh=None): """Fit to training data. Parameters ---------- y : pd.Series Target time series to which to fit the forecaster. fh : int, list or np.array, optional (default=None) The forecasters horizon with the steps ahead to to predict. X : pd.DataFrame, optional (default=None) Exogenous variables are ignored Returns ------- self : returns an instance of self. """ sp = check_sp(self.sp) if sp > 1 and not self.deseasonalize: warn("`sp` is ignored when `deseasonalise`=False") if self.deseasonalize: self.deseasonalizer_ = Deseasonalizer(sp=self.sp, model="multiplicative") y = self.deseasonalizer_.fit_transform(y) self.initialization_method = "known" if self.initial_level else "estimated" # fit exponential smoothing forecaster # find theta lines: Theta lines are just SES + drift super(ThetaForecaster, self)._fit(y, fh=fh) self.initial_level_ = self._fitted_forecaster.params["smoothing_level"] # compute trend self.trend_ = self._compute_trend(y) return self
def __init__(self, sp=1, model="additive"): self.sp = check_sp(sp) allowed_models = ("additive", "multiplicative") if model not in allowed_models: raise ValueError(f"`model` must be one of {allowed_models}, " f"but found: {model}") self.model = model self._y_index = None self.seasonal_ = None super(Deseasonalizer, self).__init__()
def _instantiate_model(self): n_jobs = check_n_jobs(self.n_jobs) sp = check_sp(self.sp, enforce_list=True) return self._ModelClass( use_box_cox=self.use_box_cox, box_cox_bounds=self.box_cox_bounds, use_trend=self.use_trend, use_damped_trend=self.use_damped_trend, seasonal_periods=sp, use_arma_errors=self.use_arma_errors, show_warnings=self.show_warnings, n_jobs=n_jobs, multiprocessing_start_method=self.multiprocessing_start_method, context=self.context, )
def autocorrelation_seasonality_test(y, sp): """Seasonality test used in M4 competition Parameters ---------- sp : int Seasonal periodicity Returns ------- is_seasonal : bool Test result References ---------- ..[1] https://github.com/Mcompetitions/M4-methods/blob/master /Benchmarks%20and%20Evaluation.R """ y = check_y(y) sp = check_sp(sp) y = np.asarray(y) n_timepoints = len(y) if sp == 1: return False if n_timepoints < 3 * sp: warn( "Did not perform seasonality test, as `y`` is too short for the " "given `sp`, returned: False" ) return False else: coefs = acf(y, nlags=sp, fft=False) # acf coefficients coef = coefs[sp] # coefficient to check tcrit = 1.645 # 90% confidence level limits = ( tcrit / np.sqrt(n_timepoints) * np.sqrt(np.cumsum(np.append(1, 2 * coefs[1:] ** 2))) ) limit = limits[sp - 1] # zero-based indexing return np.abs(coef) > limit
def fit(self, Z, X=None): """Fit to data. Parameters ---------- y_train : pd.Series Returns ------- self : an instance of self """ z = check_series(Z, enforce_univariate=True) self._set_y_index(z) sp = check_sp(self.sp) # set default condition if self.seasonality_test is None: self.seasonality_test_ = autocorrelation_seasonality_test else: self.seasonality_test_ = self.seasonality_test # check if data meets condition self.is_seasonal_ = self._check_condition(z) if self.is_seasonal_: # if condition is met, apply de-seasonalisation self.seasonal_ = seasonal_decompose( z, model=self.model, period=sp, filt=None, two_sided=True, extrapolate_trend=0, ).seasonal.iloc[:sp] else: # otherwise, set idempotent seasonal components self.seasonal_ = ( np.zeros(self.sp) if self.model == "additive" else np.ones(self.sp) ) self._is_fitted = True return self
def fit(self, Z, X=None): """Fit to data. Parameters ---------- Z : pd.Series X : pd.DataFrame Returns ------- self : an instance of self """ self._is_fitted = False z = check_series(Z, enforce_univariate=True) self._set_y_len(z) self._set_y_index(z) sp = check_sp(self.sp) if sp > 1: # apply seasonal decomposition _seasonalizer = _STL( z.values, period=sp, seasonal=self.seasonal, trend=self.trend, low_pass=self.low_pass, seasonal_deg=self.seasonal_deg, trend_deg=self.trend_deg, low_pass_deg=self.low_pass_deg, robust=self.robust, seasonal_jump=self.seasonal_jump, trend_jump=self.trend_jump, low_pass_jump=self.low_pass_jump, ).fit() self.stl_model = _seasonalizer self.seasonal_ = self.stl_model.seasonal else: self.stl_model = None self.seasonal_ = np.zeros_like(z.values) self.seasonal_ = pd.Series(self.seasonal_, index=Z.index) self._is_fitted = True return self
def fit(self, y_train, **fit_params): """Fit to data. Parameters ---------- y_train : pd.Series fit_params : dict Returns ------- self : an instance of self """ y_train = check_y(y_train) self._set_oh_index(y_train) sp = check_sp(self.sp) # set default condition if self.seasonality_test is None: self.seasonality_test_ = autocorrelation_seasonality_test else: self.seasonality_test_ = self.seasonality_test # check if data meets condition self.is_seasonal_ = self._check_condition(y_train) if self.is_seasonal_: # if condition is met, apply de-seasonalisation self.seasonal_ = seasonal_decompose( y_train, model=self.model, period=sp, filt=None, two_sided=True, extrapolate_trend=0).seasonal.iloc[:sp] else: # otherwise, set idempotent seasonal components self.seasonal_ = np.zeros( self.sp) if self.model == "additive" else np.ones(self.sp) self._is_fitted = True return self
def fit(self, Z, X=None): """Fit to data. Parameters ---------- Z : pd.Series X : pd.DataFrame Returns ------- self : an instance of self """ self._is_fitted = False z = check_series(Z, enforce_univariate=True) self._Z_index = Z.index sp = check_sp(self.sp) # The statsmodels.tsa.seasonal.STL can only deal with sp >= 2 if sp < 2: raise ValueError("sp must be positive integer >= 2") self._stl = _STL( z.values, period=sp, seasonal=self.seasonal, trend=self.trend, low_pass=self.low_pass, seasonal_deg=self.seasonal_deg, trend_deg=self.trend_deg, low_pass_deg=self.low_pass_deg, robust=self.robust, seasonal_jump=self.seasonal_jump, trend_jump=self.trend_jump, low_pass_jump=self.low_pass_jump, ).fit() self.seasonal_ = pd.Series(self._stl.seasonal, index=Z.index) self.resid_ = pd.Series(self._stl.resid, index=Z.index) self.trend_ = pd.Series(self._stl.trend, index=Z.index) self._is_fitted = True return self
def fit(self, y, **fit_params): """Fit to data. Parameters ---------- y_train : pd.Series fit_params : dict Returns ------- self : an instance of self """ y = check_y(y) self._set_oh_index(y) sp = check_sp(self.sp) self.seasonal_ = seasonal_decompose(y, model=self.model, period=sp, filt=None, two_sided=True, extrapolate_trend=0).seasonal.iloc[ :sp] self._is_fitted = True return self
def _fit(self, y, X=None, fh=None): """Fit to training data. Parameters ---------- y : pd.Series Target time series to which to fit the forecaster. fh : int, list or np.array, default=None The forecasters horizon with the steps ahead to to predict. X : pd.DataFrame, default=None Exogenous variables are ignored. Returns ------- self : returns an instance of self. """ # X_train is ignored n_timepoints = y.shape[0] if self.strategy in ("last", "mean"): # check window length is greater than sp for seasonal mean or seasonal last if self.window_length is not None and self.sp != 1: if self.window_length < self.sp: raise ValueError(f"The `window_length`: " f"{self.window_length} is smaller than " f"`sp`: {self.sp}.") self.window_length_ = check_window_length(self.window_length, n_timepoints) self.sp_ = check_sp(self.sp) # if not given, set default window length if self.window_length is None: self.window_length_ = len(y) elif self.strategy == "drift": if self.sp != 1: warn( "For the `drift` strategy, the `sp` value will be ignored." ) # window length we need for forecasts is just the # length of seasonal periodicity self.window_length_ = check_window_length(self.window_length, n_timepoints) if self.window_length is None: self.window_length_ = len(y) if self.window_length == 1: raise ValueError(f"For the `drift` strategy, " f"the `window_length`: {self.window_length} " f"value must be greater than one.") else: allowed_strategies = ("last", "mean", "drift") raise ValueError(f"Unknown strategy: {self.strategy}. Expected " f"one of: {allowed_strategies}.") # check window length if self.window_length_ > len(self._y): param = ("sp" if self.strategy == "last" and self.sp != 1 else "window_length_") raise ValueError( f"The {param}: {self.window_length_} is larger than " f"the training series.") return self
def fit(self, y_train, fh=None, X_train=None): """Fit to training data. Parameters ---------- y_train : pd.Series Target time series to which to fit the forecaster. fh : int, list or np.array, optional (default=None) The forecasters horizon with the steps ahead to to predict. X_train : pd.DataFrame, optional (default=None) Exogenous variables are ignored Returns ------- self : returns an instance of self. """ # X_train is ignored self._set_y_X(y_train, X_train) self._set_fh(fh) if self.strategy == "last": if self.sp == 1: if self.window_length is not None: warn("For the `last` strategy, " "the `window_length` value will be ignored if `sp` " "== 1.") self.window_length_ = 1 else: self.sp_ = check_sp(self.sp) # window length we need for forecasts is just the # length of seasonal periodicity self.window_length_ = self.sp_ elif self.strategy == "mean": # check window length is greater than sp for seasonal mean if self.window_length is not None and self.sp != 1: if self.window_length < self.sp: raise ValueError(f"The `window_length`: " f"{self.window_length} is smaller than " f"`sp`: {self.sp}.") self.window_length_ = check_window_length(self.window_length) self.sp_ = check_sp(self.sp) # if not given, set default window length for the mean strategy if self.window_length is None: self.window_length_ = len(y_train) elif self.strategy == "drift": if self.sp != 1: warn("For the `drift` strategy, " "the `sp` value will be ignored.") # window length we need for forecasts is just the # length of seasonal periodicity self.window_length_ = check_window_length(self.window_length) if self.window_length is None: self.window_length_ = len(y_train) if self.window_length == 1: raise ValueError(f"For the `drift` strategy, " f"the `window_length`: {self.window_length} " f"value must be greater than one.") else: allowed_strategies = ("last", "mean", "drift") raise ValueError(f"Unknown strategy: {self.strategy}. Expected " f"one of: {allowed_strategies}.") # check window length if self.window_length_ > len(self._y): param = ("sp" if self.strategy == "last" and self.sp != 1 else "window_length_") raise ValueError( f"The {param}: {self.window_length_} is larger than " f"the training series.") self._is_fitted = True return self