Пример #1
0
    def fit(self, series: TimeSeries):
        super().fit(series)
        series._assert_univariate()
        series = self.training_series

        if self.version == "tsb":
            self.forecast_val = self.method(
                series.values(copy=False),
                h=1,
                future_xreg=None,
                alpha_d=self.alpha_d,
                alpha_p=self.alpha_p,
            )
        elif self.version == "sba":
            try:
                self.forecast_val = self.method(series.values(copy=False),
                                                h=1,
                                                future_xreg=None)
            except errors.TypingError:
                raise_if(
                    True,
                    '"sba" version is not supported with this version of statsforecast.',
                )

        else:
            self.forecast_val = self.method(series.values(copy=False),
                                            h=1,
                                            future_xreg=None)
        return self
Пример #2
0
 def ts_inverse_transform(series: TimeSeries, transformer, *args,
                          **kwargs) -> TimeSeries:
     return TimeSeries.from_times_and_values(
         times=series.time_index,
         values=transformer.inverse_transform(series.values().reshape(
             (-1, series.width))),
         fill_missing_dates=False)
Пример #3
0
    def fit(self, series: TimeSeries):
        super().fit(series)
        series = self.training_series

        # if the model was initially created with `self.seasonal_periods=None`, make sure that
        # the model will try to automatically infer the index, otherwise it should use the
        # provided `seasonal_periods` value
        seasonal_periods_param = (
            None if self.infer_seasonal_periods else self.seasonal_periods
        )

        # set the seasonal periods paramter to a default value if it was not provided explicitly
        # and if it cannot be inferred due to the lack of a datetime index
        if self.seasonal_periods is None and series.has_range_index:
            seasonal_periods_param = 12

        hw_model = hw.ExponentialSmoothing(
            series.values(),
            trend=self.trend if self.trend is None else self.trend.value,
            damped_trend=self.damped,
            seasonal=self.seasonal if self.seasonal is None else self.seasonal.value,
            seasonal_periods=seasonal_periods_param,
            freq=series.freq if series.has_datetime_index else None,
            dates=series.time_index if series.has_datetime_index else None,
        )
        hw_results = hw_model.fit(**self.fit_kwargs)
        self.model = hw_results

        if self.infer_seasonal_periods:
            self.seasonal_periods = hw_model.seasonal_periods

        return self
Пример #4
0
 def _fit(self,
          series: TimeSeries,
          future_covariates: Optional[TimeSeries] = None):
     super()._fit(series, future_covariates)
     series = self.training_series
     self.model.fit(
         series.values(),
         X=future_covariates.values() if future_covariates else None)
     return self
Пример #5
0
    def fit(self, series: TimeSeries):
        super().fit(series)
        series = self.training_series

        if self.infer_seasonal_periods:
            seasonality = _seasonality_from_freq(series)
            self.kwargs["seasonal_periods"] = seasonality
            self.seasonal_periods = seasonality

        model = self._create_model()
        fitted_model = model.fit(series.values())
        self.model = fitted_model

        return self
Пример #6
0
def find_peak_indices(series: TimeSeries, peak_params: PeakParams) -> Peaks:
    """List the timestamps at which channel activity peaks."""
    peak_params = calculate_distance_wlen(series, peak_params)
    # pandas-vet thinks `series` is a pandas data structure with
    # ambiguous behavior for values()
    indices: np.ndarray
    properties: Mapping[str, np.array]
    indices, properties = sp.signal.find_peaks(
        series.values().flatten(),  # noqa: PD011
        distance=peak_params.distance,
        wlen=peak_params.wlen,
        height=series.mean(),
    )
    return Peaks(indices, properties)
Пример #7
0
    def fit(self, series: TimeSeries) -> 'Scaler':
        """
        Fits this scaler to the provided time series data

        Parameters
        ----------
        series
            The time series to fit the scaler on

        Returns
        -------
            Fitted scaler (self)
        """
        super().fit(series)
        self.transformer.fit(series.values().reshape((-1, series.width)))
        self.train_series = series
        return self
