Si vous essayez de économiser sur le temps de calcul plutôt que de simplement combiner le calcul de f
et f'
pour la commodité du code, il semble que vous avez besoin d'un wrapper supplémentaire autour de votre fonction pour mettre en cache les valeurs, car fmin_bfgs
ne semblent vous permettre de passer une telle fonction (contrairement à d'autres fonctions d'optimisation).
Voici une façon de le faire, en conservant les 10 points les plus récemment évalués dans un petit cache. (Je ne suis pas sûr que les appels à cette fonction doivent être thread-safe: probablement pas, mais si oui, vous aurez probablement besoin d'ajouter un peu de verrouillage ici, je suppose.)
def func_wrapper(f, cache_size=10):
evals = {}
last_points = collections.deque()
def get(pt, which):
s = pt.tostring() # get binary string of numpy array, to make it hashable
if s not in evals:
evals[s] = f(pt)
last_points.append(s)
if len(last_points) >= cache_size:
del evals[last_points.popleft()]
return evals[s][which]
return functools.partial(get, which=0), functools.partial(get, which=1)
Si nous alors faites
>>> def f(x):
... print "evaluating", x
... return (x-3)**2, 2*(x-3)
>>> f_, fprime = func_wrapper(f)
>>> optimize.fmin_bfgs(f_, 1000, fprime)
evaluating [ 994.93480441]
evaluating [ 974.67402207]
evaluating [ 893.63089268]
evaluating [ 665.93446894]
evaluating [ 126.99931561]
evaluating [ 3.]
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 4
Function evaluations: 7
Gradient evaluations: 7
array([ 3.])
nous pouvons voir que nous ne répétons aucune évaluation.
Belle implémentation! J'ai pensé à essayer d'utiliser cette stratégie, mais je n'étais pas sûr de savoir comment faire un tableau lavable. En outre, j'espérais qu'il y avait une fonctionnalité déjà construite dans scipy.optimize pour gérer cela.Apparemment, d'autres ont demandé la fonctionnalité parce qu'elle est supposée faire partie de Scipy 0.11, qui n'est pas encore publiée. Merci de fournir ce motif de conception! – user1389890