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

SciPy约束优化n>1000时收敛至初始值的问题求助

大规模约束优化问题:n>1000时收敛到初始值

我用SciPy的optimize工具处理10万条观测值的约束优化任务,但当观测数n>1000时,优化结果会收敛到初始值。比如500条观测值能得到良好的局部最小值,但n趋近1000时,优化值和初始值完全一致。

目标函数与约束条件代码

目标函数:

def objective(x):
    return np.sum(np.array([-TU_array[i]*(NR_fn(x[i])-LS_fn(x[i],pd_array[i])) for i in range(0,len(x))]))

# where
def NR_fn(x):
    R = (1.99525947856706E-13*x**3-0.000000299925*x**2+0.137682384749*x+3648.729074580060)
    return R

def LS_fn(x,pd):
    L =x*pd
    return L

约束条件:

def constraint1(x):
    return np.sum(x)-df["creditlimit"].sum()
 
def constraint3(x):
    return np.sum(np.array([LS_fn(x[i],pd_array[i]) for i in range(0,len(x))]))-525000

b = (df["creditlimit"].min(),df["creditlimit"].max())

bnds = (b,)*len(df)

con1 = {'type': 'eq', 'fun': constraint1}
# con2 = {'type': 'eq', 'fun': constraint2}
con3 = {'type': 'eq', 'fun': constraint3}
cons = ([con1,con3])

x0 = np.array(df["creditlimit"])
solution = minimize(objective,x0,method='SLSQP', bounds=bnds,constraints = cons, options={'maxiter': 200, 'disp': True})
x = solution.x 

我试过修改约束条件和函数形式,结果还是和初始值一致,该怎么解决?有没有其他工具适合这个函数的优化?


解决思路与方案

一、优化现有SciPy SLSQP的实现

  1. 目标函数向量化改造
    当前循环遍历每个元素的写法,在n>1000时计算效率极低,会导致优化器因计算量过大提前终止。改成完全向量化形式:

    def objective(x):
        nr_vals = NR_fn(x)
        ls_vals = x * pd_array
        return np.sum(-TU_array * (nr_vals - ls_vals))
    

    约束条件也同步去掉循环:

    def constraint3(x):
        return np.sum(x * pd_array) - 525000
    

    向量化能大幅提升计算速度,让优化器在迭代次数内完成足够的搜索步骤。

  2. 调整SLSQP迭代参数

    • 增大maxiter:当前200次迭代对高维问题可能不足,尝试调到500或1000;
    • 收紧容差:设置ftol=1e-8、eps=1e-6,让优化器更严格判断收敛状态;
    • 开启详细日志:添加iprint=2到options,查看迭代过程中目标函数和约束的变化,确认是真收敛还是提前终止。
  3. 扰动初始点
    你的初始点x0刚好满足约束1的等式条件,如果同时接近约束3的边界,优化器会直接判定当前点为可行域极值点。给初始点加小扰动:

    x0 = np.array(df["creditlimit"]) + np.random.normal(0, 10, size=len(x0))
    

    让优化器从非约束边界点开始搜索。

二、换用更适配的优化工具

  1. SciPy L-BFGS-B结合拉格朗日乘子
    L-BFGS-B更适合高维问题,可将等式约束转化为拉格朗日函数重新构造目标:

    def lagrangian(x, lambda1, lambda3):
        obj_val = objective(x)
        con1_val = constraint1(x)
        con3_val = constraint3(x)
        return obj_val + lambda1 * con1_val + lambda3 * con3_val
    

    对x、lambda1、lambda3联合优化,注意参数初始化的合理性。

  2. 用CVXPY/ Pyomo调用专业求解器
    这类建模框架能自动适配大规模问题,推荐用IPOPT求解器:

    import cvxpy as cp
    
    x = cp.Variable(len(df), bounds=bnds)
    objective = cp.sum(-TU_array * (NR_fn(x) - x * pd_array))
    constraints = [
        cp.sum(x) == df["creditlimit"].sum(),
        cp.sum(x * pd_array) == 525000
    ]
    prob = cp.Problem(cp.Minimize(objective), constraints)
    prob.solve(solver=cp.IPOPT, max_iter=1000)
    x_opt = x.value
    

    IPOPT在高维非线性约束问题上的稳定性远优于SLSQP。

  3. 并行化优化(针对10万级观测)
    超大规模问题可借助dask实现并行计算,或用mpi4py做分布式优化,降低单节点计算压力。

三、利用问题结构简化求解

你的目标函数是可分离的(每个x[i]的贡献独立,仅约束为总和形式),可以用拉格朗日对偶法分解为单变量优化问题,先求解每个x[i]的最优解表达式,再通过约束条件求解拉格朗日乘子,避免直接优化高维变量,这是处理此类问题最高效的思路。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:25:28