Skip to main content

A Python Package For System Identification Using NARMAX Models

Project description

DOI PyPI version License openissues issuesclosed downloads python status discord contributors stars

NARMAX Methods In The Time Domain

From Classical Approaches to Neural Networks

SysIdentPy offers State of the Art techniques to build your NARMAX models, including it's variants NARX, NARMA, NAR, NFIR, ARMAX, ARX, ARMA and others. It also includes tons of interesting examples to help you build nonlinear forecasting models using SysIdentPy.

What is SysIdentPy?

SysIdentPy is an open-source Python module for System Identification using NARMAX models built on top of numpy and is distributed under the 3-Clause BSD license. SysIdentPy provides an easy-to-use and flexible framework for building Dynamical Nonlinear Models for time series and dynamic systems.

Check our documentation!

How do I install SysIdentPy?

The easiest way to get SysIdentPy running is to install it using pip

pip install sysidentpy

Requirements

SysIdentPy requires:

  • Python (>= 3.7)
  • NumPy (>= 1.9.2) for all numerical algorithms
  • Matplotlib >= 3.3.2 for static plotting and visualizations
  • Pytorch (>=1.7.1) for building feed-forward neural networks
Platform Status
Linux ok
Windows ok
macOS ok

A few examples require pandas >= 0.18.0. However, it is not required to use SysIdentPy.

What are the main features of SysIdentPy?

Feature What is this?
NARMAX philosophy You can build variations of NARMAX models like NARX, NAR, NARMA, NFIR, ARMA, ARX, AR, and others.
Model Structure Selection Easy-to-use methods to select the best terms to build your models, including FROLS and MetaMSS and several combinations with parameter estimation techniques to select the model terms.
Basis Function You can use different basis functions to build your models. You can set linear and nonlinear basis functions and ensemble them to get custom NARMAX models.
Parameter Estimation More than 15 methods to estimate the model parameters and test different structure selection scenarios.
Multiobjective Parameter Estimation You can use affine information to estimate the model parameters minimizing different objective functions.
Model Simulation You can reproduce results from papers easily with SimulateNARMAX class. Moreover, you can test published models with different parameter estimation methods and compare the performance.
Neural NARX You can use SysIdentPy with Pytorch to create custom neural NARX models architectures which support all the optimizers and loss functions from Pytorch.
General Estimators You can use estimators from packages like scikit-learn, Catboost, and many other compatible interfaces and composition tools, to create NARMAX models.

Why does SysIdentPy exist?

SysIdentPy aims to be a free and open source package to help the community to design NARMAX models. More than that, be a free and robust alternative to one of the most used tools to build NARMAX models, which is the Matlab's System Identification Toolbox.

The project is actively maintained by Wilson R. L. Junior and looking for contributors.

How do I use sysIdentPy?

The SysIdentPy documentation includes more than 20 examples to help get you started:

  • Typical "Hello World" example, for an entry-level description of the main SysIdentPy concepts
  • A dedicated section focusing on SysIdentPy features, like model structure selection algorithms, basis functions, parameter estimation, and more.
  • A dedicated section focusing on use cases using SysIdentPy with real world datasets. Besides, there is some brief comparisons and benchmarks against other time series tools, like Prophet, Neural Prophet, ARIMA, and more.

Examples

from torch import nn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sysidentpy.metrics import root_relative_squared_error
from sysidentpy.utils.generate_data import get_siso_data


# Generate a dataset of a simulated dynamical system
x_train, x_valid, y_train, y_valid = get_siso_data(
  n=1000,
  colored_noise=False,
  sigma=0.001,
  train_percentage=80
)

Building Polynomial NARX models with FROLS algorithm

from sysidentpy.model_structure_selection import FROLS
from sysidentpy.basis_function import Polynomial
from sysidentpy.utils.display_results import results
from sysidentpy.utils.plotting import plot_residues_correlation, plot_results
from sysidentpy.residues.residues_correlation import compute_residues_autocorrelation
from sysidentpy.residues.residues_correlation import compute_cross_correlation

