2

I have created an ARX model using sysid function, and now I want to extrapolate this model for other inputs.

I firstly created this model and identified its parameters for a training subset of data.

m = GEKKO(remote=False)
na = n_a
nb = n_b
yp_train, p, K = m.sysid(t_train, u_train, y_train, na, nb)

Having this model fit is there any way i can use the same parameters and utilize them with different inputs ?

Here is what i was going for

def arxouriço2(df, inputs, outputs, n_a, n_b, train_slice=None, test_slice=None):
    datafreime_arx = df.copy()
    if isinstance(inputs, pd.Series):
        inputs = pd.DataFrame(inputs)
    if isinstance(outputs, pd.Series):
        outputs = pd.DataFrame(outputs)
    colunas_arx = list(inputs.columns) + list(outputs.columns)
    mean_col = []
    std_dev_col = []

    for i in colunas_arx:
        mean = np.nanmean(datafreime_arx[i])
        mean_col.append(mean)
        datafreime_arx[i] -= mean

        std_dev = np.nanstd(datafreime_arx[i])
        std_dev_col.append(std_dev)
        datafreime_arx[i] /= std_dev

    if train_slice is not None:
        train_data = datafreime_arx.iloc[train_slice]
        t_train = train_data['Tempo']
        u_train = inputs.iloc[train_slice]
        y_train = outputs.iloc[train_slice]
    else:
        t_train = datafreime_arx['Tempo']
        u_train = inputs
        y_train = outputs

    if test_slice is not None:
        test_data = datafreime_arx.iloc[test_slice]
        t_test = test_data['Tempo']
        u_test = inputs.iloc[test_slice]
        y_test = outputs.iloc[test_slice]
    else:
        t_test = datafreime_arx['Tempo']
        u_test = inputs
        y_test = outputs

    m = GEKKO(remote=False)
    na = n_a
    nb = n_b
    yp_train, p, K = m.sysid(t_train, u_train, y_train, na, nb)

    for i, col in enumerate(colunas_arx):
        datafreime_arx[col] /= std_dev_col[i]
        datafreime_arx[col] -= mean_col[i]

    resis = y_train - yp_train
    resis2 = resis ** 2
    print('Sum of squared residuals: ' + str(np.sum(resis2)))

    if test_slice is not None:
        yp_test = m.sysid(t_test, u_test, y_test, na, nb)[0]
        plt.figure(figsize=(8, 5))
        plt.subplot(2, 1, 1)
        plt.plot(t_train, u_train)
        plt.legend(inputs.columns)
        plt.ylabel('Temperature (ºC)')
        plt.subplot(2, 1, 2)
        plt.plot(t_test, y_test, label=outputs.columns)
        plt.plot(t_test, yp_test, label=outputs.columns + ' predicted')
        plt.legend()
        plt.ylabel('Rotation (º)')
        plt.xlabel('Time')
        plt.tight_layout()
        plt.show()

    return p, K, m

arxouriço2(df_c3_avg5_c2,df_c3_avg5_c2[['STH3_avg','STH-04']],df_c3_avg5_c2['C14-Y'],10,10,range(465, 829),range(829, 903))

1 Answer 1

1

Use the m.arx() function to create a model for predictions. The m.sysid() function is to determine the parameters p of an ARX model. The m.arx() function uses p parameters to create predictions. Here is an example with data:

Fit ARX with sysid

ARX Fit

from gekko import GEKKO
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# load data and parse into columns
url = 'http://apmonitor.com/pdc/uploads/Main/'
data = pd.read_csv(url+'tclab_data3.txt')
t = data['Time']
u = data['Q1']
y = data['T1']

# generate time-series model
m = GEKKO(remote=False)

# system identification
na = 2 # output coefficients
nb = 2 # input coefficients
yp,p,K = m.sysid(t,u,y,na,nb,pred='meas')

plt.figure(figsize=(10,6))
plt.subplot(2,1,1)
plt.plot(t,u)
plt.legend([r'$Q_1$ (%)'])
plt.ylabel('MV Heater (%)')
plt.subplot(2,1,2)
plt.plot(t,y,'b-',label=r'$T_{1,meas}$')
plt.plot(t,yp,'r--',label=r'$T_{1,pred}$')
plt.legend(); plt.ylabel('CV Temp (°C)')
plt.xlabel('Time (sec)')

Predictions with ARX model using arx function

ARX Predictions

# load test data
data = pd.read_csv(url+'tclab_data4.txt')
t = data['Time']
um = data['Q1']
ym = data['T1']

# generate time-series model
m = GEKKO(remote=False)

# Build GEKKO ARX model
y,u = m.arx(p)
y[0].value = ym[0]

# load inputs
m.time = t
u[0].value = um

# options
m.options.imode = 4
m.options.nodes = 2

# simulate
m.solve(disp=False)

plt.figure(figsize=(10,6))
plt.subplot(2,1,1)
plt.plot(t,u[0])
plt.legend([r'$Q_1$ (%)'])
plt.ylabel('MV Heater (%)')
plt.subplot(2,1,2)
plt.plot(t,ym,'b-',label=r'$T_{1,meas}$')
plt.plot(t,y[0],'r--',label=r'$T_{1,pred}$')
plt.legend(); plt.ylabel('CV Temp (°C)')
plt.xlabel('Time (sec)')

For your function, modify this section of code:

if test_slice is not None:
    yp_test = m.sysid(t_test, u_test, y_test, na, nb)[0]

To something like this:

if test_slice is not None:
    mt = GEKKO(remote=False)
    y,u = mt.arx(p)
    mt.time = t_test
    y[0].value = y_test[0] # initial condition
    u[0].value = u_test
    mt.options.IMODE = 4
    mt.options.NODES = 2
    mt.solve(disp=False)
    yp_test = y[0].value
Sign up to request clarification or add additional context in comments.

2 Comments

Firstly thank you for the answer. I have two questions. 1. When I was first trying to fit a model I was able to use two columns as inputs and it worked fine, but now I can't. 2. The results I'm getting fitting the model are strange. The peaks are inverted and when solving the model for the testing subset there's a big descending stem in the begging that from my seeing doesn't make much sense. The testing subset starts right after the ending of the training one. imgur.com/a/0aq1Wqm
Could you create a new question with complete code and data so that we can reproduce it? What version of gekko are you using? You can determine the version with “pip list”

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.