在Python中为fmin_ncg提供Hessian

3 投票
1 回答
559 浏览
提问于 2025-04-16 20:45

对于SciPy中的函数 fmin_ncg,有没有办法把海森矩阵和梯度作为变量提供,而不是作为函数?

我正在把一些Matlab代码改写成Python。这段代码涉及使用优化程序来调整一些参数以适应一组数据。为此,我提供了梯度和海森矩阵。比如在Matlab中,我有这样的代码:

fmincon(@myFunc,x0,[],[],[],[],lb,ub,[],options);

其中 myFunc 返回三个值:函数的计算结果、梯度和海森矩阵。

但是在Python的 fmin_ncg 中,似乎梯度和海森矩阵必须作为单独的函数提供。

我觉得这样效率不高,因为代码需要处理大量数据,而函数、梯度和海森矩阵之间有一些共同的计算。比如,想象一个函数 f(x) = a(x)*b(x),它的梯度是 g(x) = a(x)*c(x),海森矩阵是 h(x) = a(x)*d(x) ... 在Matlab中,我可以只计算一次 a(x),而在Python中,似乎我必须计算三次。

我是不是误解了 fmin_ncg 的工作原理,或者有没有其他解决办法?

1 个回答

4

你可以创建一个类,把你所有的函数都放在里面。每次运行的时候,第一次调用函数时会计算一些共同的变量,然后后面的调用就可以重复使用这些变量。fmin_ncg的回调功能可以用来在每次运行结束时重置这些共同的变量。

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

你可以这样使用它。

f = function()
fmin_ncg(f.calcFunction,x0,f.calcGradient,fhess=f.calcHessian,callback=f.resetCommonVars)

这样做会增加一些额外的开销,所以只有在计算共同变量的工作量比较大的时候,这样做才有意义。

撰写回答