简体   繁体   中英

scipy.optimize.basinhopping doesn't call accept_test. Why?

I am trying to optimise the output of a function using the scipy basinhopping algorithm.

def acceptance_criteria(self,**kwargs): 
    print "kwargs "
    print kwargs

    x = kwargs["x_new"]
    beta = x[0]
    alpha = [x[1],x[2],x[3],x[4],x[5],x[6]]
    print x
    inputnow= raw_input()
    beta_gamma_pass = beta != self.gamma
    beta_zero_pass = beta >= 0.0
    alpha1_pass = alpha[0] > 0.0
    alpha2_pass = alpha[1] > 0.0
    alpha3_pass = alpha[2] > 0.0
    alpha4_pass= alpha[3] > 0.0
    alpha5_pass= alpha[4] > 0.0
    alpha6_pass= alpha[5] > 0.0
    return  beta_gamma_pass,beta_zero_pass,alpha1_pass,alpha2_pass,alpha3_pass,alpha4_pass,alpha5_pass,alpha6_pass

def variational_calculation(self):
    minimizer_kwargs = {"method": "BFGS"}

    initial_paramater_guesses = [2,1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0]
    ret = basinhopping(self.Calculate, initial_paramater_guesses, minimizer_kwargs=minimizer_kwargs, niter=200, accept_test=self.acceptance_criteria)

I am getting problems with Nans and infs in my calculate function. This is due to invalid parameter values being used. I have attempted to prevent this by using acceptance criteria. But the basinhopping routine does not call the accept_test function. Thus the criteria remain unimplemted.

Can anyone help me out as to why basinhopping isn't calling the accept_test function?

Thanks

EDIT: in response to @sascha's comment, There are fractional powers of parameters, and 1/parameter terms in the function. Not limiting the range of the allowed parameter values gives complex and inf values in this case. It is actually an eigenvalue problem, where I am trying to minimise the trace of the eigenvalues of a set of 18*18 matrices. The matrix elements depend on the 7 parameters in a complex way with dozens of non linear terms.

I have never worked on anything more complex than polynomial regression before, so I am not familiar with the algorithms or their applicability at all. However, the function/s that I am trying to minimise are smooth as long as you avoid parameter values near poles; caused by 1/parameter and 1/(paramter^n -constant) terms.

EDIT2: QUESTION CLARIFICATION The question here is nothing to do with the applicability of the basinhopping algorithm.

It is why the specific implementation of it, in the 2.7 version of python and scipy, does not call the accept_test function?

I can't say why your example doesn't work, but here's a similar but minimal example where it does call the accept_test, maybe you can spot the difference

import scipy
import numpy as np
from scipy.optimize import basinhopping

class MyClass:
    def Calculate(self, x):
        return np.dot(x, x)

    def acceptance_criteria(self, **kwargs):
        print("in accept test")
        return True

    def run(self):
        minimizer_kwargs = {"method": "BFGS"}

        initial_paramater_guesses = [2,1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0]
        ret = basinhopping(self.Calculate,
                           initial_paramater_guesses,
                           minimizer_kwargs=minimizer_kwargs,
                           niter=200,
                           accept_test=self.acceptance_criteria)

my_class = MyClass()
my_class = my_class.run()

I know this post is old, but it still shows up on Googling this question.

I was having the same issue, so I ran a test by modifying the code here a bit and adding a counter. My code minimizes 5 variables, but requires all values to be greater than 0.5

import numpy as np
from scipy.optimize import basinhopping
n = 0

def acceptance_criteria(**kwargs):
    print("in accept test")
    X = kwargs['x_new']
    for x in X:
        if x < .5:
            print('False!')
            return False
    return True

def f(x):
    global n
    print(n)
    n += 1
    return (x[0]**2-np.sin(x[1])*4+np.cos(x[2]**2)+np.sin(x[3]*5.0)-(x[4]**2 -3*x[4]**3))**2

if __name__ == '__main__':
    res = basinhopping(f,[.5]*5,accept_test=acceptance_criteria)

It took about 100 iterations before entering the acceptance_criteria function.

If you are optimizing a function that takes a long time to run (as I was), then you might just need to give it more time to enter into the acceptance_test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM