You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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))

错误原因及修正方案

核心问题

  1. 除以0的数值异常:当H0values包含0时,h0=0会导致h=0且hd=0,此时h*d/hd和(hd-hdmeas)/hdmeas都会触发除以0的错误;hdmeas中也会包含0值,进一步放大这个问题。
  2. 目标函数与约束混淆:原代码将h*d/hd设为目标函数,但这实际上是kd的定义,应该作为约束方程,而非优化目标。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 22:57:47