带阈值求和约束的最小二乘优化求解效率提升问询
高效求解带约束最小二乘问题的方案
约束建模合理性确认
你的问题是凸优化问题,建模完全合理:
- 目标函数是凸二次函数(最小化平方差和);
- 约束均为凸集:
sum(w) = 1是线性等式约束;w_i ∈ [0, 0.3]是线性不等式约束;sum(w_i where w_i > 0.06) ≤ 0.6可转化为凸约束:sum(w) - sum(min(w_i, 0.06)) ≤ 0.6(因为min(w_i, 0.06)是凸函数,凸函数的和也是凸函数,因此该约束定义的可行域是凸集)。
之前求解效率低的核心原因是没有利用问题的凸性,用了不匹配的求解工具(Gekko擅长动态/非线性规划,Scipy循环组合完全是冗余操作)。
高效单步求解方案
直接使用专门处理凸二次规划的工具链,300变量规模可在毫秒级完成求解,推荐用CVXPY + OSQP组合:
示例代码
import cvxpy as cp import numpy as np # 模拟输入(替换为你的w_bar) n = 300 w_bar = np.random.rand(n) # 定义优化变量 w = cp.Variable(n) # 目标函数:最小化平方差和 objective = cp.Minimize(cp.sum_squares(w - w_bar)) # 约束集合 constraints = [ cp.sum(w) == 1, # 转化后的"大于0.06的w值和≤0.6"约束 cp.sum(w) - cp.sum(cp.min(w, 0.06)) <= 0.6, w >= 0, w <= 0.3 ] # 调用OSQP求解(默认也会选高效求解器,指定更保险) prob = cp.Problem(objective, constraints) prob.solve(solver=cp.OSQP, verbose=False) # 输出结果 print("最优目标值:", prob.value) optimal_w = w.value
为什么高效?
- OSQP是专门为大规模二次规划设计的求解器,采用交替方向乘子法(ADMM),在稀疏/稠密问题上都有极高效率;
- CVXPY自动处理凸约束的转化,无需手动推导梯度或约束形式,代码简洁且不易出错。
如果无法使用CVXPY,也可以用scipy.optimize.minimize配合SLSQP求解器,但需要手动将非光滑约束转化为光滑近似(例如用np.maximum(w - 0.06, 0)的光滑替代),但效率会略低于CVXPY+OSQP。
问题重构方向
如果业务允许对约束做微小调整,可考虑:
- 将
sum(w_i where w_i > 0.06) ≤ 0.6替换为sum(max(w_i - 0.06, 0)) ≤ 0.6 - 0.06 * k(其中k是允许超过0.06的变量数量上限),但这会改变约束的实际含义,仅适合对约束精度要求不高的场景; - 若0.06是经验阈值,可尝试调整为线性约束,但对300变量规模来说,常规线性替代(如
sum(w_i) - 0.06 * n ≤ 0.6)会因0.06*300=18远大于1而失去约束效果,因此不适用。
综上,最推荐的方案是利用问题的凸性,用CVXPY+OSQP直接求解,效率和准确性都能满足需求。
内容的提问来源于stack exchange,提问作者Ted S
相关产品推荐
相关产品推荐