Пример #8
0
    def filter(self,
               series: TimeSeries,
               num_samples: int = 1) -> TimeSeries:
        """
        Fits the Gaussian Process on the observations and returns samples from the Gaussian Process,
        or its mean values if `num_samples` is set to 1.

        Parameters
        ----------
        series : TimeSeries
            The series of observations used to infer the values according to the specified Gaussian Process.
            This must be a deterministic series (containing one sample).
        num_samples: int, default: 1
            Number of times a prediction is sampled from the Gaussian Process. If set to 1,
            instead the mean values will be returned.

        Returns
        -------
        TimeSeries
            A stochastic `TimeSeries` sampled from the Gaussian Process, or its mean
            if `num_samples` is set to 1.
        """
        raise_if_not(series.is_deterministic, 'The input series for the Gaussian Process filter must be '
                                              'deterministic (observations).')
        super().filter(series)

        values = series.values(copy=False)
        if series.has_datetime_index:
            times = np.arange(series.n_timesteps).reshape(-1, 1)
        else:
            times = series.time_index.values.reshape(-1, 1)

        not_nan_mask = np.all(~np.isnan(values), axis=1)

        self.model.fit(times[not_nan_mask, :], values[not_nan_mask, :])

        if num_samples == 1:
            filtered_values = self.model.predict(times)
        else:
            filtered_values = self.model.sample_y(times, n_samples=num_samples)
        
        return TimeSeries.from_times_and_values(series.time_index, filtered_values)
Пример #9
0
    def inverse_transform(self, series: TimeSeries, *args,
                          **kwargs) -> TimeSeries:
        """
        Performs the inverse transformation on a time series

        Parameters
        ----------
        series
            The time series to inverse transform

        Returns
        -------
        TimeSeries
            The inverse transform
        """
        super().inverse_transform(series, *args, **kwargs)
        return TimeSeries.from_times_and_values(
            series.time_index(),
            self.transformer.inverse_transform(series.values().reshape(
                (-1, series.width))), series.freq())
Пример #10
0
    def transform(self, series: TimeSeries, *args, **kwargs) -> TimeSeries:
        """
        Returns a new time series, transformed with this (fitted) scaler.
        This does not handle series with confidence intervals - the intervals are discarded.

        Parameters
        ----------
        series
            The time series to transform

        Returns
        -------
        TimeSeries
            A new time series, transformed with this (fitted) scaler.
        """
        super().transform(series, *args, **kwargs)
        return TimeSeries.from_times_and_values(
            series.time_index(),
            self.transformer.transform(series.values().reshape(
                (-1, series.width))), series.freq())
Пример #11
0
    def select_best_model(
        ts: TimeSeries,
        thetas: Optional[List[int]] = None,
        m: Optional[int] = None,
        normalization: bool = True,
        n_jobs: int = 1,
    ) -> "FourTheta":
        """
        Performs a grid search over all hyper parameters to select the best model,
        using the fitted values on the training series `ts`.


        Uses 'ForecastingModel.gridsearch' with 'use_fitted_values=True' and 'metric=metrics.mae`.

        Parameters
        ----------
        ts
            The TimeSeries on which the model will be tested.
        thetas
            A list of thetas to loop over. Defaults to [1, 2, 3].
        m
            Optionally, the season used to decompose the time series.
        normalization
            If `True`, the data is normalized so that the mean is 1. Defaults to `True`.
        n_jobs
            The number of jobs to run in parallel. Parallel jobs are created only when there are two or more theta
            values to be evaluated. Each job will instantiate, train, and evaluate a different instance of the model.
            Defaults to `1` (sequential). Setting the parameter to `-1` means using all the available cores.

        Returns
        -------
        FourTheta
            The best performing model on the time series.
        """
        # Only import if needed
        from darts.metrics import mae

        if thetas is None:
            thetas = [1, 2, 3]
        if (ts.values(copy=False) <= 0).any():
            drift_mode = [TrendMode.LINEAR]
            model_mode = [ModelMode.ADDITIVE]
            season_mode = [SeasonalityMode.ADDITIVE]
            logger.warning(
                "The given TimeSeries has negative values. The method will only test "
                "linear trend and additive modes."
            )
        else:
            season_mode = [season for season in SeasonalityMode]
            model_mode = [model for model in ModelMode]
            drift_mode = [trend for trend in TrendMode]

        theta = FourTheta.gridsearch(
            {
                "theta": thetas,
                "model_mode": model_mode,
                "season_mode": season_mode,
                "trend_mode": drift_mode,
                "seasonality_period": [m],
                "normalization": [normalization],
            },
            ts,
            use_fitted_values=True,
            metric=mae,
            n_jobs=n_jobs,
        )
        return theta
