示例#1
0
 def build(self, config):
     """
     Build ARIMA Model
     :param config: Other ARIMA hyperparameters. You may refer to
        https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
     for the parameter names to specify.
     """
     from zoo.chronos.model.arima import ARIMAModel
     model = ARIMAModel()
     model._build(**config)
     return model
示例#2
0
    def test_save_restore(self):
        self.model.fit_eval(data=self.data, validation_data=self.validation_data, **self.config)
        result_save = self.model.predict(horizon=self.horizon, rolling=False)
        model_file = "tmp.pkl"

        self.model.save(model_file)
        assert os.path.isfile(model_file)
        new_model = ARIMAModel()
        new_model.restore(model_file)
        assert new_model.model
        result_restore = new_model.predict(horizon=self.horizon, rolling=False)
        assert_array_almost_equal(result_save, result_restore, decimal=2), \
            "Prediction values are not the same after restore: " \
            "predict before is {}, and predict after is {}".format(result_save, result_restore)
        os.remove(model_file)
示例#3
0
 def setup_method(self, method):
     self.seq_len = 400
     self.config = {
         "p": np.random.randint(0, 4),
         "q": np.random.randint(0, 4),
         "seasonality_mode": np.random.choice([True, False]),
         "P": 5,
         "Q": 5,
         "m": np.random.choice([4, 7]),
         "metric": "mse",
     }
     self.model = ARIMAModel()
     self.data = np.random.rand(self.seq_len)
     self.horizon = np.random.randint(2, 50)
     self.validation_data = np.random.rand(self.horizon)
示例#4
0
    def __init__(
        self,
        p=2,
        q=2,
        seasonality_mode=True,
        P=3,
        Q=1,
        m=7,
        metric="mse",
    ):
        """
        Build a ARIMA Forecast Model.
        User need to set p, q, P, Q, m for the ARIMA model, the differencing term (d) and
        seasonal differencing term (D) are automatically estimated from the data.

        :param p: hyperparameter p for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param q: hyperparameter q for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param seasonality_mode: hyperparameter seasonality_mode for the ARIMA model,
            for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param P: hyperparameter P for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param Q: hyperparameter Q for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param m: hyperparameter m for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param metric: the metric for validation and evaluation. For regression, we support
            Mean Squared Error: ("mean_squared_error", "MSE" or "mse"),
            Mean Absolute Error: ("mean_absolute_error","MAE" or "mae"),
            Mean Absolute Percentage Error: ("mean_absolute_percentage_error", "MAPE", "mape")
            Cosine Proximity: ("cosine_proximity", "cosine")
        """
        self.model_config = {
            "p": p,
            "q": q,
            "seasonality_mode": seasonality_mode,
            "P": P,
            "Q": Q,
            "m": m,
            "metric": metric,
        }
        self.internal = ARIMAModel()

        super().__init__()
示例#5
0
class ARIMAForecaster(Forecaster):
    """
    ARIMA Forecaster
    AutoRegressive Integrated Moving Average (ARIMA) is a class of statistical models
    for analyzing and forecasting time series data. It consists of 3 components:
    AR (AutoRegressive), I (Integrated) and MA (Moving Average). In ARIMAForecaster we use
    the SARIMA model (Seasonal ARIMA), which is an extension of ARIMA that additionally
    supports the direct modeling of the seasonal component of the time series.
    """
    def __init__(
        self,
        p=2,
        q=2,
        seasonality_mode=True,
        P=3,
        Q=1,
        m=7,
        metric="mse",
    ):
        """
        Build a ARIMA Forecast Model.
        User need to set p, q, P, Q, m for the ARIMA model, the differencing term (d) and
        seasonal differencing term (D) are automatically estimated from the data.

        :param p: hyperparameter p for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param q: hyperparameter q for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param seasonality_mode: hyperparameter seasonality_mode for the ARIMA model,
            for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param P: hyperparameter P for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param Q: hyperparameter Q for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param m: hyperparameter m for the ARIMA model, for details you may refer to
            https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.ARIMA.html#pmdarima.arima.ARIMA
        :param metric: the metric for validation and evaluation. For regression, we support
            Mean Squared Error: ("mean_squared_error", "MSE" or "mse"),
            Mean Absolute Error: ("mean_absolute_error","MAE" or "mae"),
            Mean Absolute Percentage Error: ("mean_absolute_percentage_error", "MAPE", "mape")
            Cosine Proximity: ("cosine_proximity", "cosine")
        """
        self.model_config = {
            "p": p,
            "q": q,
            "seasonality_mode": seasonality_mode,
            "P": P,
            "Q": Q,
            "m": m,
            "metric": metric,
        }
        self.internal = ARIMAModel()

        super().__init__()

    def fit(self, data, validation_data):
        """
        Fit(Train) the forecaster.

        :param data: A 1-D numpy array as the training data
        :param validation_data: A 1-D numpy array as the evaluation data
        """
        self._check_data(data, validation_data)
        data = data.reshape(-1, 1)
        validation_data = validation_data.reshape(-1, 1)
        return self.internal.fit_eval(data=data,
                                      validation_data=validation_data,
                                      **self.model_config)

    def _check_data(self, data, validation_data):
        assert data.ndim == 1, \
            "data should be an 1-D array), \
            Got data dimension of {}."\
            .format(data.ndim)
        assert validation_data.ndim == 1, \
            "validation_data should be an 1-D array), \
            Got validation_data dimension of {}."\
            .format(validation_data.ndim)

    def predict(self, horizon, rolling=False):
        """
        Predict using a trained forecaster.

        :param horizon: the number of steps forward to predict
        :param rolling: whether to use rolling prediction
        """
        if self.internal.model is None:
            raise RuntimeError(
                "You must call fit or restore first before calling predict!")
        return self.internal.predict(horizon=horizon, rolling=rolling)

    def evaluate(self, validation_data, metrics=['mse'], rolling=False):
        """
        Evaluate using a trained forecaster.

        :param validation_data: A 1-D numpy array as the evaluation data
        :param metrics: A list contains metrics for test/valid data.
        """
        if validation_data is None:
            raise ValueError("Input invalid validation_data of None")
        if self.internal.model is None:
            raise RuntimeError(
                "You must call fit or restore first before calling evaluate!")
        return self.internal.evaluate(validation_data,
                                      metrics=metrics,
                                      rolling=rolling)

    def save(self, checkpoint_file):
        """
        Save the forecaster.

        :param checkpoint_file: The location you want to save the forecaster.
        """
        if self.internal.model is None:
            raise RuntimeError(
                "You must call fit or restore first before calling save!")
        self.internal.save(checkpoint_file)

    def restore(self, checkpoint_file):
        """
        Restore the forecaster.

        :param checkpoint_file: The checkpoint file location you want to load the forecaster.
        """
        self.internal.restore(checkpoint_file)
