Skip to content

Commit

Permalink
Adding the Neural Prophet Params Class
Browse files Browse the repository at this point in the history
Summary:
This submission creates 2 files

1. kats/kats/models/neural_prophet_models.py

2. kats/kats/test/models/test_models_neural_prophet_model.py

And makes the following to the TARGETS file
replaces the source of the neural prophet package from data.ai to external

1. adds target for testing

2. adds the neural_propjet_models.py to the kats target

Reviewed By: ckomurlufb

Differential Revision: D30550349

fbshipit-source-id: 4fa090778118378a8ce7dc69e3ee662399bd73d3
  • Loading branch information
Mehmet Yunt authored and facebook-github-bot committed Aug 30, 2021
1 parent 206c504 commit 5f44b20
Show file tree
Hide file tree
Showing 2 changed files with 286 additions and 0 deletions.
225 changes: 225 additions & 0 deletions kats/models/neural_prophet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# Copyright (c) Facebook, Inc. and its affiliates.
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

"""The NeuralProphet model
Neural Prophet model is a neural network based time-series model, inspired by
Facebook Prophet and AR-Net, built on PyTorch.
"""

import logging

try:
from neuralprophet import NeuralProphet

_no_neural_prophet = False
except ImportError:
_no_neural_prophet = True
NeuralProphet = None # for Pyre

from kats.consts import Params


class NeuralProphetParams(Params):
"""Parameter class for NeuralProphet model
This is the parameter class for the neural prophet model. It contains all necessary
parameters as definied in Prophet implementation:
https://github.com/ourownstory/neural_prophet/blob/master/neuralprophet/forecaster.py
Attributes:
## Trend Parameters:
growth (str): ['off', 'linear'] to specify
no trend or a linear trend.
Note: 'discontinuous' setting is actually not a trend per se.
only use if you know what you do.
changepoints list: Dates at which to include potential changepoints.
If not specified, potential changepoints are selected automatically.
data format: list of str, list of np.datetimes, np.array of np.datetimes
(not np.array of np.str)
n_changepoints (int): Number of potential changepoints to include.
Changepoints are selected uniformly from the first `changepoints_range`
proportion of the history.
Not used if input `changepoints` is supplied. If `changepoints` is not
supplied.
changepoints_range (float): Proportion of history in which trend changepoints
wil be estimated. Defaults to 0.8 for the first 80%.
Not used if `changepoints` is specified.
trend_reg (float): Parameter modulating the flexibility of the automatic
changepoint selection.
Large values (~1-100) will limit the variability of changepoints.
Small values (~0.001-1.0) will allow changepoints to change faster.
default: 0 will fully fit a trend to each segment.
trend_reg_threshold (bool, float): Allowance for trend to change
without regularization.
True: Automatically set to a value that leads to a smooth trend.
False: All changes in changepoints are regularized
## Seasonality Parameters
yearly_seasonality (bool, int): Fit yearly seasonality.
Can be 'auto', True, False, or a number of Fourier/linear terms to generate.
weekly_seasonality (bool, int): Fit monthly seasonality.
Can be 'auto', True, False, or a number of Fourier/linear terms to generate.
daily_seasonality (bool, int): Fit daily seasonality.
Can be 'auto', True, False, or a number of Fourier/linear terms to generate.
seasonality_mode (str): 'additive' (default) or 'multiplicative'.
seasonality_reg (float): Parameter modulating the strength of the seasonality model.
Smaller values (~0.1-1) allow the model to fit larger seasonal fluctuations,
larger values (~1-100) dampen the seasonality.
default: None, no regularization
## AR Parameters
n_lags (int): Previous time series steps to include in auto-regression. Aka AR-order
ar_sparsity (float): [0-1], how much sparsity to enduce in the AR-coefficients.
Should be around (# nonzero components) / (AR order), eg. 3/100 = 0.03
## Neural Network Model Parameters
n_forecasts (int): Number of steps ahead of prediction time step to forecast.
num_hidden_layers (int): number of hidden layer to include in AR-Net. defaults to 0.
d_hidden (int): dimension of hidden layers of the AR-Net. Ignored if num_hidden_layers == 0.
## Train Parameters
learning_rate (float): Maximum learning rate setting for 1cycle policy scheduler.
default: None: Automatically sets the learning_rate based on a learning rate range test.
For manual values, try values ~0.001-10.
epochs (int): Number of epochs (complete iterations over dataset) to train model.
default: None: Automatically sets the number of epochs based on dataset size.
For best results also leave batch_size to None.
For manual values, try ~5-500.
batch_size (int): Number of samples per mini-batch.
default: None: Automatically sets the batch_size based on dataset size.
For best results also leave epochs to None.
For manual values, try ~1-512.
loss_func (str, torch.nn.modules.loss._Loss, 'typing.Callable'):
Type of loss to use: str ['Huber', 'MSE'],
or torch loss or callable for custom loss, eg. asymmetric Huber loss
train_speed (int, float) a quick setting to speed up or slow down
model fitting [-3, -2, -1, 0, 1, 2, 3]
potentially useful when under-, over-fitting, or simply in a hurry.
applies
epochs *= 2**-train_speed, batch_size *= 2**train_speed, learning_rate *= 2**train_speed,
default None: equivalent to 0.
## Data Parameters
normalize (str): Type of normalization to apply to the time series.
options: ['auto', 'soft', 'off', 'minmax, 'standardize']
default: 'auto' uses 'minmax' if variable is binary, else 'soft'
'soft' scales minimum to 0.1 and the 90th quantile to 0.9
impute_missing (bool): whether to automatically impute missing dates/values
imputation follows a linear method up to 10 missing values, more are filled with trend.
"""

