22

scipy.optimize.minimizeを使用して調整したいコンピュータービジョンアルゴリズムがあります。今は2つのパラメーターだけを調整したいのですが、最終的にはパラメーターの数が増える可能性があるので、高次元の勾配検索ができる手法を使用したいと思います。SciPyでのネルダーミードの実装はぴったりのようでした。

コードをすべて設定しましたが、minimize関数は、ステップサイズが1未満の浮動小数点値を実際に使用したいと考えているようです。現在のパラメーターのセットは両方とも整数であり、一方のステップサイズはもう一方です。ステップサイズは2です(つまり、値は奇数でなければなりません。最適化しようとしているものでない場合は、奇数に変換されます)。大まかに1つのパラメーターはピクセル単位のウィンドウサイズであり、もう1つのパラメーターはしきい値(0〜255の値)です。

価値があるのは、gitリポジトリからのscipyの新しいビルドを使用していることです。各パラメーターに特定のステップサイズを使用するようにscipyに指示する方法を知っている人はいますか?自分のグラデーション関数をロールする方法はありますか?私を助けることができるscipyフラグはありますか?これは単純なパラメータースイープで実行できることは承知していますが、最終的には、このコードをはるかに大きなパラメーターのセットに適用したいと思います。

コード自体は非常に単純です。

import numpy as np
from scipy.optimize import minimize
from ScannerUtil import straightenImg 
import bson

def doSingleIteration(parameters):
    # do some machine vision magic
    # return the difference between my value and the truth value

parameters = np.array([11,10])
res = minimize( doSingleIteration, parameters, method='Nelder-Mead',options={'xtol': 1e-2, 'disp': True,'ftol':1.0,}) #not sure if these params do anything
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
print res

これは私の出力がどのように見えるかです。ご覧のとおり、多くの実行を繰り返しており、最小化のどこにも到達していません。

*+++++++++++++++++++++++++++++++++++++++++
[ 11.  10.]  <-- Output from scipy minimize
{'block_size': 11, 'degree': 10} <-- input to my algorithm rounded and made int
+++++++++++++++++++++++++++++++++++++++++
120  <-- output of the function I am trying to minimize
+++++++++++++++++++++++++++++++++++++++++
[ 11.55  10.  ]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.   10.5]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.55   9.5 ]
{'block_size': 11, 'degree': 9}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.1375  10.25  ]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.275  10.   ]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.    10.25]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.275   9.75 ]
{'block_size': 11, 'degree': 9}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
~~~
SNIP 
~~~
+++++++++++++++++++++++++++++++++++++++++
[ 11.         10.0078125]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
Optimization terminated successfully.
         Current function value: 120.000000
         Iterations: 7
         Function evaluations: 27
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  status: 0
    nfev: 27
 success: True
     fun: 120.0
       x: array([ 11.,  10.])
 message: 'Optimization terminated successfully.'
     nit: 7*
4

5 に答える 5

6

最小化する関数が任意に複雑(非線形)であると仮定すると、これは一般に非常に難しい問題です。考えられるすべてのオプションを試さない限り、最適に解決されることを保証することはできません。整数制約付き非線形オプティマイザーがあるかどうかはわかりませが(多少疑わしいです)、Nelder-Meadが連続関数であれば正常に機能するはずです。

編集:@Dougalからのコメントを考慮して、ここに追加します:最初に粗いグリッドと細かいグリッドの検索を設定します。次にネルダーミードが機能する(そしてより速く収束する)かどうかを試したい場合は、以下のポイントが役立つ可能性があります...

しかし、おそらく役立ついくつかのポイント:

  1. 整数制約全体が非常に難しいことを考えると、オプティマイザーを支援するためにいくつかの単純な補間を行うオプションになるかもしれません。それでも整数解に収束するはずです。もちろん、これには余分なポイントを計算する必要がありますが、他の多くの問題を解決する可能性があります。(線形整数計画法でも、制約のないシステムを最初に解決するのが一般的です)
  2. Nelder-MeadはN+1ポイントで始まり、これらはscipy(少なくとも古いバージョン)で(1+0.05) * x0[j]( 0jでない限り、すべての次元で)に配線されx0[j]ています。これは、最初の評価ステップで表示されます。たぶん、これらは新しいバージョンで提供される可能性があります。そうでない場合は、scipyコード(純粋なPython)を変更/コピーして、より合理的なものに設定することができます。または、それがより簡単だと思う場合は、(1 + 0.05)*x0が適切なサイズになるようにすべての入力変数を縮小します。
  3. Nelder-Meadを使用する場合、(少なくとも最後に)常に重複評価に遭遇する可能性があるため、すべての関数評価をキャッシュする必要があります。
  4. Nelder-Meadは常に同じ結果を見つけるため、単一の値に縮小してあきらめる可能性を確認する必要があります。
  5. 通常、関数が正常に動作するかどうかを確認する必要があります...この最適化は、関数がパラメーター空間でスムーズに変化しない場合に運命づけられます。それでも、必要に応じて極小値に簡単にぶつかる可能性があります。(すべての評価をキャッシュしたので-2を参照してください。-少なくともそれらをプロットして、余分な評価を行うことなくエラーの状況を確認できます)
