使用python和gekko拟合非线性模型

时间:2019-11-17 17:18:03

标签: python gekko

我有一个树木的数据集。在此数据集中,我具有唯一的Plot数,按顺序获取数据“ Measurement”时的顺序,以及树木的高度平均值(以米为单位)和年龄平均值(以年为单位)。像这样: head of data

接下来,我定义模型以这种方式使用年龄来预测身高:

  

高度= B0 *((1-exp(-B1 *年龄))** B2)

我的目标是分别确定B0,B1和B2的值。为此,我使用gekko包通过以下代码查找模型的参数:

num_p = data_gek.Plot.unique()
nmp = 5
number_p = (data_gek.Plot == num_p[nmp])

m = GEKKO()

xm = np.array(data_gek[number_p]['Age'])
x = m.Param(value=xm)

B0 = m.FV(value=38.2) #value=38.2
B0.STATUS = 1

B1 = m.FV(value=0.1) #value=0.1
B1.STATUS = 1

B2 = m.FV(value=2.08) #value=2.08
B2.STATUS = 1

ym =  np.array(data_gek[number_p]['Height'])
z = m.CV(value=ym)

y = m.Var()
m.Equation(y==B0 * ((1 - m.exp(-B1 *x))**B2))
m.Obj(((y-z)/z)**2)

m.options.IMODE = 2
m.options.SOLVER = 1
m.solve(disp=False)

print(B0.value[0],B1.value[0],B2.value[0])
#output 
27.787958561 0.0052435491089 0.21178326158

但是,我不确定我做对的方式是否正确。是否可以在没有参数初始值的情况下执行此操作?因为我使用文献中的B0,B1和B2以前的值。

如果您要查看我的数据集和流程,则可以访问此notebook in Google Colab

1 个答案:

答案 0 :(得分:3)

您的脚本只有一个问题。 z的定义必须是ParamMV类型,而不是CV作为z = m.Param(value=ym),因为它是目标函数的输入。

如果您将y定义为CV而不是Var,则也可以使用built-in objective。您只需要打开feedback status FSTATUS=1即可使用目标函数,该目标函数可最小化测量值与模型预测之间的差异。这是脚本的修改版本。

regression fit

from gekko import GEKKO
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
url = 'http://apmonitor.com/pdc/uploads/Main/data_2nd_order.txt'
data = pd.read_csv(url)
m  = GEKKO()
xm = np.array(data['time'])
x  = m.Param(value=xm)
B0 = m.FV(1); B1 = m.FV(1); B2 = m.FV(1)
B0.STATUS = 1; B1.STATUS = 1; B2.STATUS = 1
ym =  np.array(data['output (y)'])
y  = m.CV(value=ym)
y.FSTATUS = 1
yi = m.Intermediate(B0 * ((1 - m.exp(-B1 *x))**B2))
m.Equation(y==yi)
m.options.IMODE = 2
m.options.SOLVER = 1
m.solve(disp=True)
print(B0.value[0],B1.value[0],B2.value[0])
plt.plot(xm,ym,'ro')
plt.plot(xm,y.value,'b--')
plt.show()
相关问题