3
votes

I am trying to create a Neural Network to predict the behavior of variable "miu".

Since I only have 6 data points, I tried to use spline to find more points that follow the behavior of the system to afterwards use all those points in the neural network.

I am trying to use 2 inputs, which are time and cell concentration. And the expected output would be the miu value, which is given as the derivative dy/dx where y is the cell concentration and x the time.

I implemented the following code:

from gekko import brain
import numpy as np
import matplotlib.pyplot as plt  
from numpy import diff
from scipy.interpolate import CubicSpline
xm = np.array([ 0.0 , 23.0 , 47.0 , 49.0 ,\
                71.5 , 95.0 , 119.0 , 143.0 ])

def spline(cell):    
    m = GEKKO()
    m.options.IMODE=2
    c = [m.FV(value=0) for i in range(4)]
    x = m.Param(value=xm)
    cell = np.array(cell)
    y = m.CV(value=cell)
    y.FSTATUS = 1
    # polynomial model
    m.Equation(y==c[0]+c[1]*x+c[2]*x**2+c[3]*x**3)
    c[0].STATUS=1
    m.solve(disp=False)
    c[1].STATUS=1
    m.solve(disp=False)
    c[2].STATUS=1
    c[3].STATUS=1
    m.solve(disp=False)
    pbr = [c[3].value[0],c[2].value[0],\
           c[1].value[0],c[0].value[0]]
    print(pbr)
    xp = np.linspace(0,144,100)
    plot1 = plt.figure(1)
    if cell[0] == cell_br2[0]:
        plt.plot(xm,cell_br2, 'ko', label ='BR2')
        plt.plot(xp,np.polyval(pbr,xp),'g:',linewidth=2)
    elif cell[0]  == cell_br1[0] :
        plt.plot(xm,cell_br1, 'mo', label ='BR1')
        plt.plot(xp,np.polyval(pbr,xp),'r:',linewidth=2)

    plt.xlabel('time(hr)')
    plt.ylabel('cells')
    plt.legend()
    dx = diff(xp)
    dy1 = diff(np.polyval(pbr,xp))
    deriv1 = dy1/dx
    time =np.linspace(0,144,99)
    plot1 = plt.figure(2)
    if cell[0] == cell_br2[0]:
        plt.plot(time,deriv1,'b:',linewidth=2, label ='BR2')
    elif cell[0] == cell_br1[0]:
        plt.plot(time,deriv1,'m:',linewidth=2, label ='BR1')
    plt.xlabel('time(hr)')
    plt.ylabel('miu(1/h)')
    plt.legend()
    plt.show()
    return(deriv1)
    
m = GEKKO()
cell_br1 = (0.63*10**6 , 1.10*10**6, 2.06*10**6, 2.08*10**6,\
            3.73*10**6, 3.89*10**6, 3.47*10**6,2.312*10**6)
cell_br2=  (0.58*10**6 , 0.96*10**6, 2.07*10**6, 1.79*10**6,\
            3.57*10**6, 3.34*10**6, 2.62*10**6, 1.75*10**6)

b = brain.Brain()
b.input_layer(2)
b.layer(linear=5)
b.layer(tanh=5)
b.layer(linear=5)
b.output_layer(1)

x_s = np.linspace(0,144,99)
xg = np.array([ 0.0 , 23.0 , 47.0 , 49.0 , 71.5 ,\
                95.0 , 119.0 , 144.0 ])
cells_spline = CubicSpline(xm, cell_br1) 
y_cells = cells_spline(x_s)
miu_1 = spline(cell_br1)
miu_2 = spline(cell_br2)
x = (x_s, y_cells)#, y_glucose) #Inputs (3)
y = (miu_1)    #Output (2)

b.learn(x,y) # train
xp = np.linspace(0,144,99)
yp = b.think(x) # validate
yyp = np.array(yp)
miu = np.reshape(yyp, (99,))

plot1 = plt.figure(3)
plt.plot(xp,miu,'r-', label = 'Predicted ')
plt.plot(x_s,miu_1,'bo', label = 'Experimental points')
plt.xlabel('Time [hr]')
plt.ylabel('miu [1/h]')
plt.legend()
plt.show()

Although solver finds a solution, it is constant, which indicated that the solver is not working. My output is the following : enter image description here

enter image description here

Can someone please help? I can't find what is failing. Thanks

1
Could you post the Experimental_Data module that you import? I can't reproduce the issue without it. - John Hedengren
Sorry, I updated the code and the data that is imported in that module is already posted - Cláudia Bento

