2017-03-16 14 views
2

最小化の問題とそのヤコビ行列の制約と、ヤコビ行列をほとんど無料で得る点。計算を共有する方法はありますか?scipy.optimize.minimize、制約とそれらのヤコビアンを一度に計算する

+0

例を追加できますか? – Cleb

+0

関数はPythonのファーストクラスの市民であるため、jacobianとconstraintの両方を扱う関数を定義し、共通のものを格納するためにインスタンス属性を使用することができます。しかし、あなたは何とか最初に呼び出されたものを何とか処理しなければならないでしょう。たぶん 'コールバック 'でフラグを設定するのでしょうか?私は唯一推測している、私は遠く離れた何かをしたことはない。 –

答えて

2

制約とヤコビアンは常に評価されるとは限らないので、ほんの少しの改善しか期待できません。しかし、あなたは別の関数/メソッドに一般的な計算を置くことができる場合は、後でそれらを再計算する必要がないように、あなたはその戻り値をcacheことができます。

import scipy.optimize as opt 
from functools import lru_cache 

# only for the dummy example: 
import scipy as sp 
from time import sleep 

def cost(x): 
    '''dummy cost function to minimize on [1,11]''' 
    return sp.log(x) 

@lru_cache(maxsize=None) # careful with this choice 
def heavy_stuff(x): 
    '''idle computation representing common work in constraint and jacobian''' 
    sleep(0.1) 
    return 0 

def constraint(x): 
    '''constraint for [1,11], with simulated idle work''' 
    # the following only works for 1d arrays, needs more work for nd 
    throwaway = heavy_stuff(tuple(x)) 
    return 5 - abs(6 - x) # non-negative between 1 and 11 

def jacobian(x): 
    '''return the jacobiam with the same simulated idle work''' 
    throwaway = heavy_stuff(tuple(x)) 
    return 1/x 

x0 = 11 
tol = 0 
opts = {'disp': True} 
cons = {'type': 'ineq', 'fun': constraint} 
kwargs = {'method':'SLSQP', 'constraints': cons, 
      'jac': jacobian, 'tol': tol, 'options': opts} 
res = opt.minimize(cost,x0,**kwargs) 
print(heavy_stuff.cache_info()) 

log(x)を最小化しようとする試み上記のダミーの例は、区間[1,11]。一定の境界の代わりに私は間隔を与える制約を定義したので、あなたの質問に関して私が意味することを示すことができます。

constraintjacobianは同じ作業を行いますが、これは同じ引数で複数の評価が行われた場合に備えておきたいことです。これらの共通の計算をすべて共通の関数(ここではheavy_stuff)に入れ、戻り値をconstraintjacobianの両方で使用する必要があります。

重いものをメモするには、functools.lru_cacheを使用する必要があります。適切なキャッシュサイズを設定することにより、複数の評価heavy_stuffが同じxになると、計算をやり直すことなく、以前に計算された戻り値が一度に得られます。

私の疑惑が正しい場合はmaxsize=1で、おそらくlru_cacheデコレータで十分です。 maxsize=None(上限なし)を設定すると、正当な理由であまりにも多くのメモリを失う危険があります。あなたは実験して、複数のメモ化された値が必要かどうか、またはいくつかの唯一の値が十分かどうかを確認する必要があります。

ただし、lru_cacheは、キーが装飾された関数の入力パラメータである以前に計算された結果を検索するためにdictを使用することに注意してください。これは、入力引数がハッシュ可能でなければならないことを意味します。これは実際には不変でなければならないことを意味します。ナンシー配列はリストと非常によく似ていて、同様にではなく、ハッシュ可能です。このため、heavy_stufftuple(x)と呼びます.1dの配列入力はタプルに変換されます。 xが多次元配列である場合、入れ子の各レベルはタプルに変換する必要があります。さらに悪いことに、heavy_stuffは、タフプルをnumpy ndarraysに変換して、重い作業を行う必要があります。しかし、ジャコビー/コンストレインを計算するのが実際にこのCPUを大量に使用する場合は、おそらく全体的にはまだ良いでしょう。

キャッシュのパフォーマンスを評価する場合は、末尾にheavy_stuff.cache_info()が表示されます。キャッシュされた値が使用された頻度、および新しい値が何回計算されなければならなかったかを示します。

関連する問題