我正在尝试定义一个类,在该类中优化了许多变量的函数。通常我正在使用~500-1000个变量。在这个课程中,我需要将函数及其派生函数传递给minimize
中的scipy
,以找到最小化此函数的x0
。
以下是该概念的一个简单的工作示例,它工作正常。但正如你所看到的那样,函数(f
)及其派生(df
)依赖于另一个函数g
(在这个例子中,它看起来很简单,可以用另一种方式编写,但实际上功能要复杂得多)。
我想知道我是否可以在每次迭代时只计算g
一次,然后在该类中使用该值。考虑到f
和df
在minimize
多次更新,因此每个步骤g
也应重新评估。
谢谢!
from scipy.optimize import minimize
class Minimization(object):
'''A class to optimizae a function'''
def __init__(self,x,y):
self.x = x
self.y = y
self.p = np.array([x,y])
def g(self,x,y):
return x-y
def f(self,p):
return (self.g(*p) - 1)**2
def df(self,p):
fprime = 2*(self.g(*p) - 1)
return np.array([fprime,-fprime])
def optimize(self):
P1 = minimize(fun=self.f, x0=self.p, args=(), method='Newton-CG',jac=self.df)
return P1
m = Minimization(2,4)
m.optimize()
#fun: 0.0
# jac: array([ 0., -0.])
#message: 'Optimization terminated successfully.'
# nfev: 3
# nhev: 0
# nit: 2
#njev: 6
#status: 0
#success: True
# x: array([ 3.5, 2.5])
答案 0 :(得分:1)
如果没有深入研究代码本身,这里有一个示例类来演示如何计算一次值并避免在每次调用时重新计算它。你也可以把它变成一个属性。
class StackOverflow:
def __init__(self, value=None):
self._value = value
def compute_value(self):
if self._value is None:
self._value = 100 # Compute value here
return self._value
答案 1 :(得分:1)
你想要的是“记忆”。当函数g计算一个值时,它将结果存储在字典中,由参数x,y索引。每次调用g时,它都会检查字典以查看它所需的值是否已经存储在那里。如果需要重置值,请清除字典。像这样:
class Minimization(object):
'''A class to optimizae a function'''
def __init__(self,x,y):
self.x = x
self.y = y
self.p = np.array([x,y])
self.cache = {} # previously computed values of g
def g(self,x,y):
cache_index = (x, y)
if cache_index in self.cache: # check cache first
return self.cache[cache_index]
value = x - y
self.cache[cache_index] = value # save for later
return value
def f(self,p):
return (self.g(*p) - 1)**2
def df(self,p):
fprime = 2*(self.g(*p) - 1)
return np.array([fprime,-fprime])
def optimize(self):
self.cache.clear() # Blow the cache
P1 = minimize(fun=self.f, x0=self.p, args=(), method='Newton-CG',jac=self.df)
return P1
答案 2 :(得分:1)
为了补充Paul的答案,您可以定义一个类聚合缓存的方法,然后您将(重新)用作装饰器。
Cache
然后使用班级Minimization
作为import numpy as np
from scipy.optimize import minimize
class Minimization(Cache):#<----------Inherits of Cache instead of object
'''A class to optimizae a function'''
def __init__(self,x,y):
super(Minimization,self).__init__()
self.x0 = x # I changed the names because as it stands,
self.y0 = y # these attributes are actually used as first guesses
self.p0 = np.array([x,y]) # for the resolution process
@Cache._method
def g(self, x, y):
return x - y
#@Cache._method
def f(self,p):
return (self.g(*p) - 1)**2
#@Cache._method
def df(self,p):
fprime = 2*(self.g(*p) - 1)
return np.array([fprime,-fprime])
@Cache._property
def optimized(self):#<----- I changed the name into optimized to make it representative of what it is, a property
return minimize(fun=self.f, x0=self.p0, args=(), method='Newton-CG',jac=self.df)
的祖先,如下所示
>>> m = Minimization(2,4)
>>> # Take care to clear the cache if optimized is not called for the first time and that you changed one of its "dependencies", doing m._cache.clear().
>>> # something you may want to do is simply removing the @Cache._property decorator
>>> m.optimized
status: 0
success: True
njev: 6
nfev: 3
fun: 0.0
x: array([ 3.5, 2.5])
message: 'Optimization terminated successfully.'
nhev: 0
jac: array([ 0., -0.])
用例 (在Python 2.7.11和3.6.1下测试)
input="$(
sudo gdb -n -q -batch-silent \
-ex "set logging on" \
-ex "set logging file /dev/null" \
-ex "set logging redirect on" \
-ex "attach $PID" \
-ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \
-ex "call \$dlopen(\"/$filename\", 1)" \
-ex "detach" \
-ex "quit"
)"