def __init__(
self,
growth="linear",
changepoints=None,
n_changepoints=10,
changepoints_range=0.9,
trend_reg=0,
trend_reg_threshold=False,
yearly_seasonality="auto",
weekly_seasonality="auto",
daily_seasonality="auto",
seasonality_mode="additive",
seasonality_reg=0,
n_forecasts=1,
n_lags=0,
num_hidden_layers=0,
d_hidden=None,
ar_sparsity=None,
learning_rate=None,
epochs=None,
batch_size=None,
loss_func="Huber",
optimizer="AdamW",
train_speed=None,
normalize="auto",
impute_missing=True,
) -> None:
super().__init__()
self.growth = growth
self.changepoints = changepoints
self.n_changepoints = n_changepoints
self.changepoints_range = changepoints_range
self.trend_reg = trend_reg
self.trend_reg_threshold = trend_reg_threshold
self.yearly_seasonality = yearly_seasonality
self.weekly_seasonality = weekly_seasonality
self.daily_seasonality = daily_seasonality
self.seasonality_mode = seasonality_mode
self.seasonality_reg = seasonality_reg
self.n_forecasts = n_forecasts
self.n_lags = n_lags
self.num_hidden_layers = num_hidden_layers
self.d_hidden = d_hidden
self.ar_sparsity = ar_sparsity
self.learning_rate = learning_rate
self.epochs = epochs
self.batch_size = batch_size
self.loss_func = loss_func
self.optimizer = optimizer
self.train_speed = train_speed
self.normalize = normalize
self.impute_missing = impute_missing
if _no_neural_prophet:
raise RuntimeError("requires neuralprophet to be installed")

logging.debug(
"Initialized Neural Prophet with parameters. "
"growth:{growth},"
"changepoints:{changepoints},"
"n_changepoints:{n_changepoints},"
"changepoints_range:{changepoints_range},"
"trend_reg:{trend_reg},"
"trend_reg_threshold:{trend_reg_threshold},"
"yearly_seasonality:{yearly_seasonality},"
"weekly_seasonality:{weekly_seasonality},"
"daily_seasonality:{daily_seasonality},"
"seasonality_mode:{seasonality_mode},"
"seasonality_reg:{seasonality_reg},"
"n_forecasts:{n_forecasts},"
"n_lags:{n_lags},"
"num_hidden_layers:{num_hidden_layers},"
"d_hidden:{d_hidden},"
"ar_sparsity:{ar_sparsity},"
"learning_rate:{learning_rate},"
"epochs:{epochs},"
"batch_size:{batch_size},"
"loss_func:{loss_func},"
"optimizer:{optimizer},"
"train_speed:{train_speed},"
"normalize:{normalize},"
"impute_missing:{impute_missing}".format(
growth=growth,
changepoints=changepoints,
n_changepoints=n_changepoints,
changepoints_range=changepoints_range,
trend_reg=trend_reg,
trend_reg_threshold=trend_reg_threshold,
yearly_seasonality=yearly_seasonality,
weekly_seasonality=weekly_seasonality,
daily_seasonality=daily_seasonality,
seasonality_mode=seasonality_mode,
seasonality_reg=seasonality_reg,
n_forecasts=n_forecasts,
n_lags=n_lags,
num_hidden_layers=num_hidden_layers,
d_hidden=d_hidden,
ar_sparsity=ar_sparsity,
learning_rate=learning_rate,
epochs=epochs,
batch_size=batch_size,
loss_func=loss_func,
optimizer=optimizer,
train_speed=train_speed,
normalize=normalize,
impute_missing=impute_missing,
)
)

def validate_params(self):
"""Validate Neural Prophet Parameters"""
logging.debug("Not yet implemented")
pass
61 changes: 61 additions & 0 deletions kats/tests/models/test_neural_prophet_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright (c) Facebook, Inc. and its affiliates.
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

import io
import logging
import os
import pkgutil
import unittest
from unittest import TestCase

import pandas as pd
from kats.consts import TimeSeriesData
from kats.models.neural_prophet import NeuralProphetParams


class NeuralProphetModelTest(TestCase):
def setUp(self):
# Expected default parameters
self.expected_defaults = NeuralProphetParams(
growth="linear",
changepoints=None,
n_changepoints=10,
changepoints_range=0.9,
trend_reg=0,
trend_reg_threshold=False,
yearly_seasonality="auto",
weekly_seasonality="auto",
daily_seasonality="auto",
seasonality_mode="additive",
seasonality_reg=0,
n_forecasts=1,
n_lags=0.0,
num_hidden_layers=0,
d_hidden=None,
ar_sparsity=None,
learning_rate=None,
epochs=None,
batch_size=None,
loss_func="Huber",
optimizer="AdamW",
train_speed=None,
normalize="auto",
impute_missing=True,
)

def test_default_parameters(self) -> None:

"""Check that the default parameters are as expected. The expected values are hard coded."""
act_params = vars(NeuralProphetParams())

for param, exp_val in vars(self.expected_defaults).items():
msg = """param:{param}, exp_val:{exp_val}, val:{val}""".format(
param=param, exp_val=exp_val, val=act_params[param]
)
logging.info(msg)
self.assertEqual(act_params[param], exp_val)


if __name__ == "__main__":
unittest.main()

0 comments on commit 5f44b20

Please sign in to comment.