参数估计和最小二乘最小化-Python和Gekko

参数估计和最小二乘最小化-Python和Gekko,python,gekko,Python,Gekko,我试图估计4个参数(kdoc1,kdoc2,S1,S2),用GEKKO解一个代数常微分方程组,最小化观测值和预测值之间剩余误差的平方和。我在测量数据和预测数据之间没有得到很好的调整,您对我在代码中做错了什么有什么建议吗? 此外,我还尝试添加另一组测量数据。我希望模型使用两个测量数据集进行参数估计,我需要使用两个数据集最小化残差之和。你知道如何在代码中实现它吗 我已经添加了额外的点,以帮助使用该建议的解算器收敛 以下是更接近的新结果 我给参数添加了约束,并给它们非零的起始值(1) kdoc1=m

我试图估计4个参数(kdoc1,kdoc2,S1,S2),用GEKKO解一个代数常微分方程组,最小化观测值和预测值之间剩余误差的平方和。我在测量数据和预测数据之间没有得到很好的调整,您对我在代码中做错了什么有什么建议吗?
此外,我还尝试添加另一组测量数据。我希望模型使用两个测量数据集进行参数估计,我需要使用两个数据集最小化残差之和。你知道如何在代码中实现它吗

我已经添加了额外的点,以帮助使用该建议的解算器收敛


以下是更接近的新结果

我给参数添加了约束,并给它们非零的起始值(1)

kdoc1=m.FV(1,lb=0.01,ub=10)#m-1h-1
kdoc2=m.FV(1,lb=0.01,ub=10)#m-1h-1
S1=m.FV(1,磅=0.01,磅=10)
S2=m.FV(1,磅=0.01,磅=10)
计算了
C0
C1
的初始条件,因为它们在
C2
中产生了较大的瞬时跃变。如果已知这些初始浓度,则可能需要切换回固定的初始条件

m.free_首字母(C0)
m、 自由首字母(C1)
缩放目标函数,因为1e-4**2已经是一个小数字,并且可能已经满足目标收敛标准。原始问题的目标函数值非常小。我将每个平方值近似等于1作为起点

m.Minimize(meas*(1e4*(C2-C2m))**2)
这提供了一个合理的解决方案,您可以从该解决方案开始获得所需的回归结果

kdoc1 = 3.7210285146
kdoc2 = 2.5743961631
S1 = 3.7210285146
S2 = 2.5743961631
参数值不会在约束处结束,因此这意味着此解决方案是最优的。即使参数约束在结束时不处于活动状态,这些约束也有助于在适当的搜索区域上引导解算器