basis_function=Polynomial(degree=2)
model = FROLS(
  order_selection=True,
  n_info_values=10,
  extended_least_squares=False,
  ylag=2,
  xlag=2,
  info_criteria='aic',
  estimator='least_squares',
  basis_function=basis_function
)
model.fit(X=x_train, y=y_train)
yhat = model.predict(X=x_valid, y=y_valid)
rrse = root_relative_squared_error(y_valid, yhat)
print(rrse)
r = pd.DataFrame(
	results(
		model.final_model, model.theta, model.err,
		model.n_terms, err_precision=8, dtype='sci'
		),
	columns=['Regressors', 'Parameters', 'ERR'])
print(r)

Regressors     Parameters        ERR
0        x1(k-2)     0.9000  0.95556574
1         y(k-1)     0.1999  0.04107943
2  x1(k-1)y(k-1)     0.1000  0.00335113

plot_results(y=y_valid, yhat=yhat, n=1000)
ee = compute_residues_autocorrelation(y_valid, yhat)
plot_residues_correlation(data=ee, title="Residues", ylabel="$e^2$")
x1e = compute_cross_correlation(y_valid, yhat, x2_val)
plot_residues_correlation(data=x1e, title="Residues", ylabel="$x_1e$")

polynomial

NARX Neural Network

from sysidentpy.neural_network import NARXNN
from sysidentpy.basis_function import Polynomial
from sysidentpy.utils.plotting import plot_residues_correlation, plot_results
from sysidentpy.residues.residues_correlation import compute_residues_autocorrelation
from sysidentpy.residues.residues_correlation import compute_cross_correlation

class NARX(nn.Module):
    def __init__(self):
        super().__init__()
        self.lin = nn.Linear(4, 10)
        self.lin2 = nn.Linear(10, 10)
        self.lin3 = nn.Linear(10, 1)
        self.tanh = nn.Tanh()

    def forward(self, xb):
        z = self.lin(xb)
        z = self.tanh(z)
        z = self.lin2(z)
        z = self.tanh(z)
        z = self.lin3(z)
        return z

basis_function=Polynomial(degree=1)

narx_net = NARXNN(
  net=NARX(),
  ylag=2,
  xlag=2,
  basis_function=basis_function,
  model_type="NARMAX",
  loss_func='mse_loss',
  optimizer='Adam',
  epochs=200,
  verbose=False,
  optim_params={'betas': (0.9, 0.999), 'eps': 1e-05} # optional parameters of the optimizer
)

narx_net.fit(X=x_train, y=y_train)
yhat = narx_net.predict(X=x_valid, y=y_valid)
plot_results(y=y_valid, yhat=yhat, n=1000)
ee = compute_residues_autocorrelation(y_valid, yhat)
plot_residues_correlation(data=ee, title="Residues", ylabel="$e^2$")
x1e = compute_cross_correlation(y_valid, yhat, x_valid)
plot_residues_correlation(data=x1e, title="Residues", ylabel="$x_1e$")

neural

Catboost-narx

from catboost import CatBoostRegressor
from sysidentpy.general_estimators import NARX
from sysidentpy.basis_function import Polynomial
from sysidentpy.utils.plotting import plot_residues_correlation, plot_results
from sysidentpy.residues.residues_correlation import compute_residues_autocorrelation
from sysidentpy.residues.residues_correlation import compute_cross_correlation


basis_function=Polynomial(degree=1)

catboost_narx = NARX(
  base_estimator=CatBoostRegressor(
    iterations=300,
    learning_rate=0.1,
    depth=6),
  xlag=2,
  ylag=2,
  basis_function=basis_function,
  fit_params={'verbose': False}
)

