Simular Modelos Existentes¶
Exemplo criado por Wilson Rocha Lacerda Junior
Procurando mais detalhes sobre modelos NARMAX? Para informações completas sobre modelos, métodos e uma ampla variedade de exemplos e benchmarks implementados no SysIdentPy, confira nosso livro: Nonlinear System Identification and Forecasting: Theory and Practice With SysIdentPy
Este livro oferece orientação aprofundada para apoiar seu trabalho com o SysIdentPy.
import numpy as np
import pandas as pd
from sysidentpy.simulation import SimulateNARMAX
from sysidentpy.metrics import root_relative_squared_error
from sysidentpy.utils.generate_data import get_siso_data
from sysidentpy.basis_function import Polynomial
from sysidentpy.parameter_estimation import LeastSquares
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,
compute_cross_correlation,
)
Gerando dados de amostra com 1 entrada e 1 saída¶
Os dados são gerados simulando o seguinte modelo:¶
\(y_k = 0.2y_{k-1} + 0.1y_{k-1}x_{k-1} + 0.9x_{k-2} + e_{k}\)
Se colored_noise for definido como True:
\(e_{k} = 0.8\nu_{k-1} + \nu_{k}\)
onde \(x\) é uma variável aleatória uniformemente distribuída e \(\nu\) é uma variável com distribuição gaussiana com \(\mu=0\) e \(\sigma=0.1\)
No próximo exemplo, geraremos dados com 1000 amostras com ruído branco e selecionando 90% dos dados para treinar o modelo.
x_train, x_test, y_train, y_test = get_siso_data(
n=1000, colored_noise=False, sigma=0.001, train_percentage=90
)
Definindo o modelo¶
Já sabemos que os dados gerados são resultado do modelo \(𝑦_𝑘=0.2𝑦_{𝑘−1}+0.1𝑦_{𝑘−1}𝑥_{𝑘−1}+0.9𝑥_{𝑘−2}+𝑒_𝑘\). Assim, podemos criar um modelo com esses regressores seguindo um padrão de codificação: - \(0\) é o termo constante, - \([1001] = y_{k-1}\) - \([100n] = y_{k-n}\) - \([200n] = x1_{k-n}\) - \([300n] = x2_{k-n}\) - \([1011, 1001] = y_{k-11} \times y_{k-1}\) - \([100n, 100m] = y_{k-n} \times y_{k-m}\) - \([12001, 1003, 1001] = x11_{k-1} \times y_{k-3} \times y_{k-1}\) - e assim por diante
Nota Importante¶
A ordem dos arrays importa.
Se você usar [2001, 1001], funcionará, mas [1001, 2001] não (o regressor será ignorado). Sempre coloque o maior valor primeiro: - \([2003, 2001]\) funciona - \([2001, 2003]\) não funciona
Trataremos esta limitação em uma atualização futura.
s = SimulateNARMAX(
basis_function=Polynomial(), calculate_err=True, estimate_parameter=False
)
# the model must be a numpy array
model = np.array(
[
[1001, 0], # y(k-1)
[2001, 1001], # x1(k-1)y(k-1)
[2002, 0], # x1(k-2)
]
)
# theta must be a numpy array of shape (n, 1) where n is the number of regressors
theta = np.array([[0.2, 0.9, 0.1]]).T
Simulando o modelo¶
Após definir o modelo e theta, só precisamos usar o método simulate.
O método simulate retorna os valores preditos e os resultados onde podemos visualizar os regressores, parâmetros e valores de ERR.
yhat = s.simulate(
X_test=x_test,
y_test=y_test,
model_code=model,
theta=theta,
)
r = pd.DataFrame(
results(s.final_model, s.theta, s.err, s.n_terms, err_precision=8, dtype="sci"),
columns=["Regressors", "Parameters", "ERR"],
)
print(r)
plot_results(y=y_test, yhat=yhat, n=1000)
ee = compute_residues_autocorrelation(y_test, yhat)
plot_residues_correlation(data=ee, title="Residues", ylabel="$e^2$")
x1e = compute_cross_correlation(y_test, yhat, x_test)
plot_residues_correlation(data=x1e, title="Residues", ylabel="$x_1e$")
Regressors Parameters ERR
0 y(k-1) 2.0000E-01 0.00000000E+00
1 x1(k-2) 9.0000E-01 0.00000000E+00
2 x1(k-1)y(k-1) 1.0000E-01 0.00000000E+00
Opções¶
Você pode definir o steps_ahead para executar a predição/simulação:
yhat = s.simulate(
X_test=x_test,
y_test=y_test,
model_code=model,
theta=theta,
steps_ahead=1,
)
rrse = root_relative_squared_error(y_test, yhat)
print(rrse)
0.001980394341423956
yhat = s.simulate(
X_test=x_test,
y_test=y_test,
model_code=model,
theta=theta,
steps_ahead=21,
)
rrse = root_relative_squared_error(y_test, yhat)
print(rrse)
0.0019394741034286557
Estimando os parâmetros¶
Se você tiver apenas a estrutura do modelo, pode criar um objeto com estimate_parameter=True e escolher o método de estimação usando estimator. Neste caso, você precisa passar os dados de treinamento para estimação dos parâmetros.
Quando estimate_parameter=True, também calculamos o ERR considerando apenas os regressores definidos pelo usuário.
s = SimulateNARMAX(
basis_function=Polynomial(),
estimate_parameter=True,
estimator=LeastSquares(),
calculate_err=True,
)
yhat = s.simulate(
X_train=x_train,
y_train=y_train,
X_test=x_test,
y_test=y_test,
model_code=model,
# theta will be estimated using the defined estimator
)
r = pd.DataFrame(
results(s.final_model, s.theta, s.err, s.n_terms, err_precision=8, dtype="sci"),
columns=["Regressors", "Parameters", "ERR"],
)
print(r)
plot_results(y=y_test, yhat=yhat, n=1000)
ee = compute_residues_autocorrelation(y_test, yhat)
plot_residues_correlation(data=ee, title="Residues", ylabel="$e^2$")
x1e = compute_cross_correlation(y_test, yhat, x_test)
plot_residues_correlation(data=x1e, title="Residues", ylabel="$x_1e$")
Regressors Parameters ERR
0 y(k-1) 1.9999E-01 9.57682046E-01
1 x1(k-2) 9.0003E-01 3.87716434E-02
2 x1(k-1)y(k-1) 1.0009E-01 3.54306118E-03





