Pyomo带约束多元线性回归实现报错求助及约束添加指导
Pyomo求解带约束多元线性回归的问题修正
问题背景
需求是用Pyomo求解带约束的多元线性回归,涉及三个矩阵:
- X(代码中为
tour1):600×13输入矩阵,对应Pyomo集合bureaux*t1 - Y(代码中为
tour2):600×3待预测矩阵,对应Pyomo集合bureaux*t2 - T(代码中为
transfer):13×3转换矩阵,对应Pyomo集合t1*t2
优化目标与约束:
ypred = X·T minimize Σ(ypred - Y)² subject to: 0 < T < 1 Σᵢ Tᵢⱼ = 1 (对每个j,所有行i的T元素和为1)
错误原因
运行代码出现KeyError: "Index '('X0', 'B0', 'Y0')' is not valid for indexed component 'transfer'",原因是目标函数中错误遍历了model.tour2(二维Param),直接遍历会得到(bureau_id, t2_col)的元组,而非t2集合的单个列名,导致调用model.transfer[k,j]时j是元组,索引不匹配。
修正后的完整代码
from pyomo.environ import * import pandas as pd import numpy as np # 生成测试数据 tour1 = pd.DataFrame(np.random.random(size=(60,13)), columns=["X"+str(i) for i in range(13)], index=["B"+str(i) for i in range(60)]) tour2 = pd.DataFrame(np.random.random(size=(60,3)), columns=["Y"+str(i) for i in range(3)], index=["B"+str(i) for i in range(60)]) def gettour1(model, i, j): return tour1.loc[i,j] def gettour2(model, i, j): return tour2.loc[i,j] def cost(model): # 修正:遍历model.t2(t2集合)而非model.tour2(二维Param) return sum( (sum(model.tour1[i,k] * model.transfer[k,j] for k in model.t1) - model.tour2[i,j])**2 for i in model.bureaux for j in model.t2 # 这里改为model.t2 ) def col_sum_rule(model, j): # 约束:对每个t2的列j,所有t1行的transfer元素和为1 return sum(model.transfer[i,j] for i in model.t1) == 1 # 构建模型 model = ConcreteModel() model.bureaux = Set(initialize=tour1.index.tolist()) model.t1 = Set(initialize=tour1.columns) model.t2 = Set(initialize=tour2.columns) model.tour1 = Param(model.bureaux, model.t1, initialize=gettour1) model.tour2 = Param(model.bureaux, model.t2, initialize=gettour2) # 定义transfer变量,0<T<1的约束通过bounds实现 model.transfer = Var(model.t1, model.t2, bounds=(0, 1)) # 目标函数 model.obj = Objective(rule=cost, sense=minimize) # 添加列和为1的约束 model.col_sum_constraint = Constraint(model.t2, rule=col_sum_rule) # 可选:求解模型(需安装对应求解器,比如ipopt) # solver = SolverFactory('ipopt') # solver.solve(model)
修正说明
- 目标函数修正:将循环中的
for j in model.tour2改为for j in model.t2,确保j是t2集合的单个列名,匹配transfer的索引规则。 - 约束条件添加:
- 变量
transfer的bounds=(0,1)直接实现了0<T<1的约束; - 通过
col_sum_rule和Constraint(model.t2, rule=col_sum_rule)添加了每列元素和为1的约束,对应需求中的Σᵢ Tᵢⱼ = 1。
- 变量
内容的提问来源于stack exchange,提问作者Julien Denos
相关产品推荐
相关产品推荐

