Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

ソルバーが失敗する場合

過剰な反復または関数評価

目的関数が要求された許容誤差に最小化される前に、反復または関数評価の回数が上限に達したため、ソルバーは停止しました。継続するには、以下の 1 つ、またはいくつかを試してください。

1.反復表示の有効化
2.許容誤差の緩和
3.異なる点からソルバーを開始
4.目的関数と制約関数の定義を確認
5.問題のセンタリングとスケーリング
6.勾配またはヤコビアンの指定
7.ヘッシアンの供給

1.反復表示の有効化

Display オプションを 'iter' に設定します。この設定により、ソルバー反復の結果が表示されます。

MATLAB® コマンド ラインで反復表示を有効にするには、次を入力します。

options = optimoptions('solvername','Display','iter');

options 構造体を使用して、ソルバーを呼び出します。

反復表示の例については、結果の解釈を参照してください。

反復表示内で何を探すか

  • 目的関数 (Fvalf(x)Resnorm) が減少するかどうかを観察します。減少すれば、進行していることを示します。

  • それが確実に 0 に減少するように、制約違反 (Max constraint) を調べます。減少すれば、進行していることを示します。

  • 1 次の最適性が 0 に向かって減少するかどうかを観察します。減少すれば、進行していることを示します。

  • Trust-region radius が小さい値に減少するかどうか観察します。この減少は、対象が滑らかでないかもしれないことを示します。

何をすべきか

  • ソルバーが進行していると思われる場合:

    1. MaxIterationsMaxFunctionEvaluations を既定値よりも大きく設定します。ソルバーの関数リファレンス ページにあるオプションの表で既定値を確認できます。

    2. その最後に計算された点からソルバーを開始します。

  • ソルバーが進行していない場合は、リストされている他の推奨操作を試してください。

2.許容誤差の緩和

たとえば、StepToleranceOptimalityTolerance が小さすぎると、いつそれが最小値に達したかをソルバーが認識しないかもしれません。無制限に無益な反復を行う可能性があります。

コマンド ラインで許容誤差を変更するには、最適化オプションの設定と変更で説明するように、関数 optimoptions を使用します。

FiniteDifferenceStepSize オプション (または、DiffMaxChange および DiffMinChange オプション) はソルバーの進行に影響する可能性があります。これらのオプションは、導関数値推定のための有限差分のステップ サイズを制御します。

3.異なる点からソルバーを開始

「初期点の変更」を参照してください。

4.目的関数と制約関数の定義を確認

たとえば、目的関数と非線形制約関数が任意の点で正しい値を返すことを確認します。「目的関数と制約関数の確認」を参照してください。実行不可能な点で関数がエラーを起こさないことを確認します。反復は制約に違反する可能性ありを参照してください。

5.問題のセンタリングとスケーリング

各座標が目的関数と制約関数にほぼ同じ影響を与える場合に、ソルバーはより高い信頼性をもって機能します。座標軸の各方向に適切なスカラーを乗算することにより各座標の影響を均等化します。適切な値を特定の座標に追加し、それらのサイズを均等化します。

例: センタリングとスケーリング.  1e6*x(1)^2 + 1e-6*x(2)^2 の最小化を考えます。

f = @(x) 10^6*x(1)^2 + 10^-6*x(2)^2;

fminunc 'quasi-newton' アルゴリズムを使用して f を最小化します。

opts = optimoptions('fminunc','Display','none','Algorithm','quasi-newton');
x = fminunc(f,[0.5;0.5],opts)

x =
         0
    0.5000

結果は正しくありません。不適切なスケーリングにより良い解の取得が妨げられました。

問題をスケーリングします。次を設定します

D = diag([1e-3,1e3]);
fr = @(y) f(D*y);
y = fminunc(fr, [0.5;0.5], opts)

y =
     0
     0 % the correct answer

同様に、不適切なセンタリングにより解が妨げられる可能性があります。

fc = @(z)fr([z(1)-1e6;z(2)+1e6]); % poor centering
z = fminunc(fc,[.5 .5],opts)

z =
  1.0e+005 *
   10.0000  -10.0000 % looks good, but...

z - [1e6 -1e6] % checking how close z is to 1e6

ans =

   -0.0071    0.0078 % reveals a distance


fcc = @(w)fc([w(1)+1e6;w(2)-1e6]); % centered

w = fminunc(fcc,[.5 .5],opts)