示例#6
0
class TestARIMAModel(ZooTestCase):

    def setup_method(self, method):
        np.random.seed(0)
        self.seq_len = 400
        self.config = {
            "p": np.random.randint(0, 4),
            "q": np.random.randint(0, 4),
            "seasonality_mode": np.random.choice([True, False]),
            "P": 5,
            "Q": 5,
            "m": np.random.choice([4, 7]),
            "metric": "mse",
        }
        self.model = ARIMAModel()
        self.data = np.random.rand(self.seq_len)
        self.horizon = np.random.randint(2, 50)
        self.validation_data = np.random.rand(self.horizon)

    def teardown_method(self, method):
        del self.model
        del self.data
        del self.validation_data

    def test_arima(self):
        # test fit_eval
        evaluate_result = self.model.fit_eval(data=self.data,
                                              validation_data=self.validation_data,
                                              **self.config
                                              )
        # test predict
        result = self.model.predict(horizon=self.horizon)
        assert len(result) == self.horizon
        # test evaluate
        evaluate_result = self.model.evaluate(target=self.validation_data, metrics=['mae', 'smape'])
        assert len(evaluate_result) == 2
        # test rolling predict
        rolling_result = self.model.predict(horizon=self.horizon, rolling=True)
        assert len(rolling_result) == self.horizon

    def test_error(self):
        with pytest.raises(ValueError, match="x should be None"):
            self.model.predict(x=1)

        with pytest.raises(ValueError, match="We don't support input x currently"):
            self.model.evaluate(target=self.validation_data, x=1)

        with pytest.raises(ValueError, match="Input invalid target of None"):
            self.model.evaluate(target=None)

        with pytest.raises(Exception,
                           match="Needs to call fit_eval or restore first before calling predict"):
            self.model.predict(horizon=self.horizon)

        with pytest.raises(Exception,
                           match="We don't support updating model "
                                 "without rolling prediction currently"
                           ):
            self.model.predict(horizon=self.horizon, update=True, rolling=False)

        with pytest.raises(Exception,
                           match="Needs to call fit_eval or restore first before calling evaluate"):
            self.model.evaluate(target=self.validation_data, x=None)

        with pytest.raises(Exception,
                           match="Needs to call fit_eval or restore first before calling save"):
            model_file = "tmp.pkl"
            self.model.save(model_file)

    def test_save_restore(self):
        self.model.fit_eval(data=self.data, validation_data=self.validation_data, **self.config)
        result_save = self.model.predict(horizon=self.horizon, rolling=False)
        model_file = "tmp.pkl"

        self.model.save(model_file)
        assert os.path.isfile(model_file)
        new_model = ARIMAModel()
        new_model.restore(model_file)
        assert new_model.model
        result_restore = new_model.predict(horizon=self.horizon, rolling=False)
        assert_array_almost_equal(result_save, result_restore, decimal=2), \
            "Prediction values are not the same after restore: " \
            "predict before is {}, and predict after is {}".format(result_save, result_restore)
        os.remove(model_file)