中等规模带约束优化问题:是否存在快于SLSQP的算法?
更快的求解方案
针对你的500变量、带边界+少量不等式约束的优化问题,核心提速思路是把问题转化为线性规划(LP)——你的目标函数和约束本质都是线性的,没必要用SLSQP这类通用非线性求解器,专用LP求解器的速度会快很多。以下是具体方案:
1. 改用Scipy的linprog(线性规划专用求解器)
linprog是Scipy专为LP问题设计的求解器,内置高效的内点法/单纯形法,处理中等规模变量的LP问题远快于SLSQP。
首先把你的约束转化为标准LP形式:
- 目标函数:最大化
sum(x*pred)→ 等价于最小化-sum(x*pred) - 原约束
|sum(x*varN)| ≤5拆成两个线性不等式:sum(x*varN) ≤5和-sum(x*varN) ≤5 - 变量上下界保持
-0.03 ≤x ≤0.03
代码示例:
from scipy.optimize import linprog import pandas as pd import numpy as np df = pd.DataFrame(np.random.rand(500,5),columns=['pred','var1','var2','var3','weights']) # 提前提取numpy数组,避免DataFrame重复索引开销 pred = df['pred'].values var1 = df['var1'].values var2 = df['var2'].values var3 = df['var3'].values # 目标函数系数:minimize -sum(x*pred) → c = -pred c = -pred # 构造不等式约束矩阵A_ub和向量b_ub A_ub = np.array([ var1, # sum(x*var1) ≤5 -var1, # sum(x*var1) ≥-5 → 等价于 -sum(x*var1) ≤5 var2, -var2, var3, -var3 ]) b_ub = np.array([5,5,5,5,5,5]) # 变量上下界 bounds = [(-0.03, 0.03)] * len(pred) # 用'highs'方法求解(Scipy 1.9+默认,高效内点法) sol = linprog( c=c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs', options={'maxiter': 1000} )
2. 用cvxpy调用更高效的LP求解器
如果Scipy的linprog还不够快,可以用cvxpy——它封装了ECOS、OSQP等更快的开源LP求解器,代码更简洁,自动处理约束转化,适合大规模问题。
在Colab中先安装(若未安装):
!pip install cvxpy
代码示例:
import cvxpy as cp import pandas as pd import numpy as np df = pd.DataFrame(np.random.rand(500,5),columns=['pred','var1','var2','var3','weights']) pred = df['pred'].values var1 = df['var1'].values var2 = df['var2'].values var3 = df['var3'].values # 定义优化变量 x = cp.Variable(len(pred)) # 目标函数:直接最大化sum(x*pred) objective = cp.Maximize(x @ pred) # 约束直接用数学表达式书写,无需手动构造矩阵 constraints = [ cp.abs(x @ var1) <= 5, cp.abs(x @ var2) <= 5, cp.abs(x @ var3) <= 5, x >= -0.03, x <= 0.03 ] # 构建问题并求解(可选ECOS/OSQP等求解器) prob = cp.Problem(objective, constraints) prob.solve(solver=cp.ECOS) # 获取结果 print("最优值:", prob.value) print("最优解:", x.value)
3. 优化原SLSQP代码(若必须用非线性求解器)
如果因特殊需求坚持用SLSQP,可通过以下细节提速:
- 提前把DataFrame列转为numpy数组,避免每次函数调用都从DataFrame取数
- 用矩阵乘法
@替代元素乘后求和,减少计算开销 - 关闭不必要的输出,调整精度参数(若不需要极高精度)
优化后的代码:
from scipy.optimize import minimize, Bounds import pandas as pd import numpy as np df = pd.DataFrame(np.random.rand(500,5),columns=['pred','var1','var2','var3','weights']) # 提前提取numpy数组 pred_arr = df['pred'].values var1_arr = df['var1'].values var2_arr = df['var2'].values var3_arr = df['var3'].values def obj(x): return -(x @ pred_arr) def c1(x): return 5 - abs(x @ var1_arr) def c2(x): return 5 - abs(x @ var2_arr) def c3(x): return 5 - abs(x @ var3_arr) sol = minimize( fun=obj, x0=df['weights'].values, method='SLSQP', bounds=Bounds(-0.03, 0.03), constraints=[{'type': 'ineq', 'fun': c1},{'type': 'ineq', 'fun': c2},{'type': 'ineq', 'fun': c3}], options={'maxiter': 1000, 'disp': False} )
内容的提问来源于stack exchange,提问作者helloimgeorgia
相关产品推荐
相关产品推荐

