使用Gekko拟合优化kd时出现NLP无效数值错误求助
拟合优化方程组求解kd时的数值错误解决
我需要通过拟合优化一组方程组来获取kd的数值,生成测试数据的代码运行正常,但优化kd时持续收到错误提示:EXIT: Invalid number in NLP function or derivative detected。
生成测试数据(运行正常)
def solve_gekko_equations(H0input, D0input, Kinput): m = GEKKO(remote=False) d0 = m.Const(D0input) h0 = m.Const(H0input) hdLimit=min([D0input,H0input]) d = m.Var(1,0,D0input) h = m.Var(1,0,H0input) hd = m.Var(1,0,hdLimit) kd = m.Const(Kinput) m.Equations([h + hd == h0, d + hd == d0, kd == h * d / hd]) m.solve(disp=False) return d.value[0], h.value[0], hd.value[0] H0values= np.linspace(0, 12, 100) solve_gekko_equations_vec = np.vectorize(solve_gekko_equations) dvalues, hvalues, hdvalues = solve_gekko_equations_vec(H0values, 2, 0.5)
优化kd的报错代码
from gekko import GEKKO m = GEKKO(remote=False) kd = m.FV(value=1) kd.STATUS = 1 d0 = m.Const(2) hdmeas = m.Param(value=hdvalues) h0 = m.Param(value=H0values) d = m.Var(1,0,2) h = m.Var(1,0) hd = m.Var(1,0) m.Equation(h + hd == h0) m.Equation(d + hd == d0) # Objective m.Obj(h * d / hd) m.Minimize(((hd-hdmeas)/hdmeas)**2) # Solve m.solve(disp=False) m.options.IMODE = 2 # Final objective print('Final Objective: '+ str(m.options.objfcnval)) # Print solution print('Solution') print('kd: ' + str(kd.value))
错误原因及修正方案
核心问题
- 除以0的数值异常:当
H0values包含0时,h0=0会导致h=0且hd=0,此时h*d/hd和(hd-hdmeas)/hdmeas都会触发除以0的错误;hdmeas中也会包含0值,进一步放大这个问题。 - 目标函数与约束混淆:原代码将
h*d/hd设为目标函数,但这实际上是kd的定义,应该作为约束方程,而非优化目标。 - IMODE设置顺序错误:
IMODE=2(参数估计模式)需要在solve()前设置,否则求解器会使用默认模式,导致逻辑错误。
修正后的代码
from gekko import GEKKO import numpy as np # 重新生成测试数据:避免H0为0,防止出现除以0的情况 def solve_gekko_equations(H0input, D0input, Kinput): m = GEKKO(remote=False) d0 = m.Const(D0input) h0 = m.Const(H0input) hdLimit=min([D0input,H0input]) d = m.Var(1,0,D0input) h = m.Var(1,0,H0input) hd = m.Var(1,0,hdLimit) kd = m.Const(Kinput) m.Equations([h + hd == h0, d + hd == d0, kd == h * d / hd]) m.solve(disp=False) return d.value[0], h.value[0], hd.value[0] # H0从0.1开始,而非0,避免数值为0的情况 H0values= np.linspace(0.1, 12, 100) solve_gekko_equations_vec = np.vectorize(solve_gekko_equations) dvalues, hvalues, hdvalues = solve_gekko_equations_vec(H0values, 2, 0.5) # 优化kd的修正代码 m = GEKKO(remote=False) m.options.IMODE = 2 # 先设置参数估计模式 kd = m.FV(value=1) kd.STATUS = 1 # 允许kd作为优化变量 d0 = m.Const(2) hdmeas = m.Param(value=hdvalues) h0 = m.Param(value=H0values) # 给变量设置极小下界,防止数值为0引发除以0错误 d = m.Var(lb=1e-6, ub=2) h = m.Var(lb=1e-6) hd = m.Var(lb=1e-6) # 系统约束方程:明确kd的定义 m.Equation(h + hd == h0) m.Equation(d + hd == d0) m.Equation(kd == h * d / hd) # 目标函数:仅最小化拟合误差 m.Minimize(((hd - hdmeas)/hdmeas)**2) # 求解 m.solve(disp=False) # 输出结果 print('Final Objective: '+ str(m.options.objfcnval)) print('Solution') print('kd: ' + str(kd.value[0]))
关键修正点
- 调整
H0values的起始值为0.1,避免h0=0导致的变量为0问题 - 给
d、h、hd设置下界1e-6,从根源上防止除以0的数值异常 - 将
kd = h*d/hd改为约束方程,明确变量间的关系,不再混淆目标与约束 - 提前设置
IMODE=2,确保求解器运行在参数估计模式下 - 移除多余的
m.Obj(h*d/hd),仅保留拟合误差最小化作为优化目标
内容的提问来源于stack exchange,提问作者Stephan Sinn
相关产品推荐
相关产品推荐

