如何解决选择合计一个值同时最小化另一个的最佳列 示例数据示例输出
我有一个基于机器学习模型的预测网格。我想选择遵循3条标准的最佳预测集。
-
id
列不能重复 - 第
x
列的总和必须尽可能接近x_goal
- 每个
y
的值都应最小化
示例数据
import numpy as np
import pandas as pd
np.random.seed(10)
x_goal = 20
df = pd.DataFrame({'x':np.random.uniform(1,10,20),'y':np.random.uniform(0,1,'id':list(range(0,4)) * 5})
df.head(10)
x y id
0 7.941886 0.542544 0
1 1.186768 0.142170 1
2 6.702834 0.373341 2
3 7.739235 0.674134 3
4 5.486563 0.441833 0
5 3.023170 0.434014 1
6 2.782566 0.617767 2
7 7.844776 0.513138 3
8 2.521998 0.650397 0
9 1.795058 0.601039 1
示例输出
在此示例中,我达到了第一和第三标准。但是当我希望尽可能接近20时,总和为24。
opt_1 = df.sort_values(['id','y']).groupby('id').first()
print(opt_1['x'].sum())
opt_1
24.455267105201795
x y
id
0 7.495798 0.113984
1 1.186768 0.142170
2 9.259967 0.046896
3 6.512735 0.300700
到目前为止,我已经尝试随机选择行,然后检查它是否与x_goal
相匹配,但这很慢,并且不能保证找到最佳的行。
欢迎任何建议或帮助!谢谢!
解决方法
我的解释方式是:
- 为每个ID最多选择一行
- 我们优化了以下两个目标:
- 所选x值的总和应尽可能接近20
- 选定的y值之和应尽可能小。
这是一个多目标问题。因此,一种方法是引入两个权重来确定这两个目标之间的权衡。
我们可以制定以下MIP模型:
min w1*absv + w2*ysum
subject to
xsum = sum(i,df.x[i]*select[i])
ysum = sum(i,df.y[i]*select[i])
sum(i,select[i]) <= 1 for each id
-absv <= xsum - 20 <= absv
select[i] ∈ {0,1}
这里有一些Python代码可以玩:
import pulp as lp
n = df.shape[0] # number of rows in data frame
w = [0.9,0.1] # weights on objectives
xtarget = 20
K = max(df.id)
prob = lp.LpProblem("SelectRows",lp.LpMinimize)
select = [lp.LpVariable("select{}".format(i),cat=lp.LpBinary) for i in range(n)]
absv = lp.LpVariable("absv")
ysum = lp.LpVariable("ysum")
xsum = lp.LpVariable("xsum")
prob += w[0]*absv + w[1]*ysum
prob += ysum == lp.lpSum([df.y[i]*select[i] for i in range(n)])
prob += xsum == lp.lpSum([df.x[i]*select[i] for i in range(n)])
prob += -absv <= xsum-20
prob += xsum-20 <= absv
for k in range(K+1):
prob += lp.lpSum([select[i] for i in range(n) if df.id[i]==k]) <= 1
prob.solve(lp.PULP_CBC_CMD())
print("Status:",lp.LpStatus[prob.status])
print("xsum:{}".format(xsum.value()))
print("ysum:{}".format(ysum.value()))
df["select"] = [round(select[i].value()) for i in range(n)]
输出如下:
Status: Optimal
xsum:20.027275
ysum:0.71071352
选定的行是:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。