使用scipy.optimize.minimize触发IndexError:数组索引过多问题排查
Scipy minimize约束报错问题解析
问题描述
我想用Scipy的scipy.optimize.minimize函数找到误差函数的最优值,需要指定上下界和A*x < b的不等式约束,代码如下:
from scipy.optimize import minimize, LinearConstraint import numpy as np def error_func(theta): return theta[0] - theta[1] theta0 = [100, 0] A = np.array([[1, 0], [0, 1]]) b = np.array([[100], [0]]) bnds = ((0, 100), (0, 0)) constraint = LinearConstraint(A, lb=-np.inf, ub=b) theta = minimize(error_func, theta0, method='trust-constr',constraints=constraint, bounds=bnds, options={'maxiter': 500})
运行时抛出如下错误:
/usr/local/lib/python3.7/dist-packages/scipy/optimize/_constraints.py in __init__(self, constraint, x0, sparse_jacobian, finite_diff_bounds) 259 mask = keep_feasible & (lb != ub) 260 f0 = fun.f --> 261 if np.any(f0[mask] < lb[mask]) or np.any(f0[mask] > ub[mask]): 262 raise ValueError("`x0` is infeasible with respect to some " 263 "inequality constraint with `keep_feasible` " IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed
错误原因
核心问题是约束上下界的维度不匹配:
- 你定义的
b是二维数组(形状(2,1)),但LinearConstraint要求ub(以及lb)的形状必须和A @ x0的输出形状一致。 A是(2,2)的矩阵,x0是长度为2的一维数组,计算A @ x0得到的是长度为2的一维数组,因此ub必须是一维数组,不能是二维的。- 当代码尝试用一维的
f0(即A@x0的结果)去和二维的ub做索引比较时,就会触发维度不匹配的索引错误。
另外补充:Scipy的数值优化中,严格不等式A*x < b通常会被转化为A*x <= b来处理(因为严格不等在数值计算中无法精确满足),如果确实需要近似严格小于,可以给b的每个元素减去一个极小值(比如1e-6)。
修正后的代码
把b改成一维数组即可解决问题,同时如果需要严格小于约束,可以微调b的值:
from scipy.optimize import minimize, LinearConstraint import numpy as np def error_func(theta): return theta[0] - theta[1] theta0 = [100, 0] A = np.array([[1, 0], [0, 1]]) # 改成一维数组,若需要严格小于则减去极小值 b = np.array([100, 0]) # 对应A*x <= b;若要近似A*x < b,可写成[99.999, -1e-6] bnds = ((0, 100), (0, 0)) # 定义线性约束:-inf < A@x <= b constraint = LinearConstraint(A, lb=-np.inf, ub=b) theta = minimize(error_func, theta0, method='trust-constr', constraints=constraint, bounds=bnds, options={'maxiter': 500}) print(theta)
内容的提问来源于stack exchange,提问作者abdullatif
相关产品推荐
相关产品推荐

