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

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)

修正说明

  1. 目标函数修正:将循环中的for j in model.tour2改为for j in model.t2,确保j是t2集合的单个列名,匹配transfer的索引规则。
  2. 约束条件添加:
    • 变量transfer的bounds=(0,1)直接实现了0<T<1的约束;
    • 通过col_sum_rule和Constraint(model.t2, rule=col_sum_rule)添加了每列元素和为1的约束,对应需求中的Σᵢ Tᵢⱼ = 1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:25:34