catboost_narx.fit(X=x_train, y=y_train)
yhat = catboost_narx.predict(X=x_valid, y=y_valid)
plot_results(y=y_valid, yhat=yhat, n=1000)
ee = compute_residues_autocorrelation(y_valid, yhat)
plot_residues_correlation(data=ee, title="Residues", ylabel="$e^2$")
x1e = compute_cross_correlation(y_valid, yhat, x_valid)
plot_residues_correlation(data=x1e, title="Residues", ylabel="$x_1e$")

catboost

Catboost without NARX configuration

The following is the Catboost performance without the NARX configuration.

def plot_results_tmp(y_valid, yhat):
    _, ax = plt.subplots(figsize=(14, 8))
    ax.plot(y_valid[:200], label='Data', marker='o')
    ax.plot(yhat[:200], label='Prediction', marker='*')
    ax.set_xlabel("$n$", fontsize=18)
    ax.set_ylabel("$y[n]$", fontsize=18)
    ax.grid()
    ax.legend(fontsize=18)
    plt.show()

catboost = CatBoostRegressor(
  iterations=300,
  learning_rate=0.1,
  depth=6
)
catboost.fit(x_train, y_train, verbose=False)
plot_results_tmp(y_valid, catboost.predict(x_valid))

catboost

The examples directory has several Jupyter notebooks with tutorials of how to use the package and some specific applications of sysidentpy. Try it out!

Communication

Citation

DOI

If you use SysIdentPy on your project, please drop me a line.

If you use SysIdentPy on your scientific publication, we would appreciate citations to the following paper:

  • Lacerda et al., (2020). SysIdentPy: A Python package for System Identification using NARMAX models. Journal of Open Source Software, 5(54), 2384, https://doi.org/10.21105/joss.02384
@article{Lacerda2020,
  doi = {10.21105/joss.02384},
  url = {https://doi.org/10.21105/joss.02384},
  year = {2020},
  publisher = {The Open Journal},
  volume = {5},
  number = {54},
  pages = {2384},
  author = {Wilson Rocha Lacerda Junior and Luan Pascoal Costa da Andrade and Samuel Carlos Pessoa Oliveira and Samir Angelo Milani Martins},
  title = {SysIdentPy: A Python package for System Identification using NARMAX models},
  journal = {Journal of Open Source Software}
}

Inspiration

The documentation and structure (even this section) is openly inspired by sklearn, einsteinpy, and many others as we used (and keep using) them to learn.

Contributors

Sponsors

Special thanks to our sponsors


Gold Sponsors

Technium

Individual Sponsors

Nath Keles

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sysidentpy-0.3.4.tar.gz (48.5 MB view details)

Uploaded Source

Built Distribution

sysidentpy-0.3.4-py3-none-any.whl (109.7 kB view details)

Uploaded Python 3

File details

Details for the file sysidentpy-0.3.4.tar.gz.

File metadata

  • Download URL: sysidentpy-0.3.4.tar.gz
  • Upload date:
  • Size: 48.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.9

File hashes

Hashes for sysidentpy-0.3.4.tar.gz
Algorithm Hash digest
SHA256 498abc6fde6431961e100daa4ef4ded736332181e07041ad62e6e86328b8d453
MD5 e17122106a29fb29b2f13021ea7e955f
BLAKE2b-256 4f1edc22fca88e4dc0b8cb1a4c1b623e4db5e8ffd0fb8f9668189d9a1189fc15

See more details on using hashes here.

File details

Details for the file sysidentpy-0.3.4-py3-none-any.whl.

File metadata

  • Download URL: sysidentpy-0.3.4-py3-none-any.whl
  • Upload date:
  • Size: 109.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.9

File hashes

Hashes for sysidentpy-0.3.4-py3-none-any.whl
Algorithm Hash digest
SHA256 930968eeeccc63a181b1e7f54ed5990658c3c1862a219b87555cd0d83dd12de7
MD5 cce9349a076305327965cfaae18e0753
BLAKE2b-256 22c55fc87b888a0bcf852c4aa4f8c0d841925d26d3439dd09c5330c5fa43ed68

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page