Согласно обратному вызову docs должен вызываться вызов, возвращающий True
для завершения и имеющий следующий формат callback(xk)
.Принимая во внимание, что в вашем коде вы определяете его как инициализацию вашего класса.Вместо этого вы должны определить экземпляр вашего класса, а затем присвоить его __call__()
функцию callback
следующим образом:
import time
import warnings
import numpy as np
from scipy.optimize import minimize, rosen
class TookTooLong(Warning):
pass
class MinimizeStopper(object):
def __init__(self, max_sec=10):
self.max_sec = max_sec
self.start = time.time()
def __call__(self, xk):
# callback to terminate if max_sec exceeded
elapsed = time.time() - self.start
if elapsed > self.max_sec:
warnings.warn("Terminating optimization: time limit reached",
TookTooLong)
else:
# you might want to report other stuff here
print("Elapsed: %.3f sec" % elapsed)
# init stopper
minimize_stopper = MinimizeStopper()
# minimze
res = minimize(rosen,
x0 = np.random.randint(5, size=128),
method ="BFGS",
tol = 0.01,
options = {"maxiter":10, "disp":True},
callback = minimize_stopper.__call__)
В качестве альтернативы вы можете определить класс для вашего минимизатора и построить в нем функцию обратного вызова.прекратить минимизацию через определенное время.Это можно сделать следующим образом:
import time
import warnings
import numpy as np
from scipy.optimize import minimize, rosen
class TookTooLong(Warning):
pass
class Minimizer:
def __init__(self, timeout, maxiter):
self.timeout = timeout
self.maxiter = maxiter
def minimize(self):
self.start_time = time.time()
# minimize
res = minimize(rosen,
x0 = np.random.randint(5, size=128),
method ="BFGS",
tol = 0.01,
options = {"maxiter":self.maxiter, "disp":True},
callback = self.callback)
return res
def callback(self, x):
# callback to terminate if max_sec exceeded
elapsed = time.time() - self.start_time
if elapsed > self.timeout:
warnings.warn("Terminating optimization: time limit reached",
TookTooLong)
return True
else:
print("Elapsed: %.3f sec" % elapsed)
# init minimizer and minimize
minimizer = Minimizer(0.1, 100)
result = minimizer.minimize()
Проверьте этот код с помощью: timeout=0.1 & maxiter=100
затем timeout=10 & maxiter=10
, чтобы наблюдать оба типа завершения.