Information Criteria - Examples

Example created by Wilson Rocha Lacerda Junior

Comparing different information criteria methods

Here we import the NARMAX model, the metric for model evaluation and the methods to generate sample data for tests. Also, we import pandas for specific usage.

pip install sysidentpy
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sysidentpy.polynomial_basis import PolynomialNarmax
from sysidentpy.metrics import root_relative_squared_error
from sysidentpy.utils.generate_data import get_miso_data, get_siso_data

Generating sample data

The data is generated by simulating the following model: \(y_k = 0.2y_{k-1} + 0.1y_{k-1}x_{k-1} + 0.9x_{k-1} + e_{k}\)

If colored_noise is set to True:

\(e_{k} = 0.8\nu_{k-1} + \nu_{k}\)

where \(x\) is a uniformly distributed random variable and \(\nu\) is a gaussian distributed variable with \(\mu=0\) and \(\sigma=0.1\)

In the next example we will generate a data with 3000 samples with white noise and selecting 90% of the data to train the model.

x_train, x_valid, y_train, y_valid = get_siso_data(n=1000,
                                                   colored_noise=False,
                                                   sigma=0.2,
                                                   train_percentage=90)

The idea is to show the impact of the information criteria to select the number of terms to compose the final model. You will se why it is an auxiliary tool and let the algorithm select the number of terms based on the minimum value is not a good idea when dealing with data highly corrupted by noise (even white noise)

Note: You may find different results when running the examples. This is due the fact we are not setting a fixed random generator for the sample data. However, the main analysis remain.

AIC

model = PolynomialNarmax(non_degree=2,
                         order_selection=True,
                         n_info_values=15,
                         extended_least_squares=False,
                         ylag=2, xlag=2,
                         info_criteria='aic',
                         estimator='least_squares',
                         )

model.fit(x_train, y_train)
yhat = model.predict(x_valid, y_valid)
rrse = root_relative_squared_error(y_valid, yhat)
print(rrse)

results = pd.DataFrame(model.results(err_precision=8,
                                     dtype='dec'),
                       columns=['Regressors', 'Parameters', 'ERR'])

print(results)

xaxis = np.arange(1, model.n_info_values + 1)
plt.plot(xaxis, model.info_values)
plt.xlabel('n_terms')
plt.ylabel('Information Criteria')
0.38202463734760717
      Regressors Parameters         ERR
0        x1(k-2)     0.9210  0.84287328
1         y(k-1)     0.1867  0.03532986
2  x1(k-1)y(k-1)     0.1215  0.00403228
3       y(k-1)^2     0.0478  0.00073353
4      x1(k-1)^2    -0.0342  0.00052802
Text(0, 0.5, 'Information Criteria')
../_images/information_criteria_examples_10_2.svg
model.info_values
array([-2694.09936284, -2920.43235501, -2948.99729043, -2951.5656718 ,
       -2953.60017972, -2952.10447799, -2950.4899516 , -2948.64474158,
       -2946.7871786 , -2944.89120846, -2942.95165921, -2940.98557817,
       -2939.02706707, -2937.03646143, -2935.03708992])

As can be seen above, the minimum value make the algorithm choose a model with 5 terms. However, if you check the plot, 3 terms is the best choice. Incresase the number of terms from 3 upwards do not lead to a better model since the difference is very small.

In this case, you should run the model again with the parameters n_terms=3! The ERR algorithm ordered the terms in a correct way, so you will get the exact model structure again!

BIC

model = PolynomialNarmax(non_degree=2,
                         order_selection=True,
                         n_info_values=15,
                         extended_least_squares=False,
                         ylag=2, xlag=2,
                         info_criteria='bic',
                         estimator='least_squares',
                         )

model.fit(x_train, y_train)
yhat = model.predict(x_valid, y_valid)
rrse = root_relative_squared_error(y_valid, yhat)
print(rrse)

results = pd.DataFrame(model.results(err_precision=8,
                                     dtype='dec'),
                       columns=['Regressors', 'Parameters', 'ERR'])

print(results)

xaxis = np.arange(1, model.n_info_values + 1)
plt.plot(xaxis, model.info_values)
plt.xlabel('n_terms')
plt.ylabel('Information Criteria')
0.38121187399853695
      Regressors Parameters         ERR
