5

私はscipy.optimize.fmin_bfgs(f, init_theta, fprime)最小化するために使用してfいますが、これには勾配がありfprimeます。ほとんどの計算は同じであり、2 回行う必要がないため、1 つの関数でfandを計算します。fprime

と の両方をfmin_bfgs()返す単一の関数を指定して呼び出す方法はありますか?ffprime

4

3 に答える 3

4

fコードの利便性のためにとの計算を組み合わせるだけでなく、計算時間を節約しようとしている場合は、そのような関数を渡すことができないように見えるためf'、値をキャッシュするために関数の周りに追加のラッパーが必要なようです。fmin_bfgs(他の最適化関数とは異なります)。

これを行う 1 つの方法として、最近評価された 10 個のポイントを小さなキャッシュに保持します。(この関数の呼び出しがスレッドセーフである必要があるかどうかはわかりません。おそらくそうではありませんが、そうであれば、おそらくここにロックを追加する必要があると思います。)

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)

もしそうなら

>>> 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.])

評価を繰り返さないことがわかります。

于 2012-05-23T03:50:08.110 に答える
1

f(x)関数値と勾配の両方を返すPython 関数があるとします。

In [20]: def f(x):
   ....:     return (x-3)**2, 2*(x-3)

次に、出力を次のように個別に渡します。

In [21]: optimize.fmin_bfgs(lambda x: f(x)[0], 1000, lambda x: f(x)[1])
Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 4
         Function evaluations: 7
         Gradient evaluations: 7
Out[21]: array([ 3.])
于 2012-05-23T03:36:07.370 に答える