1 Answers

1
votes

Here are a couple issues with your current approach:

  • The training uses two inputs while the validation uses only one input
  • The data is not scaled. It generally helps if you scale the data to -1 to 1. I included a simple scalar but there are better ways to do this that also zero-center the data.

Neural Network Results

from gekko import brain
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt  
from numpy import diff
from scipy.interpolate import CubicSpline
xm = np.array([ 0.0 , 23.0 , 47.0 , 49.0 ,\
                71.5 , 95.0 , 119.0 , 143.0 ])

def spline(cell):    
    m = GEKKO()
    m.options.IMODE=2
    c = [m.FV(value=0) for i in range(4)]
    x = m.Param(value=xm)
    cell = np.array(cell)
    y = m.CV(value=cell)
    y.FSTATUS = 1
    # polynomial model
    m.Equation(y==c[0]+c[1]*x+c[2]*x**2+c[3]*x**3)
    c[0].STATUS=1
    m.solve(disp=False)
    c[1].STATUS=1
    m.solve(disp=False)
    c[2].STATUS=1
    c[3].STATUS=1
    m.solve(disp=False)
    pbr = [c[3].value[0],c[2].value[0],\
           c[1].value[0],c[0].value[0]]
    print(pbr)
    xp = np.linspace(0,144,100)
    plot1 = plt.figure(1)
    if cell[0] == cell_br2[0]:
        plt.plot(xm,cell_br2, 'ko', label ='BR2')
        plt.plot(xp,np.polyval(pbr,xp),'g:',linewidth=2)
    elif cell[0]  == cell_br1[0] :
        plt.plot(xm,cell_br1, 'mo', label ='BR1')
        plt.plot(xp,np.polyval(pbr,xp),'r:',linewidth=2)

    plt.xlabel('time(hr)')
    plt.ylabel('cells')
    plt.legend()
    dx = diff(xp)
    dy1 = diff(np.polyval(pbr,xp))
    deriv1 = dy1/dx
    time =np.linspace(0,144,99)
    plot1 = plt.figure(2)
    if cell[0] == cell_br2[0]:
        plt.plot(time,deriv1,'b:',linewidth=2, label ='BR2')
    elif cell[0] == cell_br1[0]:
        plt.plot(time,deriv1,'m:',linewidth=2, label ='BR1')
    plt.xlabel('time(hr)')
    plt.ylabel('miu(1/h)')
    plt.legend()
    #plt.show()
    return(deriv1)
    
cell_br1 = np.array([0.63*10**6 , 1.10*10**6, 2.06*10**6, 2.08*10**6,\
            3.73*10**6, 3.89*10**6, 3.47*10**6,2.312*10**6])
cell_br2=  np.array([0.58*10**6 , 0.96*10**6, 2.07*10**6, 1.79*10**6,\
            3.57*10**6, 3.34*10**6, 2.62*10**6, 1.75*10**6])

b = brain.Brain(remote=True)
b.input_layer(1)
b.layer(linear=1)
b.layer(tanh=4)
b.layer(linear=1)
b.output_layer(1)

x_s = np.linspace(0,144,99)
xg = np.array([ 0.0 , 23.0 , 47.0 , 49.0 , 71.5 ,\
                95.0 , 119.0 , 144.0 ])
cells_spline = CubicSpline(xm, cell_br1) 
y_cells = cells_spline(x_s)
miu_1 = spline(cell_br1)
miu_2 = spline(cell_br2)
scale = [1.0e6,1.0e4]
x = (y_cells/scale[0]) #, y_glucose) #Inputs (3)
y = (miu_1/scale[1])    #Output (2)

b.learn(x,y) # train
yp = b.think(x) # validate

xp = np.linspace(0,144,99)
yyp = np.array(yp)
miu = np.reshape(yyp, (99,))

plot1 = plt.figure(3)
plt.plot(xp,miu*scale[1],'r-', label = 'Predicted ')
plt.plot(x_s,miu_1,'bo', label = 'Experimental points')
plt.xlabel('Time [hr]')
plt.ylabel('miu [1/h]')
plt.legend()
plt.show()

Recommendations:

  • Adjust the number of nodes and types of layers.
  • Use a package such as Keras or PyTorch for this type of problem. Here is a tutorial on Keras. Gekko is especially good at problems that need extra things such as constraints, non-standard activation functions, and hybrid machine learning where the model is a combination of physics-based and empirical elements.
  • Gekko uses gradient-based solvers that may get stuck at local minima.