scipy.optimize.minimize调用trust-constr方法触发UserWarning告警
问题根因
你看到的两条告警,本质是因为你定义的目标函数是分段线性函数:abs(x_tot.dot(multipliers))除了x_tot.dot(multipliers)=0的折点外,其余区域一阶导数为常数、二阶导数(Hessian矩阵)全为0,准牛顿迭代过程中检测到梯度变化量为0,就会抛出对应提示。
hess参数入参数量问题说明
trust-constr方法对传入的目标函数Hessian回调,传参规则是固定的:第一个参数为当前迭代的优化变量x,后续会把你通过args传入的所有目标函数额外参数按顺序透传给Hessian回调。
你之前调用时args传入了3个参数a1,a2,a3,加上优化变量x总共4个入参,所以写只接收1个参数的lambda x: np.zeros((n,n))会触发参数数量不匹配的报错。
告警未消失的解决方法
你之前仅给目标函数指定了零Hessian,但没有给约束条件指定Hessian,算法默认仍会对约束项做准牛顿二阶近似,因此还是会触发相同告警。按如下方式修改即可:
- 给每个等式约束单独指定零Hessian(如果你的约束是线性约束,其Hessian本身就是零矩阵)
- 目标函数的Hessian回调用
*args接收透传的额外参数,无需手动匹配参数个数
修改后的代码示例:
import numpy as np from scipy import optimize # 给每个线性等式约束指定零Hessian cons = [ {'type': 'eq', 'fun': func1, 'hess': lambda x, *rest_args: np.zeros((Nc, Nc))}, {'type': 'eq', 'fun': func2, 'hess': lambda x, *rest_args: np.zeros((Nc, Nc))} ] result = optimize.minimize( obj_func, x0=x0, args=(a1, a2, a3), bounds=((-0.5, 0.5),) * Nc, constraints=cons, hess=lambda x, *rest_args: np.zeros((Nc, Nc)), method='trust-constr' )
额外优化建议
你的目标函数含绝对值项,折点处不可导,用基于梯度的trust-constr求解效率和稳定性都一般。可以把问题转换为标准线性规划形式求解:
引入辅助变量t,将原目标
min abs(x_tot.dot(multipliers))转换为min t,新增两个线性不等式约束:
x_tot.dot(multipliers) <= t-x_tot.dot(multipliers) <= t
转换后整个问题为纯线性目标+线性约束,用线性规划求解器计算速度更快,也不会出现梯度相关的告警。
内容的提问来源于stack exchange,提问作者JejeBelfort
相关产品推荐
相关产品推荐