从gekko导入gekko
将numpy作为np导入
将matplotlib.pyplot作为plt导入
将数学作为数学导入
作为pd进口熊猫
#测量
t_数据=[0.08333,0.5,1,4,22.61667]
x_数据=[9.33e-5,8.55e-5,8.55e-5,7.77e-5,7.00e-5]
#x_数据2=[2.92e-4,2.72e-4,2.92e-4,2.72e-4,2.14e-4]
df1=pd.DataFrame({'time':t_data,'x':x_data})
df1.设置索引(“时间”,就地=真)
#模拟时间点
df2=pd.DataFrame({'time':np.linspace(0,25,51)})
df2.设置索引(“时间”,就地=真)
#合并数据帧
df=df2.join(df1,how='outer')
#获取测量值的真(1)或假(0)
df['meas']=(df['x'].values==df['x'].values)。astype(int)
#将NaN替换为零
df0=df.fillna(值=0)
#估计模型
m=GEKKO()
m、 时间=df.index.values
#可调参数
kdoc1=m.FV(1,lb=0.01,ub=10)#m-1h-1
kdoc2=m.FV(1,lb=0.01,ub=10)#m-1h-1
S1=m.FV(1,磅=0.01,磅=10)
S2=m.FV(1,磅=0.01,磅=10)
#状态变量
#M(摩尔/升)
C0=m.Var(值=8.00e-5,磅=0,ub=1e-3)
m、 自由首字母(C0)
C1=m.Var(值=1.36e-3,磅=0,ub=2e-3)
m、 自由首字母(C1)
C2=m.Var(值=x_数据[0])
C2m=m.Param(df0['x'].值,lb=0)
meas=m.Param(df0['meas'].值)
m、 最小化(MEA*(1e4*(C2-C2m))**2)
C3=m.Var(值=0)
C4=m.Var(值=3.16e-8)
C5=m.Var(值=3.83e-7)
C6=m.Var(值=0)
C7=m.Var(值=0)
C8=m.Var(值=0)
C9=m.Var(值=0)
C10=m.Var(值=0)
C11=m.Var(值=0)
C12=m.Var(值=3.21e-3)
总有机碳=m.Var(值=5.93)#毫克碳/升
cC1=m.Var(值=0)
cC2=m.Var(值=0)
#温度摄氏度
T=20
#速率常数
k1=2040000000*数学实验(-1887/(273.15+T))*3600
k2=13800000*数学实验(-8800/(273.15+T))*3600
k3=300000*数学实验(-2010/(273.15+T))*3600
k4=0.00000065*3600
k6=26700*3600
k7=167*3600
k8=27700*3600
k9=8300*3600
k10=0
k5=3780000000*数学实验(-2169/(273.15+T))*C4\
+2.52e25*数学实验(-16860/(273.15+T))*C10\
+0.87*数学实验(-503/(273.15+T))*C9
r1=k1*C0*C1
r2=k2*C2
r3=k3*C0*C2
r4=k4*C3
r5=k5*C2*C2
r6=k6*C3*C1*C4
r7=k7*C3*C5
r8=k8*C6*C3
r9=k9*C6*C2
r10=k10*C2*C3
r11=kdoc1*S1*TOC*C2/12000
r12=kdoc2*S2*TOC*C0/12000
t=m.Param(值=m.time)
m、 方程(C0.dt()==-r1+r2-r3+r4+r8-r12)
m、 方程(C1.dt()==-r1+r2+r5-r6+r11)
m、 方程(C2.dt()==r1-r2-r3+r4-r5+r6-r9-r10-r11)
m、 方程(C3.dt()==r3-r4+r5-r6-r7-r8-r10)
m、 方程(C4.dt()==0)
m、 方程式(C5==1e-14/C4)
m、 方程(C6.dt()==r7-r8-r9)
m、 方程(C7==(3.16e-8*C0)/C4)
m、 方程(C1==(5.01e-10*C8)/C4)
m、 方程(C11==(5.01e-11*C10)/C4)
m、 方程(C9==(5.01e-7*C9)/C4)
m、 方程(C10==C12-2*C11-C5+C4)
m、 方程(C12.dt()==0)
m、 方程(TOC.dt()==0)
m、 方程(cC1==17000*C1)
m、 方程(cC2==51500*C2)
#应用程序选项
m、 options.SOLVER=3#APOPT SOLVER
m、 options.IMODE=5#动态同步-估计
m、 options.EV_TYPE=2#绝对误差
m、 options.NODES=3个搭配节点(2,5)
如果为真:
kdoc1.STATUS=1
kdoc2.STATUS=1
S1.状态=1
S2.状态=1
#解决
m、 求解(disp=True)
打印('解决方案')
打印('kdoc1='+str(kdoc1.value[0]))
打印('kdoc2='+str(kdoc2.value[0]))
打印('S1='+str(S1.value[0]))
打印('S2='+str(S2.value[0]))
plt.图(1,figsize=(8,5))
plt.子地块(2,1,1)
plt.plot(m.time,C2.value,'bo',label='Predicted')
plt.plot(m.time,df['x'].值,'rs',label='Meas')
plt.plot(m.time,C2.value,label='C2')
plt.图例(loc='best')
plt.子地块(2,1,2)
plt.plot(m.time,cC2.value,label='C2')
plt.plot(m.time,cC1.value,label='C1')
plt.图例(loc='best')
plt.xlabel(‘时间(h)’)
plt.图(2,figsize=(12,8))
plt.子地块(4,3,1)
plt.plot(m.time,C0.value,label='C0')
plt.legend()
plt.子地块(4,3,2)
plt.plot(m.time,C1.value,label='C1')
plt.legend()
plt.子地块(4,3,3)
plt.plot(m.time,C3.value,label='C3')
plt.legend()
plt.子地块(4,3,4)
plt.plot(m.time,C4.value,label='C4')
plt.legend()
plt.子地块(4,3,5)
plt.plot(m.time,C5.value,label='C5'
kdoc1 = 3.7210285146
kdoc2 = 2.5743961631
S1 = 3.7210285146
S2 = 2.5743961631
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt 
import math as math
import pandas as pd

#data set 1
t_data1 = [0.08333,0.5,1,4,22.61667]
x_data1 = [7.77e-5,7e-5,7e-5,6.22e-5,3.89e-5]
x_data1mgl = [4,3.6,3.6,3.2,2]

#data set 2
t_data4 = [0.08333,0.5,1,4,22.61667]
x_data4 = [2.92e-4,2.72e-4,2.92e-4,2.72e-4,2.14e-4]
x_data4mgl = [15,14,15,14,11]

#combine data and time in the same dataframe
data1 = pd.DataFrame({'time':t_data1,'x1':x_data1})
data4 = pd.DataFrame({'time':t_data4,'x4':x_data4})
data1.set_index('time', inplace=True)
data4.set_index('time', inplace=True)


# merge dataframes
data = data1.join(data4, how='outer')

# simulation time points
dftp = pd.DataFrame({'time':np.linspace(0,25,51)})
dftp.set_index('time', inplace=True)

# merge dataframes
df = data.join(dftp,how='outer')

# get True (1) or False (0) for measurement
#df['meas'] = (df['x'].values==df['x'].values).astype(int)
z1 = (df['x1']==df['x1']).astype(int)
z4 = (df['x4']==df['x4']).astype(int)


# replace NaN with zeros
df0 = df.fillna(value=0)

#Estimator Model
m = GEKKO(remote=True)
#m = GEKKO(remote=False) # remote=False to produce local folder with results

m.time = df.index.values

# measurements - Gekko arrays to store measured data
xm = m.Array(m.Param,2)
xm[0].value = df0['x1'].values
xm[1].value = df0['x4'].values


cl=m.Array(m.Var,2)
cl[0].value= 4e-5
cl[1].value= 1.33e-4


TOC=m.Array(m.Var,2)
TOC[0].value= 11.85
TOC[1].value= 11.85


C0=m.Array(m.Var,2)
C1=m.Array(m.Var,2)
cC1=m.Array(m.Var,2)
C2=m.Array(m.Var,2)
C2m=m.Array(m.Var,2)
cC2=m.Array(m.Var,2)
C3=m.Array(m.Var,2)
C4=m.Array(m.Var,2)
C5=m.Array(m.Var,2)
C6=m.Array(m.Var,2)
C7=m.Array(m.Var,2)
C8=m.Array(m.Var,2)
C9=m.Array(m.Var,2)
C10=m.Array(m.Var,2)
C11=m.Array(m.Var,2)
C12=m.Array(m.Var,2)

r1=m.Array(m.Var,2)
r2=m.Array(m.Var,2)
r3=m.Array(m.Var,2)
r4=m.Array(m.Var,2)
r5=m.Array(m.Var,2)
r6=m.Array(m.Var,2)
r7=m.Array(m.Var,2)
r8=m.Array(m.Var,2)
r9=m.Array(m.Var,2)
r10=m.Array(m.Var,2)
r11=m.Array(m.Var,2)
r12=m.Array(m.Var,2)

k5=m.Array(m.Var,2)

#Define GEKKO variables that determine if time point contains data to be used in regression
#index for objective (0=not measured, 1=measured)
zm = m.Array(m.Param,2)
zm[0].value=z1
zm[1].value=z4


# fit to measurement
x=m.Array(m.Var,2)                         
x[0].value=x_data1[0]
x[1].value=x_data4[0]


#adjustable parameters
kdoc1 = 0 #m-1h-1
kdoc2 = m.FV(1,lb=0.01,ub=10) #m-1h-1
S1 = 0
S2 = m.FV(1,lb=0.01,ub=10)

#Define Variables
for i in range(2):

#State variables
# M (mol/L)
    #C0 = m.Var(cl[i])
    C0[i] = m.Var(value=cl[i],lb=0,ub=1e-3)
    C1[i] = m.Var(value=6.9e-6,lb=0,ub=2e-3)
    C2[i] = m.Var(value=x[i],lb=0, ub=1e-3)
    C2m[i] = m.Param(xm[i],lb=0)
    meas = m.Param(zm[i])
    m.Minimize(meas*((C2[i]-C2m[i]))**2)
    C3[i] = m.Var(value=0)
    C4[i] = m.Var(value=3.16e-8)
    C5[i] = m.Var(value=3.83e-7)
    C6[i] = m.Var(value=0)
    C7[i]= m.Var(value=0)
    C8[i] = m.Var(value=0)
    C9[i] = m.Var(value=0)
    C10[i] = m.Var(value=0)
    C11[i] = m.Var(value=0)
    C12[i] = m.Var(value=3.21e-3)
    TOC[i] = m.Var(value=5.93)#mg-C/L 
    cC1[i] = m.Var(value=0)
    cC2[i] = m.Var(value=0)

#temperature ºC
    T = 20 

#Rate constants
    k1 = 2040000000*math.exp(-1887/(273.15+T))*3600
    k2 = 138000000*math.exp(-8800/(273.15+T))*3600
    k3 = 300000*math.exp(-2010/(273.15+T))*3600
    k4 = 0.00000065*3600
    k6 = 26700*3600
    k7 = 167*3600
    k8 = 27700*3600
    k9 = 8300*3600
    k10 = 0
    k5[i] = 37800000000*math.exp(-2169/(273.15+T))*C4[i]\
         +2.52e25*math.exp(-16860/(273.15+T))*C10[i]\
         +0.87*math.exp(-503/(273.15+T))*C9[i]
 
    r1[i] = k1 * C0[i] * C1[i]
    r2[i] = k2 * C2[i]
    r3[i] = k3 * C0[i] * C2[i]
    r4[i] = k4 * C3[i]
    r5[i] = k5[i] * C2[i] * C2[i]
    r6[i] = k6 * C3[i] * C1[i]* C4[i]
    r7[i] = k7 * C3[i] * C5[i]
    r8[i] = k8 * C6[i] * C3[i]
    r9[i] = k9 * C6[i] * C2[i]
    r10[i] = k10 * C2[i] * C3[i]
    r11[i] = kdoc1*S1*TOC[i]*C2[i]/12000
    r12[i] = kdoc2*S2*TOC[i]*C0[i]/12000

    t = m.Param(value=m.time)
    m.Equation(C0[i].dt()== -r1[i] + r2[i] - r3[i] + r4[i] + r8[i] - r12[i])
    m.Equation(C1[i].dt()== -r1[i] + r2[i] + r5[i] - r6[i] + r11[i])
    m.Equation(C2[i].dt()== r1[i] - r2[i] - r3[i] + r4[i] - r5[i] + r6[i] - r9[i] - r10[i] - r11[i])
    m.Equation(C3[i].dt()== r3[i] - r4[i] + r5[i] - r6[i] - r7[i] - r8[i] - r10[i])
    m.Equation(C4[i].dt()== 0)
    m.Equation(C5[i] == 1e-14/C4[i])
    m.Equation(C6[i].dt()== r7[i] - r8[i] - r9[i])
    m.Equation(C7[i] == (3.16e-8*C0[i])/C4[i])
    m.Equation(C1[i] == (5.01e-10*C8[i])/C4[i])
    m.Equation(C11[i] == (5.01e-11*C10[i])/C4[i])
    m.Equation(C9[i] == (5.01e-7*C9[i])/C4[i])
    m.Equation(C10[i] == C12[i] - 2*C11[i] - C5[i] + C4[i])
    m.Equation(C12[i].dt()== 0)
    m.Equation(TOC[i].dt()== 0)
    m.Equation(cC1[i] == 17000*C1[i])
    m.Equation(cC2[i] == 51500*C2[i])
    m.Equation(S1+S2<1)

#Application options
m.options.SOLVER = 3 #IPOPT solver
m.options.IMODE = 5 #Dynamic Simultaneous - estimation = MHE
m.options.EV_TYPE = 2 #absolute error
m.options.NODES = 3 #collocation nodes (2,5)

if True:
    #kdoc1.STATUS=1
    kdoc2.STATUS=1
    #S1.STATUS=1
    S2.STATUS=1

#Solve
#m.open_folder() # open folder if remote=False to see infeasibilities.txt
m.solve(disp=True)


print('Final SSE Objective: ' + str(m.options.objfcnval))

print('Solution')
#print('kdoc1 = ' + str(kdoc1.value[0]))
print('kdoc2 = ' + str(kdoc2.value[0]))
#print('S1 = ' + str(S1.value[0]))
print('S2 = ' + str(S2.value[0]))

plt.figure(1,figsize=(8,5))
plt.subplot(2,1,1)
plt.plot(m.time,C2[0],'b.--',label='Predicted 1')
plt.plot(m.time,C2[1],'r.--',label='Predicted 4')


plt.plot(t_data1,x_data1,'bx',label='Meas 1')
plt.plot(t_data4,x_data4,'rx',label='Meas 4')
plt.legend(loc='best')

plt.subplot(2,1,2)
plt.plot(m.time,cC2[0].value,'b',label ='C2_M1')
plt.plot(m.time,cC2[1].value,'r',label ='C2_M4')
plt.plot(t_data1,x_data1mgl,'bx',label='Meas 1')
plt.plot(t_data4,x_data4mgl,'rx',label='Meas 4')


#plt.plot(m.time,cC1.value,label ='C1')
plt.legend(loc='best')
plt.xlabel('time (h)')

plt.figure(2,figsize=(12,8))
plt.subplot(4,3,1)
plt.plot(m.time,C0[i].value,label ='C0')
plt.legend()

plt.subplot(4,3,2)
plt.plot(m.time,C1[i].value,label ='C1')
plt.legend()

plt.subplot(4,3,3)
plt.plot(m.time,C3[i].value,label ='C3')
plt.legend()

plt.subplot(4,3,4)
plt.plot(m.time,C4[i].value,label ='C4')
plt.legend()

plt.subplot(4,3,5)
plt.plot(m.time,C5[i].value,label ='C5')
plt.legend()

plt.subplot(4,3,6)
plt.plot(m.time,C6[i].value,label ='C6')
plt.legend()

plt.subplot(4,3,7)
plt.plot(m.time,C7[i].value,label ='C7')
plt.legend()

plt.subplot(4,3,8)
plt.plot(m.time,C8[i].value,label ='C8')
plt.legend()

plt.subplot(4,3,9)
plt.plot(m.time,C9[i].value,label ='C9')
plt.legend()
plt.xlabel('time (h)')

plt.subplot(4,3,10)
plt.plot(m.time,C10[i].value,label ='C10')
plt.legend()
plt.xlabel('time (h)')

plt.subplot(4,3,11)
plt.plot(m.time,C11[i].value,label ='C11')
plt.legend()
plt.xlabel('time (h)')

plt.subplot(4,3,12)
plt.plot(m.time,C12[i].value,label ='C12')
plt.legend()
plt.xlabel('time (h)')

plt.show()