w =
     0     0 % the correct answer

6.勾配またはヤコビアンの指定

勾配またはヤコビアンが提供されない場合、ソルバーは有限差分法によって勾配とヤコビアンを推定します。つまり、これらの導関数を提供することにより、計算時間の節約や精度の向上が期待できます。問題ベースのアプローチは、自動的に勾配を提供できます。Optimization Toolbox の自動微分を参照してください。

制約問題の場合は、勾配を与えることで別の利点があります。ソルバーは、x それ自体は実行可能だが、x の周囲の有限差分は常に実行不可能な点へ導くような点 x に到達することがあります。この場合、ソルバーは失敗するか途中で停止する可能性があります。勾配を与えることで、ソルバーは続行できます。

目的関数と非線形制約関数を定義するファイル内に、勾配またはヤコビアンも与えます。構文についての詳細については、スカラー目的関数の記述ベクトルと行列の目的関数の記述非線形制約を参照してください。

勾配またはヤコビアンの有効性を確認で説明されているように、勾配またはヤコビ関数が正しいことを確認するには関数 checkGradients を使用します。

Symbolic Math Toolbox™ のライセンスをお持ちの場合は、プログラミングによって勾配とヘッシアンを計算することができます。例については、Symbolic Math Toolbox を使用した勾配とヘッシアンの計算を参照してください。

勾配とヤコビアンを使用している例は、勾配およびヘッシアンを使った最小化勾配付き非線形制約Symbolic Math Toolbox を使用した勾配とヘッシアンの計算ヤコビアンを使用した場合と使用しない場合の非線形系の解法、およびヤコビアンを使用した非線形方程式の大規模スパース系を参照してください。問題ベースのアプローチの自動微分については、問題ベースの最適化における自動微分の効果を参照してください。

7.ヘッシアンの供給

ヘッシアンを与えると、ソルバーはより正確かつより少ない反復で作動します。

以下のソルバーとアルゴリズムはヘッシアンを受け入れます。

Symbolic Math Toolbox のライセンスをお持ちの場合は、プログラミングによって勾配とヘッシアンを計算することができます。例については、Symbolic Math Toolbox を使用した勾配とヘッシアンの計算を参照してください。問題ベースのアプローチでヘッシアンを提供するには、問題ベースのワークフローへの導関数の供給を参照してください。

実行不可能な点に収束

通常このような結果が得られる理由は、ソルバーが ConstraintTolerance 許容誤差内で、すべての制約を満たす点を見つけられなかったためです。しかし、ソルバーは実行可能点に位置していた、またはそこで開始したものの、実行不可能点に収束した可能性があります。ソルバーが実行可能性を失った場合は、ソルバーが実行可能性を失った場合を参照してください。quadprog がこの結果を返す場合は、quadprog の実行不可能点への収束を参照してください。

ソルバーが実行可能点を見つけないときに継続するには、以下のいずれか、またはいくつかを試してください。

1.線形制約の確認
2.非線形制約の確認

1.線形制約の確認

線形計画問題を解くことにより、境界と線形制約を満たす点を見つけてみます。

  1. 常に 0 である目的関数で線形計画問題を定義します。

    f = zeros(size(x0)); % assumes x0 is the initial point
  2. 実行可能点があるかどうかを確かめるために、線形計画問題を解きます。

    xnew = linprog(f,A,b,Aeq,beq,lb,ub);
  3. 実行可能点 xnew がある場合は、初期点として xnew を使用し、元の問題を再実行します。

  4. 実行可能点がない場合は、問題は適切に定式化されていません。範囲制約と線形制約の定義を確認します。線形制約の確認の詳細については、線形実行不可能性の調査を参照してください。

2.非線形制約の確認

範囲制約と線形制約が実行可能である (点がすべての制約を満たす) ことを確認した後、非線形制約を確認します。

  • 目的関数を 0 に設定します。

    @(x)0

    すべての制約を満たす状態で、0 の目的関数で最適化を実行します。実行可能点 xnew がある場合は、x0 = xnew を設定し、元の問題を再実行します。

  • 0 の目的関数を使用する実行可能点が見つからない場合は、複数の初期点をもつ 0 の目的関数を使用します。

    • 実行可能点 xnew がある場合は、x0 = xnew を設定し、元の問題を再実行します。

    • 実行可能点が見つからない場合は、実行可能性モードを使用した解の取得のように、EnableFeasibilityMode オプションが true に、SubproblemAlgorithm オプションが 'cg' に設定された fmincon を使用してみます。これらのオプションで複数の初期点を試します。

    • それでも実行可能点が見つからない場合は、次に検討するように、制約を緩めてみます。

