If you are trying to save the calculation time, and not just combine the calculations of f
and f'
for the convenience of the code, it seems that you need an additional shell around the function for caching values, since fmin_bfgs
does not seem to allow you to pass such a function (unlike some other optimization functions).
Here is one way to do this by supporting the 10 most recently rated points in a small cache. (I'm not sure if calls to this function should be thread safe: maybe not, but if so, you probably need to add some locks here.)
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)
If we then do
>>> 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.])
we can see that we are not repeating any ratings.
source share