如何在scipy.optimize.minimize的trust-kyrlov/trust-ncg方法中使用LbfgsInvHessProduct作为预条件子
如何在scipy.optimize.minimize的trust-kyrlov/trust-ncg方法中使用LbfgsInvHessProduct作为预条件子
这个问题我之前做大规模无约束优化时也碰到过,刚好有现成的解决思路,不用自定义优化方法,咱们一步步来实现:
第一步:用LBFGS完成热身迭代,获取预条件子
首先你需要先跑LBFGS的固定迭代次数,从结果里拿到LbfgsInvHessProduct实例——这就是我们要用来做预条件子的Hessian逆近似。代码大概是这样的:
from scipy.optimize import minimize from scipy.optimize.lbfgsb import LbfgsInvHessProduct # 先定义你的目标函数和梯度(这里替换成你自己的实现) def objective(x): # 你的目标函数计算逻辑 return ... def gradient(x): # 你的梯度计算逻辑 return ... # 执行LBFGS热身,设置你需要的迭代次数 x0 = ... # 你的初始点 lbfgs_warmup = minimize( objective, x0, method='L-BFGS-B', jac=gradient, options={'maxiter': 100} # 这里设置热身的迭代次数 ) # 从LBFGS结果中取出Hessian逆近似的线性算子 precond_hess_inv = lbfgs_warmup.hess_inv
第二步:将预条件子传入trust区域方法
scipy的trust-ncg和trust-krylov方法其实已经支持通过选项传入预条件子了,你只需要把刚才拿到的LbfgsInvHessProduct包装成一个简单的函数,然后在调用minimize时指定即可:
# 定义预条件子函数,返回我们从LBFGS得到的Hessian逆近似 def preconditioner(x): # 这里因为我们用的是热身阶段的固定近似,所以直接返回即可 return precond_hess_inv # 用trust-ncg继续优化(换成trust-krylov同理) final_result = minimize( objective, lbfgs_warmup.x, # 用LBFGS的结果作为新初始点 method='trust-ncg', jac=gradient, options={ 'preconditioner': preconditioner, 'gtol': 1e-6 # 可以根据你的需求调整收敛阈值 } )
一些需要注意的点
LbfgsInvHessProduct是基于热身阶段LBFGS迭代积累的曲率信息,它不会随着后续trust方法的迭代自动更新。不过对于病态问题,这个固定的预条件子已经能显著加速trust方法的收敛速度了。- 确保你使用的是较新版本的
scipy(建议1.0以上),旧版本可能没有在trust方法中开放preconditioner这个选项。 - 如果你的问题中,热身阶段的Hessian逆近似在后续迭代中效果下降,你也可以考虑每隔几轮trust迭代,重新用LBFGS跑几次热身更新预条件子,不过这会增加一些计算开销,需要权衡。
备注:内容来源于stack exchange,提问作者Eric Weine
相关产品推荐
相关产品推荐