0        x1(k-2)     0.9235  0.84287328
1         y(k-1)     0.1864  0.03532986
2  x1(k-1)y(k-1)     0.1188  0.00403228
Text(0, 0.5, 'Information Criteria')
../_images/information_criteria_examples_14_2.svg
model.info_values
array([-2689.29919277, -2910.83201488, -2934.59678022, -2932.36499152,
       -2929.59932938, -2923.30345758, -2916.88876112, -2910.24338103,
       -2903.58564799, -2896.88950777, -2890.14978846, -2883.38353735,
       -2876.62485618, -2869.83408047, -2863.03453889])

BIC did a better job in this case! The way it penalizes the model regarding the number of terms ensure that the minimum value here was exact the number of expected terms to compose the model. Good, but not aways the best method!

LILC

model = PolynomialNarmax(non_degree=2,
                         order_selection=True,
                         n_info_values=15,
                         extended_least_squares=False,
                         ylag=2, xlag=2,
                         info_criteria='lilc',
                         estimator='least_squares',
                         )

model.fit(x_train, y_train)
yhat = model.predict(x_valid, y_valid)
rrse = root_relative_squared_error(y_valid, yhat)
print(rrse)

results = pd.DataFrame(model.results(err_precision=8,
                                     dtype='dec'),
                       columns=['Regressors', 'Parameters', 'ERR'])

print(results)

xaxis = np.arange(1, model.n_info_values + 1)
plt.plot(xaxis, model.info_values)
plt.xlabel('n_terms')
plt.ylabel('Information Criteria')
0.38202463734760717
      Regressors Parameters         ERR
0        x1(k-2)     0.9210  0.84287328
1         y(k-1)     0.1867  0.03532986
2  x1(k-1)y(k-1)     0.1215  0.00403228
3       y(k-1)^2     0.0478  0.00073353
4      x1(k-1)^2    -0.0342  0.00052802
Text(0, 0.5, 'Information Criteria')
../_images/information_criteria_examples_18_2.svg
model.info_values

LILC also includes spurious terms. Like AIC, it fails to automatically select the correct terms but you could select the right number based on the plot above!

FPE

model = PolynomialNarmax(non_degree=2,
                         order_selection=True,
                         n_info_values=15,
                         extended_least_squares=False,
                         ylag=2, xlag=2,
                         info_criteria='fpe',
                         estimator='least_squares',
                         )

model.fit(x_train, y_train)
yhat = model.predict(x_valid, y_valid)
rrse = root_relative_squared_error(y_valid, yhat)
print(rrse)

results = pd.DataFrame(model.results(err_precision=8,
                                     dtype='dec'),
                       columns=['Regressors', 'Parameters', 'ERR'])

print(results)

xaxis = np.arange(1, model.n_info_values + 1)
plt.plot(xaxis, model.info_values)
plt.xlabel('n_terms')
plt.ylabel('Information Criteria')
0.38202463734760717
      Regressors Parameters         ERR
0        x1(k-2)     0.9210  0.84287328
1         y(k-1)     0.1867  0.03532986
2  x1(k-1)y(k-1)     0.1215  0.00403228
3       y(k-1)^2     0.0478  0.00073353
4      x1(k-1)^2    -0.0342  0.00052802
Text(0, 0.5, 'Information Criteria')
../_images/information_criteria_examples_22_2.svg
model.info_values
array([-2694.09936201, -2920.4323484 , -2948.99726811, -2951.56561889,
       -2953.60007638, -2952.10429942, -2950.48966802, -2948.64431828,
       -2946.78657589, -2944.89038168, -2942.95055875, -2940.98414946,
       -2939.02525054, -2937.03419259, -2935.03429929])

FPE also failed to automatically select the right number of terms! But, as we pointed out before, Information Criteria is an auxiliary tool! If you look at the plots, all the methods allows you to choose the right numbers of terms!

Importante Note

Here we are dealing with a known model structure! Concerning real data, we do not know the rigth number of terms so the methods above stands as excelents tools to help you out!

If you check the metrics above, even with the models with more terms, you will see excelents metrics! But System Identification always search for the best model structure! Model Structure Selection is the core of NARMAX methods! In this respect, the examples are to show basic concepts and how the algorithms work!