我正在尝试设置一个本地最小化的自定义方法。从我对basinhopping的理解来看,你从一个初始条件开始,使用局部方法最小化,然后使用basinhopping改变参数的值,再次局部最小化。我知道basinhopping有几个局部最小化方法的选项,但我试图使用一个自定义方法,并遇到了一些问题。让我们从一个MVE开始:
import scipy.optimize as so
import numpy as np
from scipy.optimize import basinhopping
from scipy.optimize import OptimizeResult
data_set=[np.array([0.01252837, 0.00994032, 0.02607758, 0.02938639, 0.03470389,
0.0393117 , 0.05045751, 0.05288866]), np.array([0.01096586, 0.0093723 , 0.02996665, 0.0490254 , 0.06359686,
0.07470107, 0.07533133, 0.10770218]), np.array([0.0108 , 0.01922004, 0.0290243 , 0.03236109, 0.00761577,
0.05216742, 0.05526853, 0.06572701]), np.array([0.01744162, 0.02563377, 0.03473111, 0.04372516, 0.05533209,
0.06429533, 0.06852919, 0.08112336]), np.array([0.01664812, 0.03377632, 0.04334155, 0.05260618, 0.06893069,
0.07831481, 0.08656102, 0.0999732 ]), np.array([0.01933805, 0.02861486, 0.04197618, 0.05017609, 0.06353904,
0.07471151, 0.08393098, 0.09447883])]
prot,lig=np.array([0.28, 0.26, 0.25, 0.23, 0.21, 0.19, 0.18, 0.15]), np.array([0.14, 0.26, 0.37, 0.47, 0.63, 0.77, 0.88, 1.1 ])
def global_fun(par,protein,ligand,csp_list):
kd,wmax=par
chi2=0
for csp in csp_list:
model=wmax*((protein+ligand+kd-np.sqrt(((protein+ligand+kd)**2)-(4*protein*ligand)))/(2*protein))
chi2+=np.sum((csp-model)**2)
return chi2
sol=basinhopping(global_fun,minimizer_kwargs={'args':(prot,lig,data_set),'options':{'maxiter':100000},'bounds':((0,np.inf),)*2,'method':'Nelder-Mead'},x0=[1,0.01])
>>>
fun: 0.00879004731452548
lowest_optimization_result: final_simplex: (array([[3.20231857, 0.33548486],
[3.20238274, 0.33549024],
[3.20240774, 0.33549202]]), array([0.00879005, 0.00879005, 0.00879005]))
fun: 0.00879004731452548
message: 'Optimization terminated successfully.'
nfev: 66
nit: 34
status: 0
success: True
x: array([3.20231857, 0.33548486])
message: ['requested number of basinhopping iterations completed successfully']
minimization_failures: 0
nfev: 8794
nit: 100
x: array([3.20231857, 0.33548486])
它工作得很好,提供了一个很好的解决方案,具有低chi2。
Basinhopping获取minimizer_kwargs
中的输入,并将其用于局部求解器。因此,边界、参数和选项都在minimizer_kwargs中定义并传递。所以我尝试了一个本地求解器(我只发布了代码的下半部分,上半部分是一样的)。
def custom_method(args=(args,bounds,options)):
local_so=so.minimize(args=args,bounds=bounds,options=options,method='Nelder-Mead')
return OptimizeResult(x=local_so.x,fun=local_so.fun,success=local_so.success)
sol=basinhopping(global_fun,minimizer_kwargs={'args':(prot,lig,data_set),'options':{'maxiter':100000},'bounds':((0,np.inf),)*2,'method':custom_method},x0=[1,0.01])
这是错误的设置,但我不太知道如何修复它。我不太知道如何将参数从minimizer_kwargs转移到我的自定义方法中,以便它们可以用作局部求解器的输入。此外,我不太清楚x0是如何从basinhopping转移到局部求解器的。对于盆地跳跃和局部求解器的第一次迭代,X0将是相同的,但是在盆地跳跃的第一次迭代之后,盆地跳跃的x0将改变,并且该改变将需要被转移到局部求解器。
1条答案
按热度按时间tzdcorbm1#
此外,我不太清楚x 0是如何从basinhopping转移到局部求解器的。对于盆地跳跃和局部求解器的第一次迭代,X 0将是相同的,但是在盆地跳跃的第一次迭代之后,盆地跳跃的x 0将改变,并且该改变将需要被转移到局部求解器。
您可以通过编写具有以下参数的函数来获取此参数,并将其用作自定义方法:
更多信息在这里:https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html(Ctrl-F“自定义最小值”)