You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Gekko中正确处理多维数组非线性回归?求解报错问题

在Gekko中正确处理多维数组非线性回归的解决方案

你遇到的这个报错,核心原因是Gekko对多维输入的处理逻辑和numpy不一样——直接把二维数组传给m.Param(),再用循环索引访问元素,会导致Gekko内部的数组维度匹配失败。Gekko的ParamCV对象本质是按样本/时间步长的一维序列管理的,多维输入需要拆分成多个独立的Param变量,同时要使用Gekko内置的符号函数(而非numpy函数)构建回归方程。

关键问题拆解

  1. 多维Param的错误用法:你把二维数组xm直接传给x = m.Param(value=xm),Gekko无法识别这是3个特征维度的样本集合,会把它当成形状不匹配的序列。
  2. numpy函数的误用:在方程里用np.log10()是数值计算,而Gekko需要构建符号化的回归方程,必须用Gekko内置的m.log10()函数。
  3. 不必要的循环:Gekko支持向量化运算,不需要手动循环每个样本,直接对整个数组操作即可。

修正后的完整代码

import pandas
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt

# 测量数据:3个特征,31个样本
xm = np.array([[80435, 33576, 3930495], [63320, 21365, 2515052], [131294, 46680, 10339497], [64470, 29271, 3272846], [23966, 7973, 3450144], [19863, 11429, 3427307], [32139, 13114, 2462822], [78976, 26973, 5619715], [32857, 10455, 3192817], [29400, 12808, 3665615], [4667, 2876, 2556650], [21477, 10349, 6005812], [9168, 4617, 2878631], [385112, 127609, 4063576], [55522, 29954, 3632023], [155, 197, 507], [160, 106, 336], [25, 23, 669], [86, 96, 751], [199, 235, 515], [60, 83, 511], [8, 25, 187], [32, 59, 679], [11, 22, 365], [322, 244, 2001], [172, 229, 1110], [41, 48, 447], [109, 144, 2386], [23, 27, 319], [105, 204, 672], [77, 77, 2]])
ym = np.array([90,85,91,90,90,82,81,85,83,83,72,78, 74,92,90,28,26,13,12,22,25,5,10,15,50,54,4,28,10,7,6])

# 初始化GEKKO模型
m = GEKKO()

# 把多维输入拆分成3个独立的Param变量(每个对应一个特征维度)
x1 = m.Param(value=xm[:,0], name='X1')
x2 = m.Param(value=xm[:,1], name='X2')
x3 = m.Param(value=xm[:,2], name='X3')

# 待拟合的目标变量,开启FSTATUS以使用测量值
y = m.CV(value=ym)
y.FSTATUS = 1

# 待优化的回归参数,开启STATUS让Gekko优化它们(给初始值加快收敛)
a1 = m.FV(value=1.0)
a1.STATUS = 1
a2 = m.FV(value=1.0)
a2.STATUS = 1
a3 = m.FV(value=1.0)
a3.STATUS = 1

# 构建向量化的回归方程:使用Gekko内置的log10(符号函数)
m.Equation(y == m.log10(x1)*a1 + m.log10(x2)*a2 + m.log10(x3)*a3)

# 设置为回归模式(IMODE=2)
m.options.IMODE = 2

# 求解优化问题(disp=True可查看优化过程)
m.solve(disp=True, GUI=False)

# 打印优化后的参数
print(f'Optimized parameters: a1={a1.value[0]:.4f}, a2={a2.value[0]:.4f}, a3={a3.value[0]:.4f}')

# 绘制拟合值vs真实值的散点图
plt.figure(figsize=(8,6))
plt.plot(y.value, ym, 'bo', label='Measured vs Fitted')
plt.plot([ym.min(), ym.max()], [ym.min(), ym.max()], 'r--', label='Perfect Fit')
plt.xlabel('Fitted Values')
plt.ylabel('Measured Values')
plt.legend()
plt.grid(True)
plt.show()

代码修改说明

  1. 拆分多维输入:把xm的三列分别拆成x1x2x3三个Param,每个都是一维数组,符合Gekko的序列处理逻辑。
  2. 使用Gekko内置函数:用m.log10()替代np.log10(),让Gekko能构建符号化方程,而非提前计算数值。
  3. 向量化方程:无需手动循环每个样本,Gekko会自动对整个数组的每个元素应用方程,简化代码同时避免维度错误。
  4. 添加初始值:给a1a2a3设置初始值1.0,帮助优化器更快收敛。

运行这段代码后,就能成功完成多维非线性回归,不会再出现维度匹配的报错,同时能得到优化后的参数和拟合效果可视化图。

内容的提问来源于stack exchange,提问作者Raj

火山引擎 最新活动