Пример #12
0
 def ts_fit(series: TimeSeries, transformer, *args, **kwargs) -> Any:
     # fit_parameter will receive the transformer object instance
     scaler = transformer.fit(series.values().reshape((-1, series.width)))
     return scaler
Пример #13
0
    def filter(
        self,
        series: TimeSeries,
        covariates: Optional[TimeSeries] = None,
        num_samples: int = 1,
    ) -> TimeSeries:
        """
        Sequentially applies the Kalman filter on the provided series of observations.

        Parameters
        ----------
        series : TimeSeries
            The series of outputs (observations) used to infer the underlying outputs according to the specified Kalman
            process. This must be a deterministic series (containing one sample).
        covariates : Optional[TimeSeries]
            An optional series of inputs (control signal), necessary if the Kalman filter was initialized with
            covariates. This must be a deterministic series (containing one sample).
        num_samples : int, default: 1
            The number of samples to generate from the inferred distribution of the output z. If this is set to 1, the
            output is a `TimeSeries` containing a single sample using the mean of the distribution.

        Returns
        -------
        TimeSeries
            A (stochastic) `TimeSeries` of the inferred output z, of the same width as the input series.
        """
        super().filter(series)

        raise_if(
            self.kf is None,
            "The Kalman filter has not been fitted yet. Call `fit()` first "
            "or provide Kalman filter in constructor.",
        )

        raise_if_not(
            series.width == self.dim_y,
            "The provided TimeSeries dimensionality does not match "
            "the output dimensionality of the Kalman filter.",
        )

        raise_if(
            covariates is not None and not self._expect_covariates,
            "Covariates were provided, but the Kalman filter was not fitted with covariates.",
        )

        if self._expect_covariates:
            raise_if(
                covariates is None,
                "The Kalman filter was fitted with covariates, but these were not provided.",
            )

            raise_if_not(
                covariates.is_deterministic,
                "The covariates must be deterministic (observations).",
            )

            covariates = covariates.slice_intersect(series)
            raise_if_not(
                series.has_same_time_as(covariates),
                "The number of timesteps in the series and the covariates must match.",
            )

        kf = deepcopy(self.kf)

        y_values = series.values(copy=False)
        if self._expect_covariates:
            u_values = covariates.values(copy=False)

            # set control signal to 0 if it contains NaNs:
            u_values = np.nan_to_num(u_values, copy=True, nan=0.0)
        else:
            u_values = np.zeros((len(y_values), 0))

        # For each time step, we'll sample "n_samples" from a multivariate Gaussian
        # whose mean vector and covariance matrix come from the Kalman filter.
        sampled_outputs = np.zeros((len(y_values), self.dim_y, num_samples))

        for i in range(len(y_values)):
            y = y_values[i, :].reshape(-1, 1)
            u = u_values[i, :].reshape(-1, 1)

            if np.isnan(y).any():
                y = None

            kf.step(y, u)
            mean_vec = kf.y_filtereds[-1].reshape(self.dim_y, )

            if num_samples == 1:
                sampled_outputs[i, :, 0] = mean_vec
            else:
                # The measurement covariance matrix is given by the sum of the covariance matrix of the
                # state estimate (transformed by C) and the covariance matrix of the measurement noise.
                cov_matrix = (
                    kf.state_space.c @ kf.p_filtereds[-1] @ kf.state_space.c.T
                    + kf.r)
                sampled_outputs[i, :, :] = np.random.multivariate_normal(
                    mean_vec, cov_matrix, size=num_samples).T

        return series.with_values(sampled_outputs)
Пример #14
0
 def ts_inverse_transform(series: TimeSeries, transformer, *args,
                          **kwargs) -> TimeSeries:
     return TimeSeries.from_times_and_values(
         series.time_index(),
         transformer.inverse_transform(series.values().reshape(
             (-1, series.width))), series.freq())
Пример #15
0
 def ts_transform(series: TimeSeries, transformer) -> TimeSeries:
     return TimeSeries.from_times_and_values(
         series.time_index(),
         transformer.transform(series.values().reshape((-1, series.width))),
         series.freq())