def __init__( self, freq: str, prediction_length: int, method_name: str = "ets", period: int = None, trunc_length: Optional[int] = None, params: Optional[Dict] = None, ) -> None: super().__init__(freq=freq, prediction_length=prediction_length) try: import rpy2.robjects.packages as rpackages from rpy2 import rinterface, robjects from rpy2.rinterface import RRuntimeError except ImportError as e: raise ImportError(str(e) + USAGE_MESSAGE) from e self._robjects = robjects self._rinterface = rinterface self._rinterface.initr() self._rpackages = rpackages this_dir = os.path.dirname(os.path.realpath(__file__)) this_dir = this_dir.replace("\\", "/") # for windows r_files = [ n[:-2] for n in os.listdir(f"{this_dir}/R/") if n[-2:] == ".R" ] for n in r_files: try: path = Path(this_dir, "R", f"{n}.R") robjects.r(f'source("{path}")'.replace("\\", "\\\\")) except RRuntimeError as er: raise RRuntimeError(str(er) + USAGE_MESSAGE) from er supported_methods = ["ets", "arima", "tbats", "croston", "mlp"] assert ( method_name in supported_methods ), f"method {method_name} is not supported please use one of {supported_methods}" self.method_name = method_name self._stats_pkg = rpackages.importr("stats") self._r_method = robjects.r[method_name] self.prediction_length = prediction_length self.freq = freq self.period = period if period is not None else get_seasonality(freq) self.trunc_length = trunc_length self.params = { "prediction_length": self.prediction_length, "output_types": ["samples"], "frequency": self.period, } if params is not None: self.params.update(params)
def naive_2( past_ts_data: np.ndarray, prediction_length: int, freq: Optional[str] = None, season_length: Optional[int] = None, ) -> np.ndarray: """ Make seasonality adjusted time series prediction. If specified, `season_length` takes precedence. As described here: https://www.m4.unic.ac.cy/wp-content/uploads/2018/03/M4-Competitors-Guide.pdf Code based on: https://github.com/Mcompetitions/M4-methods/blob/master/Benchmarks%20and%20Evaluation.R """ assert freq is not None or season_length is not None, ( "Either the frequency or season length of the time series " "has to be specified. " ) season_length = ( season_length if season_length is not None else get_seasonality(freq) ) has_seasonality = False if season_length > 1: has_seasonality = seasonality_test(past_ts_data, season_length) # it has seasonality, then calculate the multiplicative seasonal component if has_seasonality: # TODO: think about maybe only using past_ts_data[- max # (5*season_length, 2*prediction_length):] for speedup seasonal_decomposition = sm.tsa.seasonal_decompose( x=past_ts_data, period=season_length, model="multiplicative" ).seasonal seasonality_normed_context = past_ts_data / seasonal_decomposition last_period = seasonal_decomposition[-season_length:] num_required_periods = (prediction_length // len(last_period)) + 1 multiplicative_seasonal_component = np.tile( last_period, num_required_periods )[:prediction_length] else: seasonality_normed_context = past_ts_data multiplicative_seasonal_component = np.ones( prediction_length ) # i.e. no seasonality component # calculate naive forecast: (last value prediction_length times) naive_forecast = ( np.ones(prediction_length) * seasonality_normed_context[-1] ) forecast = np.mean(naive_forecast) * multiplicative_seasonal_component return forecast
def __init__( self, freq: str, prediction_length: int, method_name: str = "ets", period: int = None, trunc_length: Optional[int] = None, params: Optional[Dict] = None, ) -> None: super().__init__(freq=freq, prediction_length=prediction_length) if not R_IS_INSTALLED: raise ImportError("R is not Installed! \n " + USAGE_MESSAGE) if not RPY2_IS_INSTALLED: raise ImportError(rpy2_error_message + USAGE_MESSAGE) self._robjects = robjects self._rinterface = rinterface self._rinterface.initr() self._rpackages = rpackages this_dir = os.path.dirname(os.path.realpath(__file__)) this_dir = this_dir.replace("\\", "/") # for windows r_files = [ n[:-2] for n in os.listdir(f"{this_dir}/R/") if n[-2:] == ".R" ] for n in r_files: try: path = Path(this_dir, "R", f"{n}.R") robjects.r(f'source("{path}")'.replace("\\", "\\\\")) except RRuntimeError as er: raise RRuntimeError(str(er) + USAGE_MESSAGE) from er assert ( method_name in SUPPORTED_METHODS ), f"method {method_name} is not supported please use one of {SUPPORTED_METHODS}" self.method_name = method_name self._stats_pkg = rpackages.importr("stats") self._r_method = robjects.r[method_name] self.prediction_length = prediction_length self.freq = freq self.period = period if period is not None else get_seasonality(freq) self.trunc_length = trunc_length self.params = { "prediction_length": self.prediction_length, "output_types": ["samples"], "frequency": self.period, } if params is not None: self.params.update(params)
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 __init__(self, loss_function: str, freq: str, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.loss_function = loss_function self.freq = freq # Covert frequency string like "2H" to whats called the periodicity m. # E.g. 12 in case of "2H" because of 12 times two hours in a day. 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 automl_params_overwrite(params): """Overwrite some training options based on the selected automl mode """ params_copy = params.copy() if params_copy["forecasting_style"].startswith("auto"): params_copy["season_length"] = get_seasonality(params_copy["frequency"], DEFAULT_SEASONALITIES) params_copy["batch_size"] = 128 if params_copy["use_gpu"] else 32 if params_copy["forecasting_style"] == "auto": params_copy["epoch"] = 10 params_copy["num_batches_per_epoch"] = 50 elif params_copy["forecasting_style"] == "auto_performance": params_copy["context_length"] = params_copy["prediction_length"] params_copy["epoch"] = 30 if params_copy["is_training_multivariate"] else 10 params_copy["num_batches_per_epoch"] = -1 return params_copy
def __init__( self, freq: str, prediction_length: int, season_length: Optional[int] = None, ) -> None: super().__init__(freq=freq, prediction_length=prediction_length) assert ( season_length is None or season_length > 0), "The value of `season_length` should be > 0" self.freq = freq self.prediction_length = prediction_length self.season_length = (season_length if season_length is not None else get_seasonality(freq))
def seasonality(self) -> int: """ Returns the seasonality of the forecasts (i.e. how many steps to go back to arrive at the value of the previous period). """ return get_seasonality(self.freq.freqstr) # type: ignore
def __init__( self, freq: str, prediction_length: int, trainer: Trainer = Trainer( learning_rate=0.01, epochs=200, num_batches_per_epoch=50, hybridize=False, ), cardinality: List[int] = [1], seasonality: Optional[int] = None, embedding_dimension: int = 5, num_bins: int = 1024, hybridize_prediction_net: bool = False, n_residue=24, n_skip=32, dilation_depth: Optional[int] = None, n_stacks: int = 1, train_window_length: Optional[int] = None, temperature: float = 1.0, act_type: str = "elu", num_parallel_samples: int = 200, ) -> None: """ Model with Wavenet architecture and quantized target. :param freq: :param prediction_length: :param trainer: :param num_eval_samples: :param cardinality: :param embedding_dimension: :param num_bins: Number of bins used for quantization of signal :param hybridize_prediction_net: :param n_residue: Number of residual channels in wavenet architecture :param n_skip: Number of skip channels in wavenet architecture :param dilation_depth: number of dilation layers in wavenet architecture. If set to None, dialation_depth is set such that the receptive length is at least as long as 2 * seasonality for the frequency and at least 2 * prediction_length. :param n_stacks: Number of dilation stacks in wavenet architecture :param train_window_length: Length of windows used for training. This should be longer than prediction length. Larger values result in more efficient reuse of computations for convolutions. :param temperature: Temparature used for sampling from softmax distribution. For temperature = 1.0 sampling is according to estimated probability. :param act_type: Activation type used after before output layer. Can be any of 'elu', 'relu', 'sigmoid', 'tanh', 'softrelu', 'softsign' """ super().__init__(trainer=trainer) self.freq = freq self.prediction_length = prediction_length self.cardinality = cardinality self.embedding_dimension = embedding_dimension self.num_bins = num_bins self.hybridize_prediction_net = hybridize_prediction_net self.n_residue = n_residue self.n_skip = n_skip self.n_stacks = n_stacks self.train_window_length = (train_window_length if train_window_length is not None else prediction_length) self.temperature = temperature self.act_type = act_type self.num_parallel_samples = num_parallel_samples seasonality = (get_seasonality( self.freq, { "H": 7 * 24, "D": 7, "W": 52, "M": 12, "B": 7 * 5, "min": 24 * 60, }, ) if seasonality is None else seasonality) goal_receptive_length = max(2 * seasonality, 2 * self.prediction_length) if dilation_depth is None: d = 1 while (WaveNet.get_receptive_field(dilation_depth=d, n_stacks=n_stacks) < goal_receptive_length): d += 1 self.dilation_depth = d else: self.dilation_depth = dilation_depth self.context_length = WaveNet.get_receptive_field( dilation_depth=self.dilation_depth, n_stacks=n_stacks) self.logger = logging.getLogger(__name__) self.logger.info( f"Using dilation depth {self.dilation_depth} and receptive field length {self.context_length}" )
def __init__( self, freq: str, prediction_length: int, trainer: Trainer = Trainer( learning_rate=0.01, epochs=200, num_batches_per_epoch=50, hybridize=False, ), cardinality: List[int] = [1], seasonality: Optional[int] = None, embedding_dimension: int = 5, num_bins: int = 1024, hybridize_prediction_net: bool = False, n_residue=24, n_skip=32, dilation_depth: Optional[int] = None, n_stacks: int = 1, train_window_length: Optional[int] = None, temperature: float = 1.0, act_type: str = "elu", num_parallel_samples: int = 200, train_sampler: Optional[InstanceSampler] = None, validation_sampler: Optional[InstanceSampler] = None, batch_size: int = 32, negative_data: bool = False, ) -> None: super().__init__(trainer=trainer, batch_size=batch_size) self.freq = freq self.prediction_length = prediction_length self.cardinality = cardinality self.embedding_dimension = embedding_dimension self.num_bins = num_bins self.hybridize_prediction_net = hybridize_prediction_net self.n_residue = n_residue self.n_skip = n_skip self.n_stacks = n_stacks self.train_window_length = ( train_window_length if train_window_length is not None else prediction_length ) self.temperature = temperature self.act_type = act_type self.num_parallel_samples = num_parallel_samples self.train_sampler = ( train_sampler if train_sampler is not None else ExpectedNumInstanceSampler( num_instances=1.0, min_future=self.train_window_length ) ) self.validation_sampler = ( validation_sampler if validation_sampler is not None else ValidationSplitSampler(min_future=self.train_window_length) ) self.negative_data = negative_data low = -10.0 if self.negative_data else 0 high = 10.0 bin_centers = np.linspace(low, high, self.num_bins) bin_edges = np.concatenate( [[-1e20], (bin_centers[1:] + bin_centers[:-1]) / 2.0, [1e20]] ) self.bin_centers = bin_centers.tolist() self.bin_edges = bin_edges.tolist() seasonality = ( get_seasonality( self.freq, { "H": 7 * 24, "D": 7, "W": 52, "M": 12, "B": 7 * 5, "min": 24 * 60, }, ) if seasonality is None else seasonality ) goal_receptive_length = max( 2 * seasonality, 2 * self.prediction_length ) if dilation_depth is None: d = 1 while ( WaveNet.get_receptive_field( dilation_depth=d, n_stacks=n_stacks ) < goal_receptive_length ): d += 1 self.dilation_depth = d else: self.dilation_depth = dilation_depth self.context_length = WaveNet.get_receptive_field( dilation_depth=self.dilation_depth, n_stacks=n_stacks ) self.logger = logging.getLogger(__name__) self.logger.info( f"Using dilation depth {self.dilation_depth} and receptive field length {self.context_length}" )
def test_get_seasonality(freq, expected_seasonality): assert get_seasonality(freq) == expected_seasonality