于 2012-08-29T17:13:33.227 に答える
2

残念ながら、Scipyの組み込みの最適化ツールではこれを簡単に行うことはできません。しかし、恐れることはありません。凸問題があるように聞こえるので、数学的にきれいでなくても、一意の最適化を見つけることができるはずです。

さまざまな問題に対して実装した2つのオプションは、カスタムの最急降下アルゴリズムを作成することと、一連の単変量問題に二分法を使用することです。チューニングで交差検定を行っている場合、残念ながら損失関数は滑らかではありませんが(異なるデータセットでの交差検定からのノイズのため)、一般的に凸関数になります。

最急降下法を数値的に実装するには(勾配を評価するための分析方法がない場合)、deltaすべての次元でテストポイントとテストポイントから離れた2番目のポイントを選択します。これらの2つのポイントで損失関数を評価すると、局所劣勾配を数値的に計算できます。delta交差検定ノイズによって作成された極小値の外側に出るのに十分な大きさであることが重要です。

低速ですが、潜在的により堅牢な代替手段は、テストしているパラメーターごとに二等分線を実装することです。2つのパラメーター(またはn個のパラメーター)で共同で凸の問題がわかっている場合は、これをn個の単変量最適化問題に分離し、最適なパラメーターに再帰的に焦点を当てる二分アルゴリズムを記述できます。これは、いくつかのタイプの準凸性を処理するのに役立ちます(たとえば、損失関数がそのドメインの一部のバックグラウンドノイズ値を取り、別の領域で凸状である場合)が、最初の反復の境界について適切な推測が必要です。

xそのグリッドサイズにマップするように修正せずに、要求された値を整数グリッドにスナップするだけの場合xtol、ソルバーがグリッドセル内の2つのポイントを要求し、同じ出力値を受け取り、それが最小であると結論付けるリスクがあります。

残念ながら、簡単な答えはありません。

于 2015-12-09T23:52:23.657 に答える
1

次のように、float x、y(別名winsize、threshold)を関数の整数グリッドにスナップします。

def func( x, y ):
    x = round( x )
    y = round( (y - 1) / 2 ) * 2 + 1  # 1 3 5 ...
    ...

次に、Nelder-Meadはグリッド上でのみ関数値を表示し、整数に近いx、yを提供するはずです。

(コードをどこかに投稿したい場合は、再起動機能を備えたNelder-Meadのテストケースを探しています。)

于 2012-08-30T16:21:01.743 に答える
1

Nelder-Mead最小化メソッドでは、初期シンプレックス頂点ポイントを指定できるようになったため、シンプレックスポイントを遠くに設定できるはずです。シンプレックスは、フロップして最小値を見つけ、シンプレックスサイズが1を下回ると収束します。

https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html#optimize-minimize-neldermead

于 2017-03-27T21:55:56.583 に答える
1

問題は、アルゴリズムが(N + 1)シンプレックスを縮小しようとしてスタックすることです。この概念に不慣れな人は、シンプレックスの地理的形状について詳しく学び、入力パラメーターがシンプレックス上のポイントにどのように関連しているかを理解することを強くお勧めします。それを理解したら、IP Freeleyが提案したように、シンプレックスの強力な初期点を定義することで問題を解決できます。これはx0の定義とは異なり、ネルダーミードの専用オプションに入ることに注意してください。これは、より高い-4-次元の問題の例です。また、最初のシンプレックスには、この場合は5、この場合は3のN+1ポイントが必要であることに注意してください。

init_simplex = np.array([[1, .1, .3, .3], [.1, 1, .3, .3], [.1, .1, 5, .3],
                         [.1, .1, .3, 5], [1, 1, 5, 5]])
minimum = minimize(Optimize.simplex_objective, x0=np.array([.01, .01, .01, .01]),
                   method='Nelder-Mead',
                   options={'adaptive': True, 'xatol': 0.1, 'fatol': .00001,
                            'initial_simplex': init_simplex})

この例では、x0はinitial_simplexの定義によって無視されます。高次元の問題における他の有用なオプションは、「適応」オプションです。これは、モデルの操作係数(つまり、反射、膨張、収縮、収縮のそれぞれのα、γ、ρ、σ)を設定しようとするときに、パラメーターの数を考慮に入れます。 。また、まだ行っていない場合は、アルゴリズムの手順をよく理解しておくことをお勧めします。

さて、この問題が発生している理由は、メソッドが拡張で良い結果を得られないため、シンプレックスをどんどん小さくして、存在するかもしれないし存在しないかもしれないより良い解決策を見つけようとしているからです。

于 2021-01-28T19:51:11.023 に答える