-
Notifications
You must be signed in to change notification settings - Fork 601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unexpected behavior of stopping criterion: maxeval #570
Comments
could you please provide a minimal script to reproduce ? |
Hello, thank you for the super fast answer! import nlopt
import numpy as np
# pick algorithm
algorithm = nlopt.LD_LBFGS
# algo. options
vectorStorage = None
# set stopping criteria
xtolRel = -1
ftolAbs = 1e-6
# does not work as expected
maxeval = -1 # shouldn't this work the same as maxeval = 0?
# works as expected
#maxeval = 0
#maxeval = 50000
opt = nlopt.opt(algorithm, nmbParameters)
opt.set_maxeval(maxeval)
opt.set_xtol_rel(xtolRel)
opt.set_ftol_abs(ftolAbs)
if vectorStorage is not None:
opt.set_vector_storage(vectorStorage)
opt.set_min_objective(likelihood)
optimizedParameters = opt.optimize(startParameters)
status = self.opt.last_optimize_result() I was wondering if setting maxeval to -1 will make LBFGS act differently somehow. Thanks a lot for the help! |
@jschueller I managed to write a self-contained example: import nlopt
import numpy as np
import autograd.numpy as anp
from autograd import value_and_grad
# seed
seed = 42
rng = np.random.default_rng(seed)
# define likelihood
dim = 300
# start parameters
startParameters = rng.uniform(size=dim)
# generate 'data'
# random cov. mat.
sqrt_cov = rng.uniform(size=(dim,dim))
cov = sqrt_cov.T @ sqrt_cov
# random mean
mean = rng.uniform(size=dim)
# define negative log-likelihood
def negative_log_likelihood(x):
res = x-mean
return 0.5*res@cov@res
# ... and value and gradient
vgr_negative_log_likelihood = value_and_grad(negative_log_likelihood)
def f(x, grad):
negative_log_likelihood_value = 0
if grad.size > 0:
negative_log_likelihood_value, gradient = vgr_negative_log_likelihood(x)
grad[:] = gradient
else:
negative_log_likelihood_value = negative_log_likelihood(x)
return negative_log_likelihood_value
# pick algorithm
#algorithm = nlopt.LD_SLSQP # not affected!
algorithm = nlopt.LD_LBFGS # <- affected
#algorithm = nlopt.LD_VAR2 # <- affected
# algo. options
vectorStorage = None
# set stopping criteria
xtolRel = -1
ftolAbs = 1e-6
# does not work as expected
#maxeval = -1 # shouldn't this work the same as maxeval = 0?
# works as expected
#maxeval = 0
#maxeval = 50000
# iterate over test:
for maxeval in [None, -9999, -2, -1, 0, 10, 5000]:
opt = nlopt.opt(algorithm, dim)
if maxeval is not None:
opt.set_maxeval(maxeval)
opt.set_xtol_rel(xtolRel)
opt.set_ftol_abs(ftolAbs)
if vectorStorage is not None:
opt.set_vector_storage(vectorStorage)
opt.set_min_objective(f)
optimizedParameters = opt.optimize(startParameters)
status = opt.last_optimize_result()
print('############################################')
print(f'Results for maxeval={maxeval}:')
print('status:', status)
print('minimized objective function:', opt.last_optimum_value())
print('number of evaluations:', opt.get_numevals())
#print('parameter residuals:', optimizedParameters-mean) The output should be:
As you can see, setting maxeval to -1 or another negative value results in more iterations and a worse optimization result. I also tested (randomly) two other algorithms: nlopt.LD_SLSQP is not affected but nlopt.LD_VAR2 is. EDIT: I can also confirm that the issue appears also in version 2.8.0 |
Thanks, should be fixed by #571. |
Thank you for taking care of it so fast! |
Hello,
I noticed some unexpected behavior when disabling the 'maxeval' stopping criterion in the python interface in combination with the opt.LD_LBFGS algorithm.
1.) using a large upper number of max. evaluations
If I use opt.set_maxeval(very_large_integer) the optimization works as expected.
I get 'neval << very_large_integer' when the optimization is done.
2.) disabling with -1
If I try to disable the maximum number of evaluations completely using opt.set_maxeval(-1), I noticed very long optimization times in some settings. The number of function evaluation increases even though the number of function evaluation was much lower than 'very_large_integer' before.
3.) disabling with 0
If I, however, use opt.set_maxeval(0) the optimization works as expected and the number of function evaluations remains basically the same as when using a large upper limit.
From the documentation I would have expected both opt.set_maxeval(0) and opt.set_maxeval(-1) to behave identically.
To me it seems like setting it to a negative value additionally changes the behavior of other parameters. (Maybe some maximum number of line search steps?)
Maybe I missed a detail in the documentation, if so I am sorry for opening this issues.
Thank you very much in advance already!
The text was updated successfully, but these errors were encountered: