2016-10-12 7 views
3

scipy.optimizeは、多変量解析システムの局所最適化と大域最適化のためのさまざまな方法を提供します。しかし、私は中断する可能性のある非常に長い時間の最適化を実行しています(場合によっては意図的に中断したい場合もあります)。再起動する方法はありますか?まあ、いずれか?つまり、最初の推測として見つかった最後の、最も最適化されたパラメータセットを提供できることは明らかですが、それは唯一のパラメータではありません。たとえば、グラディエント(ジャコバンなど)、微分進化における集団など私は明らかにこれもやり直さなくてもいいと思っています。scipy.optimizeで最適化を再開しますか?

私はこれらをscipyに証明することも、その状態を保存することもほとんどありません。たとえば、ジャコビアン(jacobian)の引数( "jac")がありますが、それはブール値(評価関数がジャコビアンを返すことを示しています)、呼び出し可能な関数提供する最後の実行から単一の結果を持っている)。最後のジャコビアが利用できるだけの配列はありません。微分進化では、人口の損失は、パフォーマンスとコンバージェンスにとって恐ろしいものになります。

解決方法はありますか?最適化を再開する方法はありますか?

+0

私が思い付くした最高のは、ほとんどunthinkably醜いです:1つ以上の「ブレークポイント」のバージョン(あなたの現在実行中の最適化機能の正確なコピーを持つプロセスを作成するプロセスをフォーク - そしてその時、アプリケーション全体!)、ブレークポイント・バージョンをオプティマイザのコールバックまたは評価呼び出しにハングアップさせて、何らかのIPCによって後続するように通知されるか、または廃止された場合には強制終了されます。もちろん、あなたはまだ同じランであるので "ラン"間のパラメータを変更することはできませんでした!再起動しても保持されません。そしてちょっと醜い... – KarenRei

+0

1) 'jac'があなたの関数ならば、* kwargを使って、最初の呼び出しで' xx.jac'を読み込んで返すように簡単に言うことができます。 2)オプティマイザは、具体的には、 3)あなたはしばらく実行したい印刷物/プロット/保存するツリーを実行したいですか?大きな注文。 "A10 =ラン10; A100 =ラン100; B =(A;パラムス= ...;ラン100)..."と表示されます。 – denis

+0

私は、最適化の方法をベンチマークしていないので、どれが最適なものかを知ることができません。パフォーマンスと正確さのために私の評価機能を調整してきました。私は、例えば、それが極小に閉じ込められてしまう傾向があるかどうか、何の手がかりも持っていません。 "jac"は私の評価関数ではありません。それは、最小化関数がジャコビアン(一階微分/勾配)の決定方法を指定するという議論です。実行ツリーは素晴らしいですが、単一のチェックポイントを維持することさえ可能ですばらしいでしょう。どのようにして1つの "100回"反復を維持することができますか? – KarenRei

答えて

2

一般的な答えはいいえ、前回の実行からの最後の見積もりから始めて、あなたが言うように一般的な解決策はありません。

具体的には差分進化については、DifferentialEvolutionSolverをインスタンス化することができます。これをチェックポイントでピクルして再開すると、再開できます。 (提案はhttps://github.com/scipy/scipy/issues/6517から来ている)

0

次は、例えば、保存して、前のxから再起動し、 が、私はあなたがより多くの状態を保存し、再起動します集めることができます勾配も。それを明確にすることはできますか?

も参照してください。basinhopping、 これはすばらしいGUIを持っています。pele-pythonです。

#!/usr/bin/env python 
""" Funcgradmn: wrap f() and grad(), save all x[] f[] grad[] to plot or restart """ 

from __future__ import division 
import numpy as np 

__version__ = "2016-10-18 oct denis" 


class Funcgradmon(object): 
    """ Funcgradmn: wrap f() and grad(), save all x[] f[] grad[] to plot or restart 

    Example: minimize, save, restart -- 

    fg = Funcgradmon(func, gradfunc, verbose=1) 
     # fg(x): f(x), g(x) for minimize(jac=True) 

     # run 100 iter (if linesearch, 200-300 calls of fg()) -- 
    options = dict(maxiter=100) # ... 
    min0 = minimize(fg, x0, jac=True, options=options) 
    fg.savez("0.npz", paramstr="...") # to plot or restart 

     # restart from x[50] -- 
     # (won't repeat the previous path from 50 
     # unless you save and restore the whole state of the optimizer) 
    x0 = fg.restart(50) 
    # change params ... 
    min50 = minimize(fg, x0, jac=True, options=options) 
    """ 

    def __init__(self, func, gradfunc, verbose=1): 
     self.func = func 
     self.gradfunc = gradfunc 
     self.verbose = verbose 
     self.x, self.f, self.g = [], [], [] # growing lists 
     self.t = 0 

    def __call__(self, x): 
     """ f, g = func(x), gradfunc(x); save them; return f, g """ 
     x = np.asarray_chkfinite(x) # always 
     f = self.func(x) 
     g = self.gradfunc(x) 
     g = np.asarray_chkfinite(g) 
     self.x.append(np.copy(x)) 
     self.f.append(_copy(f)) 
     self.g.append(np.copy(g)) 
     if self.verbose: 
      print "%3d:" % self.t , 
      fmt = "%-12g" if np.isscalar(f) else "%s\t" 
      print fmt % f , 
      print "x: %s" % x , # with user's np.set_printoptions 
      print "\tgrad: %s" % g 
       # better df dx dg 
     # callback: plot 
     self.t += 1 
     return f, g 

    def restart(self, n): 
     """ x0 = fg.restart(n) returns x[n] to minimize(fg, x0) 
     """ 
     x0 = self.x[n] # minimize from here 
     del self.x[:n] 
     del self.f[:n] 
     del self.g[:n] 
     self.t = n 
     if self.verbose: 
      print "Funcgradmon: restart from x[%d] %s" % (n, x0) 
     return x0 

    def savez(self, npzfile, **kw): 
     """ np.savez(npzfile, x= f= g=) """ 
     x, f, g = map(np.array, [self.x, self.f, self.g]) 
     if self.verbose: 
      asum = "f: %s \nx: %s \ng: %s" % (
       _asum(f), _asum(x), _asum(g)) 
      print "Funcgradmon: saving to %s: \n%s \n" % (npzfile, asum) 
     np.savez(npzfile, x=x, f=f, g=g, **kw) 

    def load(self, npzfile): 
     load = np.load(npzfile) 
     x, f, g = load["x"], load["f"], load["g"] 
     if self.verbose: 
      asum = "f: %s \nx: %s \ng: %s" % (
       _asum(f), _asum(x), _asum(g)) 
      print "Funcgradmon: load %s: \n%s \n" % (npzfile, asum) 
     self.x = list(x) 
     self.f = list(f) 
     self.g = list(g) 
     self.loaddict = load 
     return self.restart(len(x) - 1) 


def _asum(X): 
    """ one-line array summary: "shape type min av max" """ 
    if not hasattr(X, "dtype"): 
     return str(X) 
    return "%s %s min av max %.3g %.3g %.3g" % (
      X.shape, X.dtype, X.min(), X.mean(), X.max()) 

def _copy(x): 
    return x if x is None or np.isscalar(x) \ 
     else np.copy(x) 

#............................................................................... 
if __name__ == "__main__": 
    import sys 
    from scipy.optimize import minimize, rosen, rosen_der 

    np.set_printoptions(threshold=20, edgeitems=10, linewidth=140, 
      formatter = dict(float = lambda x: "%.3g" % x)) # float arrays %.3g 

    dim = 3 
    method = "cg" 
    maxiter = 10 # 1 linesearch -> 2-3 calls of fg 

    # to change these params, run this.py a=1 b=None 'c = ...' in sh or ipython 
    for arg in sys.argv[1:]: 
     exec(arg) 

    print "\n", 80 * "-" 
    print "Funcgradmon: dim %d method %s maxiter %d \n" % (
      dim, method, maxiter) 
    x0 = np.zeros(dim) 

    #........................................................................... 
    fg = Funcgradmon(rosen, rosen_der, verbose=1) 
    options = dict(maxiter=maxiter) # ... 

    min0 = minimize(fg, x0, jac=True, method=method, options=options) 
    fg.savez("0.npz", paramstr="...") # to plot or restart 

    x0 = fg.restart(5) # = fg.x[5] 
    # change params, print them all 
    min5 = minimize(fg, x0, jac=True, method=method, options=options) 

    fg.savez("5.npz", paramstr="...") 
関連する問題