scipy.optimize.fmin_bfgs single function computes both f and fprime
gradient, optimization, python, scipy
Solution
If you're trying to save on computation time rather than just combine the calculation of `f` and `f'` for code convenience, it seems like you need an extra wrapper around your function to cache values, since `fmin_bfgs` doesn't seem to allow you to pass such a function (unlike some other optimization functions).
Here's one way to do that, maintaining the 10 most recently evaluated points in a little cache. (I'm not sure whether calls to this function need to be thread-safe: probably not, but if so, you'll probably need to add some locking in here, I guess.)
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 don't repeat any evaluations.
Problem
I'm using `scipy.optimize.fmin_bfgs(f, init_theta, fprime)` to minimize `f`, which has gradient `fprime`. I compute `f` and `fprime` in a single function because most of the computation is the same so there's no need to do it twice. Is there any way to call `fmin_bfgs()` specifying a single function that returns both `f` and `fprime`?