协助设置Scipy Basinhopping的自定义方法

pbossiut  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(135)

我正在尝试设置一个本地最小化的自定义方法。从我对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将改变,并且该改变将需要被转移到局部求解器。

tzdcorbm

tzdcorbm1#

此外,我不太清楚x 0是如何从basinhopping转移到局部求解器的。对于盆地跳跃和局部求解器的第一次迭代,X 0将是相同的,但是在盆地跳跃的第一次迭代之后,盆地跳跃的x 0将改变,并且该改变将需要被转移到局部求解器。
您可以通过编写具有以下参数的函数来获取此参数,并将其用作自定义方法:

def custom_method(fun, x0, args, **kwargs):
    # implement your custom method here

更多信息在这里:https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html(Ctrl-F“自定义最小值”)

相关问题