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

将XGBoost模型作为优化器目标函数的预算分配问题求解

预算分配优化问题

我正在解决一项预算分配问题,需将预算分配至20种不同的营销产品。现有一个XGBoost模型,可输入预算及其他预计算变量来预测销售结果。需从20种产品中选择n(n≤20)种,以实现总销售额最大化。

我尝试按比例分配预算(如产品1占10%、产品2占5%等),且有函数可计算每种产品的最大预算分配比例。此前尝试的方法均存在问题:

  • 使用Gekko时,Gekko的数据类型不被XGBoost支持,引发报错;
  • 因时间与内存限制,无法枚举所有分配组合进行搜索;
  • 使用Scipy时,其未遵守约束条件与边界限制。

请问是否有其他可行的解决方法?


我使用的Scipy代码

from scipy.optimize import minimize
import numpy as np

def objective_function(allocations, budget=budget):
    individual_predictions = [predict_results(allocations[i], i)
for i in range(num_products)]
    total_prediction = -sum(individual_predictions)
    if np.sum(allocations)!=1:
        loss=1e+9
    elif np.sum(allocations>0)!=7:
        loss=1e+9
    elif check_bounds(allocations, bounds)==False:
        loss=1e+9
    else:
        loss=total_prediction/budget
    return loss

num_products=len(preferred_list)

def total_allocations_constraint(allocations):
    return np.sum(allocations) - 1

def total_selections_constraint(allocations):
    return np.sum(allocations>0) - 7

def nonnegativity_constraint(allocations):
    return np.sum(allocations<0)

constraints = (
    {'type': 'eq', 'fun': total_selections_constraint},
    {'type': 'eq', 'fun': total_allocations_constraint},
    {'type': 'eq', 'fun': nonnegativity_constraint},
)

initial_allocations = [0 for i in preferred_list]

bounds = [(0, get_upper_bound(index_lookup.get(i))) for i in range(num_products)]

from datetime import datetime
t0=datetime.now()
print("Started at", t0)
result = minimize(objective_function, 
                  initial_allocations, 
                  method='trust-constr', 
                  bounds=bounds,
                  constraints=constraints)

optimized_allocations = result.x

print("Completed at", datetime.now())
print("Optimized Allocations:", optimized_allocations)

可行解决方法

1. 改进Scipy约束与目标函数写法

你的Scipy代码存在核心问题导致约束失效:

  • np.sum(allocations>0)是非光滑函数,梯度无法连续计算,trust-constr这类依赖梯度的优化器无法正确处理;
  • 目标函数中硬编码1e+9的惩罚项会导致优化器陷入局部最优,且无法保证约束严格满足。

改进方案:

  • 引入0-1选择变量(如s_i,取值0或1,表示是否选中产品i),将问题转化为混合整数优化问题;
  • 改用Scipy的SLSQP方法(对非光滑约束兼容性更好),或使用支持混合整数优化的库如PuLP、Pyomo;
  • 把选择数量约束转化为s_i的求和等于n,同时预算分配a_i = s_i * p_i,其中p_i是比例,满足sum(p_i) = 1且0 ≤ p_i ≤ upper_bound_i。

2. 使用启发式算法(适配黑箱模型)

XGBoost属于黑箱模型(无法提供梯度信息),启发式算法更适合这类场景:

  • 遗传算法:用DEAP库实现,将分配比例和选择变量编码为染色体,通过交叉、变异迭代寻找最优解;
  • 粒子群优化(PSO):用pyswarms库,每个粒子代表一组分配方案,通过群体协作更新找到最优解;
  • 模拟退火:接受较差解避免局部最优,适合非凸、黑箱目标函数。

这类方法无需梯度,能处理离散选择约束,且可通过调整种群规模、迭代次数控制时间与内存消耗。

3. 分阶段优化

先筛选高潜力产品,再优化分配比例,大幅缩小优化空间:

  1. 第一阶段:对每个产品,计算单位预算的边际收益(用XGBoost预测不同预算下的销售额,求导近似边际收益),筛选出前n个边际收益最高的产品;
  2. 第二阶段:在筛选出的n个产品中,用Scipy的SLSQP或启发式算法优化预算分配比例,满足总和为1且不超过各自上限。

4. 适配Gekko与XGBoost

Gekko报错源于数据类型不兼容,可通过包装函数解决:

  • 将XGBoost的预测函数包装成Gekko能识别的数值函数,比如用gekko.if3或自定义回调转换变量类型;
  • 用Gekko的APM模式调用外部脚本执行XGBoost预测,避免数据类型冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:16:07