GEKKO NL Solver gives fitting values that are not corresponding to the reference values

Viewed 24

I'm trying to find the parameters values for best fitting of the follow model function with a given set of points.

Model:
                 x
  y = ------------------------
       1- (a1*x)^2 + (a2*x)^4

where parameters are:  a1, a2 

(1) I used the found optimized parameters values with this equation but it gives around y=~0 for any x (red graph).

enter image description here

(3) Surprisingly, using a model with only one parameter as follow gives much better fitting.

Model:
            x
  y = -------------
       1- (a1*x)^2

where parameters are:  a1 

enter image description here

Here is my code (I followed the code for non linear regression as shown here: https://github.com/BYU-PRISM/GEKKO/blob/master/docs/examples.rst)

Note: I played with initial values until got one where the solver didn't fire exception of "Non Solution Found". The values I used are 0.3 for each parameter (I have no idea why this is a good value if at all)

Measure points file can be downloaded from here: https://www.dropbox.com/s/ai5vbd2u5gx8r17/measure.npy?dl=0

import numpy as np
import math
import os.path

import matplotlib.pyplot as plt
from gekko import GEKKO

# Model:
#                x
# y = ------------------------
#      1- (a1*x)^2 + (a2*x)^4
#

# measured data (file exist at https://www.dropbox.com/s/ai5vbd2u5gx8r17/measure.npy?dl=0)
measure_data = np.load("C:/measure.npy")
xm = measure_data[0]
ym = measure_data[1]

# GEKKO model
m = GEKKO()

# parameters
x = m.Param(value=xm)
a = [m.FV(value=0.3) for i in range(2)]
for par in a:
    par.STATUS=1

# variables
y = m.CV(value=ym)
y.FSTATUS=1

m.Equation( y==x/(1-(a[0]*x)**2+(a[1]*x)**4) )
    
# regression mode
m.options.IMODE = 2

# optimize
m.solve(disp=False)


p = [par.value[0] for par in a] 
optimized_y = xm/(1-(p[0]*xm)**2+(p[1]*xm)**4)


plt.figure(1)

plt.plot(xm,ym,'k', label = "measurements")
plt.plot(xm,optimized_y,'r', label = "optimized_y")

plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
1 Answers

Similar to the suggestions from GEKKO NL solver failed with initial guess of 0, try rearranging the equation to avoid divide-by-zero. An intermediate variable definition (z) can help simplify the expression.

z = m.Intermediate(1-(a[0]*x)**2)
m.Equation(y*z==x + z*(a[1]*x)**4)

Another thing that can help is to define the parameters to reduce the nonlinearity of the problem:

z = m.Intermediate(1-b[0]*(x**2))
m.Equation(y*z==x + b[1]*z*(x**4))

After the problem finishes solving, compute the original values of the a parameters as a[0]=math.sqrt(b[0].value[0]) and a[1]=(b[1].value[0])**(1/4).

It may also be helpful to try a different solver such as m.options.SOLVER=1 (APOPT solver). Nonlinear optimization problems sometimes need a good initial guess or bounds, especially when there are terms such as power of 4. For future questions, please post sample data that reproduces the problem.

Related