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

Scipy minimize SLSQP退出模式3求助:大模型优化失败

带不等式约束的多变量优化问题故障排查

问题背景

使用Scipy的minimize结合SLSQP求解带不等式约束的多变量优化问题:目标为最小化f(a),约束条件g(a) ≤ SIGMA。6维a向量的小模型运行正常,但476维的大模型运行时出现错误。

错误信息

More than 3*n iterations in LSQ subproblem (Exit mode 3)
        Current function value: 1543.3839071145048
        Iterations: 1
        Function evaluations: 268
        Gradient evaluations: 1

代码及小模型输入

核心代码

import numpy as np
import scipy.optimize as op

SIGMA = 0.2 * (10 ** 6)
Y_MOD = 210. * (10 ** 6)
RHO = 7.850
GRAVITY_ACC = 9.81
A_MIN = 0.05 ** 2
A_MAX = 0.25 ** 2


def w(x, adj, a):
   return GRAVITY_ACC * RHO * np.sqrt(np.sum((x[adj[:, 1]] -  x[adj[:, 0]]) ** 2, axis=1)) * a


def f(x, adj, a):
   return np.sum(w(x, adj, a))


def g(x, adj, a, s, pw, pl):
   nk = len(x)
   ne = len(adj)
   dof = nk * 3
   dir_vec = x[adj[:, 1], :] - x[adj[:, 0], :]
   lengths = np.sqrt(np.sum(dir_vec ** 2, axis=1))
   stiff = Y_MOD * (a / lengths)
   fw = 0.5 * w(x, adj, a)
   cosines = dir_vec / lengths[:, None]
   Ks = np.zeros((dof, dof), dtype=np.float32)
   K_mats = np.empty((ne, 6, 6), dtype=np.float32)
   pg = np.zeros((dof,), dtype=np.float32)
   T_mats = np.empty((ne, 2, 6), dtype=np.float32)
   for e in range(ne):
      k_mat = np.array([[-stiff[e], stiff[e]],
                      [stiff[e], -stiff[e]]])
      cx, cy, cz = cosines[e]
      T_mats[e] = np.array([
         [cx, cy, cz, 0, 0, 0],
         [0, 0, 0, cx, cy, cz]])
      K_mats[e] = T_mats[e].T @ k_mat @ T_mats[e]
      i, j = adj[e]
      for h, x_idx in [(0, i * 3), (3, j * 3)]:
         for k, y_idx in [(0, i * 3), (3, j * 3)]:
            Ks[x_idx: x_idx + 3, y_idx:y_idx + 3] += K_mats[e, h:h + 3, k:k + 3]
      pg[i * 3 + 2] += fw[e]
      pg[j * 3 + 2] += fw[e]
   p = (pg + pw.flatten() + pl.flatten())
   vec_mask = np.logical_not(s).flatten()
   d = np.zeros(dof, dtype=np.float32)
   d[vec_mask] = np.linalg.solve(Ks[vec_mask, :][:, vec_mask], p[vec_mask])
   tensions = np.empty(ne, dtype=np.float32)
   b = np.array([1, -1], dtype=np.float32)
   for e in range(ne):
      i, j = adj[e] * 3
      tensions[e] = (Y_MOD / lengths[e]) * (b @ T_mats[e] @ d[[i, i + 1, i + 2, j, j + 1, j + 2]])
   return np.abs(tensions)


def optimizeFullProfiles(x, adj, x0, s, pw, pl):
   nlc = op.NonlinearConstraint(
      fun=lambda a: g(x, adj, a, s, pw, pl),
      lb=0.,
      ub=SIGMA)
   bounds = op.Bounds(A_MIN, A_MAX)
   res = op.minimize(fun=lambda a: f(x, adj, a),
                  x0=x0,
                  method='slsqp',
                  bounds=bounds,
                  constraints=[nlc],
                  tol=1e-6,
                  options={'disp': True, 'maxiter': 1000})

小模型输入

x = np.array([[0.  0.  0. ],
              [2.  0.  0. ],
              [2.  1.  0. ],
              [0.  0.9 0. ],
              [0.6 0.5 0.9]], dtype=np.float32)
adj = np.array([[0 4],
                [1 4],
                [2 4],
                [3 4],
                [1 2],
                [1 3]], dtype=int)
x0 = np.array([0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625], dtype=np.float32)
s = np.array([[1 1 1],
              [0 0 1],
              [1 1 1],
              [1 1 1],
              [0 0 0]], dtype=int)
pw = np.array([[0. 0. 0.],
               [0. 0. 0.],
               [0. 0. 0.],
               [0. 0. 0.],
               [0. 0. 0.]], dtype=np.float32)
pl = np.array([[  0.   0.   0.],
               [  0.   0.   0.],
               [  0.   0.   0.],
               [  0.   0.   0.],
               [  0.   0. 500.]], dtype=np.float32)

故障原因及解决办法

原因分析

Exit mode 3对应SLSQP求解子问题时迭代次数超过阈值,本质是高维场景下数值稳定性下降,核心诱因包括:

  • 梯度缺失:未提供目标函数和约束的解析梯度,Scipy只能用有限差分近似,高维下近似误差大,导致优化方向混乱。
  • 矩阵病态:大模型中刚度矩阵Ks可能出现条件数过大的情况,np.linalg.solve求解时数值不稳定,误差传递到约束计算,干扰优化过程。
  • 初始点不合理:476维x0全设为相同值,可能远离最优解区域,导致子问题快速陷入迭代僵局。

解决步骤

  1. 提供解析梯度
    手动推导并实现目标函数和约束的梯度,替换有限差分近似,大幅提升高维优化稳定性:

    • 目标函数梯度:f(a)是线性求和,df/da的每个分量直接为GRAVITY_ACC * RHO * 对应单元的长度。
    • 约束梯度:利用结构力学伴随法推导张力对a的导数,避免直接求导的复杂度。
  2. 优化矩阵求解稳定性
    替换np.linalg.solve为带正则项的最小二乘求解,处理病态矩阵:

    # 替换原solve代码块
    K_sub = Ks[vec_mask, :][:, vec_mask]
    p_sub = p[vec_mask]
    # 添加小正则项避免矩阵奇异
    d[vec_mask], _, _, _ = np.linalg.lstsq(K_sub + 1e-8 * np.eye(len(K_sub)), p_sub, rcond=None)
    
  3. 调整初始点与优化参数

    • 初始点x0根据单元负载分配设置,受载大的单元初始值适当提高,避免全相同值。
    • 调整SLSQP选项,增加子问题迭代次数、调整容差:
      options={'disp': True, 'maxiter': 1000, 'maxls': 100, 'ftol': 1e-5}
      
  4. 尝试替代优化方案
    若模型规模过大,可考虑分区域优化,或换用更适合高维问题的trust-constr优化器。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:32:07