Gekko集成线性回归模型优化制冷系统的两类错误排查
制冷系统优化中Gekko线性回归集成问题解决
问题1:原生Gekko_LinearRegression触发IndexError
报错原因
原生Gekko_LinearRegression类初始化时,错误地将model.intercept_当作数组执行[0]索引操作,但sklearn单输出线性回归模型的intercept_是标量,因此触发IndexError。
解决方法
重写类的初始化逻辑,兼容标量与数组类型的coef_和intercept_:
- 检查
coef_是否为可迭代对象,按需提取对应元素 - 检查
intercept_是否为标量,直接使用或提取数组首元素
问题2:自定义类触发Intermediate Definition错误
报错原因
- 循环重复创建类实例:每次循环新建
Gekko_LinearRegression_Modified实例,导致生成的中间变量未正确关联到Gekko模型的等式系统 - 成本累加等式错误:
m.Equation(costs == costs + costs_increment)造成循环依赖(costs同时出现在等式两侧),Gekko无法解析 - 约束值类型不匹配:
coolLoad_sum_min和coolLoad_sum_max是包含GekkoConst对象的numpy数组,需转换为纯数值数组
解决方法
- 提前初始化线性回归模型封装实例,避免循环内重复创建
- 使用
m.sum()直接累加所有成本增量,替换循环依赖的等式定义 - 将
coolLoad和Q_Spc改为纯数值,计算出纯数值的约束数组
修正后的完整代码
from gekko import GEKKO from gekko import ML from gekko.ML import Gekko_LinearRegression import numpy as np # 初始化Gekko模型 m = GEKKO(remote=False) price_vec_list = [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 1, 1, 1] price_vec_gekko = m.Array(m.Param, len(price_vec_list)) for i, val in enumerate(price_vec_list): price_vec_gekko[i].value = val # 直接使用数值,无需Gekko Const coolLoad = 3 Q_Spc = 5 n = len(price_vec_gekko) T_brine_in = m.Array(m.Param, n) for i in range(n): T_brine_in[i].VALUE = 25 ST_V = m.Array(m.MV, n) for i in range(n): ST_V[i].VALUE = 0.5 ST_V[i].LOWER = 0.43 ST_V[i].UPPER = 1 ST_V[i].status = 1 # 生成纯数值的约束累加数组 coolLoad_sum_min = np.cumsum(np.full(n, coolLoad)) coolLoad_sum_max = coolLoad_sum_min + Q_Spc # 修正后的Gekko线性回归封装类 class Gekko_LinearRegression_Fixed(Gekko_LinearRegression): def __init__(self, model, m): self.m = m # 处理系数:兼容数组与标量 if hasattr(model.coef_, "__len__"): self.coef = model.coef_ if len(model.coef_) == len(model.feature_names_in_) else model.coef_[0] else: self.coef = model.coef_ # 处理截距:兼容数组与标量 self.intercept = model.intercept_ if np.isscalar(model.intercept_) else model.intercept_[0] # 提前初始化模型实例(假设MLA_LR_P和MLA_LR_Q已训练完成) lr_p = Gekko_LinearRegression_Fixed(MLA_LR_P, m) lr_q = Gekko_LinearRegression_Fixed(MLA_LR_Q, m) # 定义总成本与中间变量 costs = m.Var(value=0) cost_increments = [] Qo_constraints = [] for i in range(n): # 生成预测值 pel_pred = lr_p.predict([ST_V[i], T_brine_in[i]]) / 1000 qo_pred = lr_q.predict([ST_V[i], T_brine_in[i]]) / 1000 # 存储增量与约束项 cost_increments.append(pel_pred * price_vec_gekko[i]) Qo_constraints.append(qo_pred) # 添加存储约束 m.Equation(qo_pred < coolLoad_sum_max[i]) m.Equation(qo_pred > coolLoad_sum_min[i]) # 定义总成本等式:求和所有增量 m.Equation(costs == m.sum(cost_increments)) # 优化配置与求解 m.Minimize(costs) m.options.SOLVER = 1 m.options.IMODE = 1 m.solve(disp=True) # 输出结果 print(f'Optimized ST_V values: {[v.VALUE[0] for v in ST_V]}') print(f'Total cost: {costs.VALUE[0]}')
关键修正点说明
- 类初始化兼容处理:确保
coef_和intercept_能适配标量与数组类型,避免索引错误 - 提前实例化模型:避免循环内重复创建Gekko相关实例,保证中间变量正确绑定到模型
- 成本累加逻辑优化:使用
m.sum()直接计算总和,消除循环依赖的等式定义 - 约束值标准化:将常量转换为纯数值数组,避免Gekko变量与numpy数组混合导致的解析问题
内容的提问来源于stack exchange,提问作者Marius Madaus
相关产品推荐
相关产品推荐

