diff --git a/kats/models/metalearner/metalearner_hpt.py b/kats/models/metalearner/metalearner_hpt.py index a969759b..c86bc226 100644 --- a/kats/models/metalearner/metalearner_hpt.py +++ b/kats/models/metalearner/metalearner_hpt.py @@ -29,7 +29,6 @@ from sklearn.model_selection import train_test_split _MODELS = { - "neuralprophet", "prophet", "arima", "sarima", @@ -56,8 +55,6 @@ class DefaultModelParams: theta_numerical_idx: List[str] = field(default_factory=list) stlf_categorical_idx: List[str] = field(default_factory=list) stlf_numerical_idx: List[str] = field(default_factory=list) - neuralprophet_categorical_idx: List[str] = field(default_factory=list) - neuralprophet_numerical_idx: List[str] = field(default_factory=list) prophet_categorical_idx: List[str] = field(default_factory=list) prophet_numerical_idx: List[str] = field(default_factory=list) cusum_categorical_idx: List[str] = field(default_factory=list) @@ -81,14 +78,6 @@ def __init__(self) -> None: self.theta_numerical_idx = [] self.stlf_categorical_idx = ["method", "m"] self.stlf_numerical_idx = [] - self.neuralprophet_categorical_idx = [ - "yearly_seasonality", - "weekly_seasonality", - "daily_seasonality", - "seasonality_mode", - "changepoints_range", - ] - self.neuralprophet_numerical_idx = [] self.prophet_categorical_idx = [ "yearly_seasonality", "weekly_seasonality", @@ -126,9 +115,6 @@ class DefaultModelNetworks: stlf_n_hidden_shared: List[int] = field(default_factory=list) stlf_n_hidden_cat_combo: List[List[int]] = field(default_factory=list) stlf_n_hidden_num: List[int] = field(default_factory=list) - neuralprophet_n_hidden_shared: List[int] = field(default_factory=list) - neuralprophet_n_hidden_cat_combo: List[List[int]] = field(default_factory=list) - neuralprophet_n_hidden_num: List[int] = field(default_factory=list) prophet_n_hidden_shared: List[int] = field(default_factory=list) prophet_n_hidden_cat_combo: List[List[int]] = field(default_factory=list) prophet_n_hidden_num: List[int] = field(default_factory=list) @@ -155,9 +141,6 @@ def __init__(self) -> None: self.stlf_n_hidden_shared = [20] self.stlf_n_hidden_cat_combo = [[5], [5]] self.stlf_n_hidden_num = [] - self.neuralprophet_n_hidden_shared = [40] - self.neuralprophet_n_hidden_cat_combo = [[5], [5], [2], [3], [5]] - self.neuralprophet_n_hidden_num = [] self.prophet_n_hidden_shared = [40] self.prophet_n_hidden_cat_combo = [[5], [5], [2], [3], [5], [5], [5]] self.prophet_n_hidden_num = [] @@ -187,7 +170,7 @@ class MetaLearnHPT: categorical_idx: Optional; A list of strings of the names of the categorical hyper-parameters. Default is None. numerical_idx: Optional; A list of strings of the names of the numerical hyper-parameters. Default is None. default_model: Optional; A string of the name of the forecast model whose default settings will be used. - Can be 'arima', 'sarima', 'theta', 'neuralprophet', 'prophet', 'holtwinters', 'stlf' or None. Default is None. + Can be 'arima', 'sarima', 'theta', 'prophet', 'holtwinters', 'stlf' or None. Default is None. scale: Optional; A boolean to specify whether or not to normalize time series features to zero mean and unit variance. Default is True. load_model: Optional; A boolean to specify whether or not to load a trained model. Default is False. @@ -259,7 +242,7 @@ def __init__( categorical_idx = getattr(default_model_params, categorical_idx_var) numerical_idx = getattr(default_model_params, numerical_idx_var) else: - msg = f"default_model={default_model} is not available! Please choose one from 'neuralprophet', 'prophet', 'arima', 'sarima', 'holtwinters', 'stlf', 'theta', 'cusum', 'statsig'" + msg = f"default_model={default_model} is not available! Please choose one from 'prophet', 'arima', 'sarima', 'holtwinters', 'stlf', 'theta', 'cusum', 'statsig'" raise _log_error(msg) if (not numerical_idx) and (not categorical_idx): diff --git a/kats/tests/models/test_metalearner.py b/kats/tests/models/test_metalearner.py index d1ca1038..bc88a47e 100644 --- a/kats/tests/models/test_metalearner.py +++ b/kats/tests/models/test_metalearner.py @@ -24,7 +24,6 @@ from kats.models.metalearner.metalearner_hpt import MetaLearnHPT from kats.models.metalearner.metalearner_modelselect import MetaLearnModelSelect from kats.models.metalearner.metalearner_predictability import MetaLearnPredictability -from kats.models.neuralprophet import NeuralProphetModel, NeuralProphetParams from kats.models.prophet import ProphetModel, ProphetParams from kats.models.sarima import SARIMAModel, SARIMAParams from kats.models.stlf import STLFModel, STLFParams @@ -77,7 +76,6 @@ "arima": ARIMAModel, "holtwinters": HoltWintersModel, "sarima": SARIMAModel, - "neuralprophet": NeuralProphetModel, "prophet": ProphetModel, "stlf": STLFModel, "theta": ThetaModel, @@ -160,14 +158,12 @@ def generate_meta_data_by_model(model, n, d=num_features): "sarima", "theta", "stlf", - "neuralprophet", "prophet", ] } candidate_models = { "holtwinters": HoltWintersModel, - "neuralprophet": NeuralProphetModel, "prophet": ProphetModel, "theta": ThetaModel, "stlf": STLFModel, @@ -176,7 +172,6 @@ def generate_meta_data_by_model(model, n, d=num_features): candidate_params = { "holtwinters": HoltWintersParams, - "neuralprophet": NeuralProphetParams, "prophet": ProphetParams, "theta": ThetaParams, "stlf": STLFParams, @@ -455,7 +450,6 @@ def test_default_models(self) -> None: feature3.copy(), ) for model in [ - "neuralprophet", "prophet", "arima", "sarima", diff --git a/kats/tests/models/test_neuralprophet_model.py b/kats/tests/models/test_neuralprophet_model.py deleted file mode 100644 index c86c2e01..00000000 --- a/kats/tests/models/test_neuralprophet_model.py +++ /dev/null @@ -1,287 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -# pyre-strict - -import builtins -import sys -import unittest -from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence -from unittest import TestCase -from unittest.mock import patch - -import numpy as np -import pandas as pd -from kats.compat import pandas -from kats.consts import TimeSeriesData -from kats.data.utils import load_air_passengers, load_data -from kats.models.neuralprophet import NeuralProphetModel, NeuralProphetParams -from kats.tests.models.test_models_dummy_data import ( - NONSEASONAL_FUTURE_DF, - NONSEASONAL_INPUT, -) - -from parameterized.parameterized import parameterized - - -TEST_DATA: Dict[str, Any] = { - "nonseasonal": { - "ts": TimeSeriesData(NONSEASONAL_INPUT), - "future_df": NONSEASONAL_FUTURE_DF, - "params": NeuralProphetParams(epochs=5), - }, - "daily": { - "ts": TimeSeriesData( - load_data("peyton_manning.csv").set_axis(["time", "y"], axis=1) - ), - "params": NeuralProphetParams(epochs=5), - "params_custom_seasonality": NeuralProphetParams( - epochs=5, - custom_seasonalities=[ - { - "name": "semi_annually", - "period": 365.25 / 2, - "fourier_order": 5, - }, - ], - ), - }, - "monthly": { - "ts": load_air_passengers(), - "params": NeuralProphetParams(epochs=5), - "params_custom_seasonality": NeuralProphetParams( - epochs=5, - custom_seasonalities=[ - { - "name": "monthly", - "period": 30.5, - "fourier_order": 5, - }, - ], - ), - }, - "multivariate": { - "ts": TimeSeriesData(load_data("multivariate_anomaly_simulated_data.csv")) - }, -} - - -class NeuralProphetModelTest(TestCase): - @classmethod - def setUpClass(cls) -> None: - # pyre-fixme[33]: Given annotation cannot contain `Any`. - original_import_fn: Callable[ - [ - str, - Optional[Mapping[str, Any]], - Optional[Mapping[str, Any]], - Sequence[str], - int, - ], - Any, - ] = builtins.__import__ - - # pyre-fixme[2]: Parameter annotation cannot be `Any`. - def mock_neuralprophet_import(module: Any, *args: Any, **kwargs: Any) -> None: - if module == "neuralprophet": - raise ImportError - else: - return original_import_fn(module, *args, **kwargs) - - cls.mock_imports = patch( - "builtins.__import__", side_effect=mock_neuralprophet_import - ) - - def test_neuralprophet_not_installed(self) -> None: - # Unload prophet module so its imports can be mocked as necessary - del sys.modules["kats.models.neuralprophet"] - - with self.mock_imports: - from kats.models.neuralprophet import ( - NeuralProphetModel, - NeuralProphetParams, - ) - - self.assertRaises(RuntimeError, NeuralProphetParams) - self.assertRaises( - RuntimeError, - NeuralProphetModel, - TEST_DATA["daily"]["ts"], - TEST_DATA["daily"]["params"], - ) - - # Restore the prophet module - del sys.modules["kats.models.neuralprophet"] - from kats.models.neuralprophet import NeuralProphetModel, NeuralProphetParams - - # Confirm that the module has been properly reloaded -- should not - # raise an exception anymore - NeuralProphetModel( - TEST_DATA["daily"]["ts"], - NeuralProphetParams( - epochs=5, - ), - ) - - def test_default_parameters(self) -> None: - """ - Check that the default parameters are as expected. The expected values - are hard coded. - """ - expected_defaults = NeuralProphetParams( - growth="linear", - changepoints=None, - n_changepoints=10, - changepoints_range=0.9, - yearly_seasonality="auto", - weekly_seasonality="auto", - daily_seasonality="auto", - seasonality_mode="additive", - custom_seasonalities=None, - ) - - actual_defaults = vars(NeuralProphetParams()) - - # Expected params should be valid - expected_defaults.validate_params() - - for param, exp_val in vars(expected_defaults).items(): - msg = "param: {param}, expected default: {exp_val}, actual default: {val}".format( - param=param, exp_val=exp_val, val=actual_defaults[param] - ) - self.assertEqual(exp_val, actual_defaults[param], msg) - - def test_multivar(self) -> None: - # Prophet model does not support multivariate time series data - self.assertRaises( - ValueError, - NeuralProphetModel, - TEST_DATA["multivariate"]["ts"], - NeuralProphetParams(epochs=5), - ) - - def test_exec_plot(self) -> None: - m = NeuralProphetModel(TEST_DATA["daily"]["ts"], TEST_DATA["daily"]["params"]) - m.fit(freq="MS") - fcst = m.predict(steps=30) - m.plot(fcst) - - def test_name(self) -> None: - m = NeuralProphetModel(TEST_DATA["daily"]["ts"], TEST_DATA["daily"]["params"]) - self.assertEqual("NeuralProphet", m.__str__()) - - def test_search_space(self) -> None: - self.assertEqual( - [ - { - "name": "yearly_seasonality", - "type": "choice", - "value_type": "bool", - "values": [True, False], - }, - { - "name": "weekly_seasonality", - "type": "choice", - "value_type": "bool", - "values": [True, False], - }, - { - "name": "daily_seasonality", - "type": "choice", - "value_type": "bool", - "values": [True, False], - }, - { - "name": "seasonality_mode", - "type": "choice", - "value_type": "str", - "values": ["additive", "multiplicative"], - }, - { - "name": "changepoints_range", - "type": "choice", - "value_type": "float", - "values": list(np.arange(0.85, 0.96, 0.01)), # last value is 0.95 - "is_ordered": True, - }, - ], - NeuralProphetModel.get_parameter_search_space(), - ) - - # Testing extra regressors - # pyre-fixme[56]: Pyre was not able to infer the type of the decorator `parameter... - @parameterized.expand( - [ - [ - "lagged regressors", - 5, - 3, - [ - { - "names": "reg1", - "regularization": 0.1, - "normalize": True, - }, - { - "names": "reg2", - }, - ], - None, - ], - [ - "future regressors", - 5, - 0, - None, - [ - { - "name": "reg1", - "regularization": 0.1, - "normalize": True, - }, - { - "name": "reg2", - }, - ], - ], - ] - ) - def test_regressors( - self, - testcase_name: str, - epochs: Optional[int], - n_lags: int, - extra_lagged_regressors: Optional[List[Dict[str, Any]]], - extra_future_regressors: Optional[List[Dict[str, Any]]], - ) -> None: - tmp_df = TEST_DATA["daily"]["ts"].to_dataframe() - tmp_df["reg1"] = np.arange(len(tmp_df)) - tmp_df["reg2"] = np.arange(len(tmp_df), 0, -1) - ts = TimeSeriesData(tmp_df) - - future = pd.DataFrame( - { - "ds": pd.date_range("2013-05-01", periods=30), - "reg1": np.arange(30), - "reg2": np.arange(30, 0, -1), - } - ) - - m_daily = NeuralProphetModel( - ts, - NeuralProphetParams( - epochs=epochs, - n_lags=n_lags, - extra_lagged_regressors=extra_lagged_regressors, - extra_future_regressors=extra_future_regressors, - ), - ) - m_daily.fit(freq="D") - fcst = m_daily.predict(steps=30, future=future) - m_daily.plot(fcst) - - -if __name__ == "__main__": - unittest.main() diff --git a/kats/tests/models/test_parameter_tuning_default_search_space.py b/kats/tests/models/test_parameter_tuning_default_search_space.py index 0540dd34..2dbcba52 100644 --- a/kats/tests/models/test_parameter_tuning_default_search_space.py +++ b/kats/tests/models/test_parameter_tuning_default_search_space.py @@ -11,7 +11,6 @@ from kats.models.arima import ARIMAModel from kats.models.holtwinters import HoltWintersModel from kats.models.linear_model import LinearModel -from kats.models.neuralprophet import NeuralProphetModel from kats.models.prophet import ProphetModel from kats.models.quadratic_model import QuadraticModel from kats.models.sarima import SARIMAModel @@ -25,10 +24,6 @@ def test_parameter_tuning_default_search_space_arima(self) -> None: search_space = ARIMAModel.get_parameter_search_space() TimeSeriesParameterTuning.validate_parameters_format(search_space) - def test_parameter_tuning_default_search_space_neuralprophet(self) -> None: - search_space = NeuralProphetModel.get_parameter_search_space() - TimeSeriesParameterTuning.validate_parameters_format(search_space) - def test_parameter_tuning_default_search_space_prophet(self) -> None: search_space = ProphetModel.get_parameter_search_space() TimeSeriesParameterTuning.validate_parameters_format(search_space) diff --git a/kats/tests/test_minimal.py b/kats/tests/test_minimal.py index fbb2395d..52549f88 100644 --- a/kats/tests/test_minimal.py +++ b/kats/tests/test_minimal.py @@ -22,15 +22,9 @@ def test_install(self) -> None: def test_minimal_install(self) -> None: try: from kats.detectors import prophet_detector - from kats.models import lstm, neuralprophet - - self.assertFalse( - ( - lstm is not None - and neuralprophet is not None - and prophet_detector is not None - ) - ) + from kats.models import lstm + + self.assertFalse((lstm is not None and prophet_detector is not None)) except ImportError: self.assertTrue(True) diff --git a/kats/utils/parameter_tuning_utils.py b/kats/utils/parameter_tuning_utils.py index 19e2ed7e..d30de9b0 100644 --- a/kats/utils/parameter_tuning_utils.py +++ b/kats/utils/parameter_tuning_utils.py @@ -91,58 +91,6 @@ def get_default_prophet_parameter_search_space() -> List[Dict[str, Any]]: ] -def get_default_neuralprophet_parameter_search_space() -> List[Dict[str, Any]]: - """Generates default search space as a list of dictionaries and returns it for neuralprophet model. - - Each dictionary in the list corresponds to a hyperparameter, having properties - defining that hyperparameter. Properties are name, type, value_type, values, - is_ordered. Hyperparameters that are included: yearly_seasonality, - weekly_seasonality, daily_seasonality, seasonality_mode, changepoints_range. - - Args: - N/A - - Returns: - As described above - - Raises: - N/A - """ - return [ - { - "name": "yearly_seasonality", - "type": "choice", - "value_type": "bool", - "values": [True, False], - }, - { - "name": "weekly_seasonality", - "type": "choice", - "value_type": "bool", - "values": [True, False], - }, - { - "name": "daily_seasonality", - "type": "choice", - "value_type": "bool", - "values": [True, False], - }, - { - "name": "seasonality_mode", - "type": "choice", - "value_type": "str", - "values": ["additive", "multiplicative"], - }, - { - "name": "changepoints_range", - "type": "choice", - "value_type": "float", - "values": list(np.arange(0.85, 0.96, 0.01)), # last value is 0.95 - "is_ordered": True, - }, - ] - - def get_default_arnet_parameter_search_space() -> List[Dict[str, Any]]: """Generates default search space as a list of dictionaries and returns it for arnet. diff --git a/test_requirements.txt b/test_requirements.txt index 4f4dca22..5bb5e11f 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -3,7 +3,6 @@ ax-platform==0.2.9 fbprophet==0.7.1 gpytorch<1.9.0 holidays>=0.10.2 -neuralprophet==0.3.2 numba>=0.52.0 parameterized>=0.8.1 plotly>=2.2.1