Reputation: 71
For the SciPy function fmin_ncg
, is there a way of suppling the hessian and gradient as a variable rather than a function?
I'm trying to rewrite some Matlab code in python. The code involves using an optimisation routine to fit some parameters to a set of data. To do this, I've supplied the gradient and hessian. E.g in Matlab I have something like this:
fmincon(@myFunc,x0,[],[],[],[],lb,ub,[],options);
where myFunc
returns 3 values: the function evaluation, the gradient, and the hessian.
However for fmin_ncg
in Python it appears that the gradiant and hessian must be supplied as separate functions.
To me this seems inefficient as the code has to go through a large dataset, and there are calculations that are common to the function, the gradient and the hessian. e.g. Imagine a function f(x) = a(x)*b(x)
with gradient g(x) = a(x)*c(x)
, hessian h(x) = a(x)*d(x)
... in Matlab I can calculate a(x)
once, where as it appears that i have to calculate this three times in python.
Have I misunderstood how fmin_ncg
works or is there a way around this?
Upvotes: 3
Views: 566
Reputation: 3439
You can create a class that includes all of your functions. Each iteration, the common variables are calculated during the first function call, then are reused for the other calls. The callback feature of fmin_ncg
can be used to reset the common variables at the end of each iteration.
class function(object):
def __init__(self):
self.commonVarsDirty = True
def calcFunction(self,x,*args,**kwargs):
if self.commonVarsDirty:
self.calcCommonVars()
return self.a*b
def calcGradient(self,x,*args,**kwargs):
if self.commonVarsDirty:
self.calcCommonVars()
return self.a*c
def calcHessian(self,x,*args,**kwargs):
if self.commonVarsDirty:
self.calcCommonVars()
return self.a*d
def resetCommonVars(self,*args,**kwargs):
self.commonVarsDirty = True
def calcCommonVars(self):
self.commonVarsDirty = False
# calculate common variables and save them as class attributes
self.a = 1+1
You would use it like this.
f = function()
fmin_ncg(f.calcFunction,x0,f.calcGradient,fhess=f.calcHessian,callback=f.resetCommonVars)
This adds some overhead so would only be worth it if the computation effort to calculate the common variables is significant.
Upvotes: 4