非線形の不等式制約を緩め、それから厳しくしてみます。

  1. 非線形制約関数 c を、c-Δ を返すよう変更します。ここで Δ は正の数値です。この変更は非線形制約をより満たしやすくします。

  2. 元の目的関数または常に 0 である目的関数のどちらかを使用して、新しい制約関数での実行可能点を探します。

    1. 実行可能点が見つかる場合は、

      1. Δ の値を小さくします。

      2. 以前に見つかった点から開始し、新しい制約関数での実行可能点を探します。

    2. 実行可能点が見つからない場合は、Δ を増やし、再度探してみます。

実行可能点が見つからない場合は、問題が本当に実行不可能であるかもしれません。つまり、解が存在しないことを意味します。すべての制約定義を再度確認します。

ソルバーが実行可能性を失った場合

ソルバーが実行可能点でスタートしたが、実行不可能点に収束した場合は、以下の手法を試してください。

  • 別のアルゴリズムを試してください。fmincon 'sqp' および 'interior-point' アルゴリズムは通常最もロバストであるため、最初にこれらのいずれかまたは両方を試してください。

  • 範囲を狭くしてみます。lb ベクトルを可能な限り高くし、ub ベクトルを可能な限り低くします。これは、ソルバーが実行可能性を維持するのに役立ちます。fmincon 'sqp' および 'interior-point' アルゴリズムは各反復で範囲に従うので、範囲が狭いと最適化が容易になります。

quadprog の実行不可能点への収束

通常は、線形制約が矛盾しているか、ほぼ特異なために、このメッセージが表示されます。実行可能点が存在するかどうかを確認するには、同じ制約とゼロの目的関数ベクトル f をもつ線形計画問題を作成します。linprog 'dual-simplex' アルゴリズムを使用して解決します。

options = optimoptions('linprog','Algorithm','dual-simplex');
x = linprog(f,A,b,Aeq,beq,lb,ub,options)

linprog によって実行可能点が見つからない場合は、問題は本当に実行不可能です。

linprog によって実行可能点が見つかった場合は、別の quadprog アルゴリズムを試します。または、StepToleranceConstraintTolerance などの一部の許容誤差を変更して、再度問題を解きます。

非有界な問題

ソルバーは、目的関数が許容範囲以下の値を持つ点に達しました。

  • 問題が非有界である可能性があります。つまり、以下をもつ連続点 xi

    lim f(xi) = –∞

    があり、

    そのため、すべての xi は問題の制約を満たします。

  • 問題が正しく定式化されていることを確認します。ソルバーは、目的関数を最小化しようとします。最大値を求める場合は、目的関数に - (マイナス) を付けます。例については、目的関数の最大化を参照してください。

  • 問題をスケーリングするか、センタリングしてみます。「問題のセンタリングとスケーリング」を参照してください。

  • optimoptions を使用して ObjectiveLimit の値を減らし、目的関数値の許容範囲を緩めます。

fsolve が方程式を解けない

fsolve が方程式を解けない理由はいろいろあります。以下に、その対処法を挙げます。

  1. 初期点の変更を参照してください。fsolve は初期点に依存します。異なる初期点を与えると、成功のチャンスが増えます。

  2. 方程式の定義をチェックし、それが滑らかであることを確かめます。fsolve は、絶対値のような不連続な勾配をもつ方程式の場合は収束しない可能性があります。fsolve は、不連続点をもつ関数では収束しない場合があります。

  3. 方程式が「合致する」、すなわち入力と出力が等次元である (方程式の本数と未知数が同数存在する) ことを確認します。

  4. 許容誤差、特に OptimalityToleranceStepTolerance を変更します。許容誤差を非常に小さい値に設定することにより高精度を得ようとすると、fsolve は収束に失敗することがあります。許容誤差の設定が高すぎると、fsolve が方程式を正確に解けないことがあります。

  5. 問題の定義を確認します。x^2 + 1 = 0 のように、問題によっては実数の解をもちません。複素数解を受け入れられる場合は、初期点を複素数値に設定してみてください。初期点が実数の場合、fsolve は複素数解を見つけようとしません。

関連するトピック