- class arnet.ARNet(base_model=None, p=None, P=None, seasonality=None, repeats=20, scale_inputs=True, scale_output=True, transform_output=False)¶
Nonlinear autoregression with feed-forward neural networks (or any estimator really)
- Parameters:
- base_modelEstimator, optional
The underlying model used for fitting and predicting. Defaults to a single layer MLPRegressor, where the number of hidden neurons are chosen automatically and also with max_iter being 2_000. Any model respecting the sklearn’s estimator interface is accepted.
- pint or None, optional
Number of lags to look behind to predict the next instance. Leaving it None leads to automatic selection: “the optimal number of lags (according to the AIC) for a linear AR(p) model”, following nnetar.R.
- Pint or None, optional
Number of seasonal lags to look behind to predict the next instance. Ignored if seasonality is None. If seasonality is not None and P is None, it is automatically selected: same procedure as for p except the data subject to selection is seasonally-adjusted with an STL decomposition, following nnetar.R.
- seasonalityint or None, optional
The periodicity suspected in the data, e.g., 12 for monthly series. None signals no seasonality. No automatic detection of seasonality is performed.
- repeatsint, default=20
Number of base models to fit internally. These are then averaged when making forecasts to smooth out the inherent randomness in the model’s nature, e.g., random network weights and stochastic learning algorithms for neural networks or bagging in random forests.
- scale_inputsbool or Transformer, default=True
Whether (or how) to scale the input to the networks. The input refers to the side information variables (X), if any. If False, no scaling is performed; if True (default), sklearn.preprocessing.StandardScaler() is applied. You can also pass a scaler of your choice, e.g., MinMaxScaler(), as long as it “quacks” like an sklearn transformer.
- scale_outputbool or Transformer, default=True
Whether (or how) to scale the output variable, i.e., the target series (y). If False, no scaling is performed; if True (default), sklearn.preprocessing.StandardScaler() is applied. You can also pass a scaler of your choice, e.g., MinMaxScaler(), as long as it “quacks” like an sklearn transformer.
- transform_outputbool or Transformer, default=False
Whether (or how) to transform the output variable, i.e., the target series (y). If False, no transformation is performed; if True, sklearn.preprocessing.PowerTransformer(“box-cox”, standardize=False), i.e., a BoxCox transformation where lambda is automatically chosen, is applied. You can also pass a transformer of your choice, e.g., FunctionTransformer(np.sqrt, inverse_func=np.square), as long as it “quacks” like an sklearn transformer. Note that if scale_output is on, this transformation is performed before that.
Notes
The default MLPRegressor has two different default parameters than that of sklearn: hidden_layer_sizes and max_iter, where the former is None to signal it’s automatically determined (as in nnetar.R) and the latter is 2_000 as lower values tend to lead convergence issues on various datasets we tried. Of course, both can be changed on will, e.g., you can pass base_model=MLPRegressor() to have the sklearn’s defaults (100 and 200, respectively).
Methods
fit
(y[, X])Train the model on y with possibly side information X.
predict
([X, n_steps, return_intervals, ...])Perform multi-step recursive forecasting and optionally also calculate prediction intervals.
validate
(y, param_grid[, X, base_model_cls, ...])Perform time series cross validation with randomized (or full) grid search.
plot
(lines[, labels, true_indexes, ...])Plot lines with either a plotly or a matplotlib backend.
- fit(y, X=None)¶
Train the model on y with possibly side information X. Note that fit can be called either as fit(X, y) or fit(y, X?).
If left unspecified, p and P are determined first. Then prepares the design matrix where the lagged values reside on the left and the side information, if any, on the right. Lastly, carries out the X and y scalings and transformations, if any, and fits repeats number of base models on them.
Sets two public post-attributes: fitted_values_all_ and fitted_values_, which are the in-sample predictions (the fitted values) of all the networks and the mean of all the networks, respectively.
- Parameters:
- ypd.Series or np.ndarray
The endogenous variable, i.e., the target time series
- Xpd.DataFrame or np.ndarray, optional
The exogenous variables, i.e., the side information matrix
- Returns:
- self
The fitted instance
Notes
The primary way of calling this function is fit(y, X?) where ? signals optionality. However, to comply with the sklearn’s “normal” estimators’ way of passing X first y next, the function also accepts fit(X, y) and arranges internally which are which.
- predict(X=None, n_steps=None, return_intervals=False, n_paths=1000, alphas=95, bootstrap=False, return_paths=False)¶
Perform multi-step recursive forecasting and optionally also calculate prediction intervals.
- Parameters:
- Xpd.DataFrame or np.ndarray
The side information to use for prediction horizon. If the training data had no X, it’s an error to pass one here. Conversely, if training data did have X, it’s an error to not pass one here.
- n_stepsint
Number of steps to forecast ahead. If X is supplied, it can be inferred from X.shape[0]. It is an error to pass inconsistent X and n_steps, i.e., n_steps must be equal to X.shape[0] when both are passed.
- return_intervalsbool, default=False
Whether to also calculate and return the prediction intervals. The procedure in https://otexts.com/fpp3/nnetar.html#prediction-intervals-5 is followed. If there is a single alpha provided in alphas, then a single-index column pd.DataFrame is returned with column labels “lower” and “upper”. If there is more than one alpha, a multi-index column frame is returned, e.g., with levels [80, 95] outside and [“lower”, “upper”] inside. The parameters below are ignored if return_intervals is False.
- n_pathsint, default=1_000
Number of paths to generate from the model for the forecast horizon for the prediction intervals. Ignored if return_intervals is False.
- alphasint, list-like of int, default=95
Percentage values in (0, 100) for the prediction intervals’ quantile calculation. Ignored if return_intervals is False.
- bootstrapbool, default=False
If True, the noises are sampled from the in-sample errors; otherwise, from a normal distribution following the mean & std of the in-sample errors. Ignored if return_intervals is False.
- return_pathsbool, default=False
Whether also return the simulated n_paths paths into the future. Ignored if return_intervals is False.
- Returns:
- forespd.Series or np.ndarray
Forecasts into the future. If the training y was a pandas Series, this is a pandas Series with an (hopefully) appropriate index; otherwise, it’s a NumPy array.
- intervalspd.DataFrame, optional
Prediction intervals as either a single-index column frame with labels “lower” and “upper” if one alpha, where the .name of the columns is {alpha}%; or a multi-index one if many alphas, where the levels are the alphas outside and “lower”, “upper” inside. If the training y was a pandas Series, the index of the frame is a continuation of that one (if possible); otherwise it has the default RangeIndex. Only provided if return_intervals is True.
- pathspd.DataFrame, optional
Generated future paths of shape n_steps x n_paths. Only provided if return_intervals is True.
Notes
If the in-sample predictions are wanted, i.e., the fitted values during training, it can be obtained via the post-fit attributes .fitted_values_ and fitted_values_all_, where the latter collects all of the internal repeats number of networks’ fitted values and the former is the mean of them.
-
classmethod validate(y, param_grid, X=None, base_model_cls=None, n_iter=-1, metric=
mean_squared_error> , cv=5, refit=True, random_state=None)¶ Perform time series cross validation with randomized (or full) grid search.
- Parameters:
- ypd.Series or np.ndarray
The training target series to perform the validation over.
- param_griddict or a list of dicts
Parameter combinations to try as either a dictionary, e.g., {“p”: [1, 2, 3], “estimator__solver”: [“adam”, “sgd”]} or a list of dictionaries, e.g., [{“p”: 1, “estimator__solver”: “adam”}, {…}]. Note that the base model’s parameters are passed with an “estimator__” prefix.
- Xpd.DataFrame, np.ndarray or None, optional
The accompanying exogenous variables for validation, if any.
- base_model_clsEstimator class, optional
Uninstantiated model class, e.g., MLPRegressor. Defaults to a single-layer MLP where the number of hidden neurons are chosen automatically, i.e., the default base model when ARNet() is called.
- n_iterint or None, default=-1
Either a positive integer to indicate the number of samples to randomly draw from param_grid, or one of {-1, None} to imply a full grid search.
- metriccallable, default=sklearn.metrics.mean_squared_error
The validation metric to determine the fold scores. It should adapt “lesser is better”.
- cvint or sklearn.model_selection.TimeSeriesSplit, default=5
Determines how the folds are constructed. If an integer, TimeSeriesSplit(n_splits=cv) is constructed. For a finer control, e.g., the test folds’ sizes, one can pass a custom TimeSeriesSplit here.
- refitbool, default=True
Whether to make available a “best” model out of the parameter combinations that performed the best. The model will be trained over the entire y (and X if available), and will be returned with the key “best_estimator_”.
- random_stateint or None, optional
The seed used for sampling configurations from param_grid if randomized search is opted for with a nonnegative n_iter. Seeds the stdlib’s random. By default, no reproducibility is aimed.
- Returns:
- search_resultsdict
- A dictionary with the keys
scores_: a dictionary of parameter-config (tuple) -> fold scores;
best_params_: a dictionary of parameter (str) -> value, which performed the best (“validated” parameters);
best_estimator_: an ARNet model that has best_params_ and trained over the entire y (and X). Only provided if refit is True.
- static plot(lines, labels=None, true_indexes=0, intervals=None, paths=None, figure_kwargs=None, figure=None, show=True)¶
Plot lines with either a plotly or a matplotlib backend. Might be useful for plotting true values with predictions as well as the prediction intervals and simulated paths.
- Parameters:
- lineslist-like of list-likes
List of series to plot.
- labelslist-like of str, optional
Corresponding labels (names) of the lines to appear on the legend.
- true_indexesint or list-like of ints or None, default=0
Indexes of the “true” values in the list lines, i.e., the location(s) of the target series. Used for marking the non-true series with dashes to distinguish them better from true values. Can pass None to make all lines appear sans dashes. Default is to assume 0th element of lines has a true series.
- intervalspd.DataFrame, optional
The prediction intervals obtained through .predict(…, return_intervals=True). If supplied, the intervals with the corresponding confidence levels are plotted as shaded areas with differing transparency.
- pathspd.DataFrame, optional
The simulated paths obtained through .predict(…, return_paths=True). If supplied, the generated future paths are plotted out. Expected to be of shape (n_steps, n_paths).
- figure_kwargsdict, optional
Configuration options for the figure displayed. If using plotly, passed to fig.update_layout; if matplotlib, passed to plt.setp.
- figureplotly.graph_objects.Figure or matplotlib.pyplot.figure, optional
Pre-prepared figure to perform the plotting on.
- showbool, default=True
Whether to show the painted figure immediately.
- Returns:
- figplotly.graph_objects.Figure or matplotlib.pyplot.figure, optional
The figure plotting happened on.
Notes
This function needs either plotly or matplotlib to be installed, and the libraries are tried in that order. If none of them is available, a RuntimeError is raised. If show is True (default), the figure is immediately displayed in addition to being returned. If using the matplotlib backend, plt.setp is not as encompassing as plotly’s .update_layout, so it might be better to set show=False, capture the return value (the figure), apply figure updates over plt/fig/fig.gca() and show manually with fig.show.