数多くの新機能の中でも、 JMP13 JSL の Minimize() 関数と Maximize() 関数が改良されました。 これらの JSL 関数は、開始値が与えられた関数の極値を見つける反復オプティマイザーです。 以下の GIF は、単純な 1 次元設定でアルゴリズムがどのように機能するかを直感的に示すための視覚的なデモンストレーションです。

ほとんどの場合、 JMPユーザーは、最適化の問題には事前に構築されたプラットフォーム (Fit Y by X や Nonlinear など) で十分であると考えるでしょう。これは常に当てはまるわけではありません。これらの JSL 関数は優れた柔軟性と汎用性を提供します。 これらの関数を使用すると、JMP 開発者が JMP プラットフォームを作成するときに利用するのと同じオプティマイザーにユーザーがアクセスできるようになります。
一般的に言えば、報告される可能性がある場所であればどこでも、 JMP 、モデルは最尤法と呼ばれる最適化手法で適合されています。 同様に、最小二乗法という名前自体は、線形モデルの近似に使用される最適化手法を表しています。 JMP にはさまざまなモデルが用意されていますが、JMP で事前に構築されていないカスタム モデルを適合させたい場合があります。 また、教育上の理由から、学生が統計モデリング プログラムを最適化問題に変換して、モデルがどのように機能するかを理解するのに役立つ場合があります。
次のいくつかのセクションでは、一般的なオプティマイザーの使用の基本を説明します。 反復オプティマイザーにすでに慣れているユーザーは、最後のセクションに進んで、Minimize() および Maximize() の高度な機能のいくつかの構文例を参照することをお勧めします。
この記事の残りの部分では、Minimize() の観点からすべてを書いていきます。 関数 f(x) を最小化することは、-1 * f(x) を最大化することと同等であるため、「f(x)」を「-f(x)」に、「最小化」を「最大化」に、「凹型」に置き換えることに注意してください。 」と「convex」などを組み合わせると、結果が Maximize() に一般化されます。
簡単な例
最も基本的な最適化問題には、最適化する式と変数という 2 つの関数引数が必要です。 これまでと同様に、 Minimize(式、{ x、y }) は取得した最小値を返します。 それがどのように機能するかを示すために、最初の例では自明な 2 次式を最小化します。
x = 2; /*starting value for x */
y = 2; /*starting value for y */
expr1 = expr((x ^ 2 + (y - 1) ^ 2));
minFun = Minimize( expr1, {x, y});
Show(minFun, x, y);
出力:
minFun = 0;
x = 0;
y = 1;
少し考えた後、この関数の最小値は 0 であり、x = 0 および y = 1 で発生することがわかります。 このスクリプトを実行すると、実際にそうなっていることがわかります。
x と y が Minimize() 関数によって変更され、最小関数値に達した引数の値が反映されていることに注意してください。 この関数の等高線プロットを次に示します。
開始値の選択
オプティマイザは、開始値と呼ばれる特定のパラメータ値のセットから開始し、それらを繰り返し改善しようとします。 最適化の成功と失敗は、開始値の品質に大きく依存します。 統計ソフトウェアの開発技術の一部は、効果的な開始値を見つけることに重点が置かれています。 それらを思いつくにはさまざまな方法があります。 関数が開始値で評価できる (つまり、欠損値を返さない) ことが重要です。場合によっては、回帰パラメータをゼロに設定するなど、適切に機能する賢明な「デフォルト」値を考え出すことが最善の方法である場合があります。 多くの場合、最良の開始値は、ロジスティック回帰の開始値として線形最小二乗推定を使用するなど、より単純なモデルをデータに適合させ、その結果を使用することによって得られます。
グローバル クリティカル ポイントとローカル クリティカル ポイント
注意すべき重要な注意点は、Minimize は、グローバル最小値である場合もそうでない場合もあるローカル クリティカル ポイントを検出することです。 次の例は、これを示す単純な多項式です。 開始値が x = 0、y = 0 の場合、極小値は x = 0.25、y = -0.0833 で見つかります。 ただし、x=-1、y = -1 の場合、答えは –infinity になります。
x = 0; /*starting value for x */
y = 0; /*starting value for y */
expr2 = expr((y * 3 - 2 * x ^ 2 - 12 * x * y));
minFun = Minimize(expr2, {x, y});
Show( x, y, minFun);
出力:
x = 0.25;
y = -0.0833333333333333;
minFun = -0.125;
x = -1; /*starting value for x */
y = -1; /*starting value for y */
minFun = Minimize(expr2, {x, y});
Show( x, y, minFun);
出力:
Optimization failed: Failed: Maximum Iterations Exceeded
x = -6.55731043158825e+85;
y = -1.31136919553771e+89;
minFun = -1.03197258530774e+176;
Minimize() はローカル最小値に達したかグローバル最小値に達したかがわからないため、これに対して警告を発しないことに注意してください。 実際、この例では、最初の開始値セットは次の値に収束します。サドルポイント、この場合、これは一方向では最小値であり、別の方向では最大値です。 グローバルな最小値が望まれるが、問題はそうではない場合凸型(または確信がない場合)、1 つのオプションは、複数の開始値を試して、それらがすべて同じ位置に収束するかどうかを確認することです。 あるいは、パラメーターが 2 つ以下の場合は、関数をプロットすることもできます。これにより、それが局所最小値であるかどうかを簡単に判断できます。たとえば、ここでは 2 つの異なる開始値を持つ最後の関数からのカウンター プロットを示します。
現実的な例 1: 損失関数の最小化
統計学では、パラメーター推定値は、二乗誤差項の合計、sum (観測値 – 予測値) ^ 2 を最小化するパラメーター値を見つけることによって決定されることがよくあります。例として、次のことを考えてみましょう。非線形 NIST Dan Wood テスト ケース(「 」 )。
ここでは、与えられたモデルの二乗誤差の合計を最小限に抑えたいと考えています。つまり、次の引数を見つけます。
そして
それは最小限に抑えます
。
次の JSL コードはこれを実装します。
x = [1.309, 1.471, 1.49, 1.565, 1.611, 1.68];
y = [2.138, 3.421, 3.597, 4.34, 4.882, 5.66];
b1 = 1; /*starting value for b1 */
b2 = 5; /*starting value for b2 */
sseExpr = Expr(
Summation( i = 1, 6, (y[i] - b1 * x[i] ^ b2) ^ 2 )
);
minFun = Minimize( sseExpr, {b1, b2} );
Show( b1, b2, minFun );
出力:
b1 = 0.768858626467797;
b2 = 3.86041439611906;
minFun = 0.00431730849313329;
等高線図:
現実的な例 2: 単純な線形ロジスティック回帰
前述したように、最適化ルーチンのもう 1 つの一般的な用途は、最尤推定値を見つけることです。 たとえば、100 個のバイナリ応答値 y と、関連する連続予測子 x を観察し、ロジスティック回帰モデルを近似したいとします。 単純な線形ロジスティック回帰では、各 i について次のように仮定します。
、 どこ
。 関連する対数尤度は次のとおりです。
。 簡潔にするために、導出は省略しましたが、詳細についてはこちらをご覧ください。ここ。次の JSL コードは、この可能性を最大化します。
b0 = 0;
b1 = 0;
logLik = Expr(
Summation( i = 1, 100, y[i] * log( logist(b0 + b1 * x[i]) ) + (1 - y[i]) * log(1- logist(b0 + b1 * x[i]) ) )
);
minFun = Maximize( logLik, {b0, b1} );
Show( b0, b1);
出力:
b0 = 0.169912186525928;
b1 = 2.37904556815702;
したがって、このモデルは、いくつかの新しい x 値について、推定確率は次のようになると予測します。

近似のプロット:

興味があれば、この例で使用した x と y の特定の値とそれらの生成方法を確認するための添付の JSL スクリプトを参照してください。
新しいオプション機能 <
私のお気に入りの新機能では、ユーザーはオプションの引数 <
x = [1.309, 1.471, 1.49, 1.565, 1.611, 1.68];
y = [2.138, 3.421, 3.597, 4.34, 4.882, 5.66];
b1 = 1; /*starting value for b1 */
b2 = 5; /*starting value for b2 */
sseExpr = Expr(
Summation( i = 1, 6, (y[i] - b1 * x[i] ^ b2) ^ 2 )
);
{objVal, iters, gradient, hessian} = Minimize( sseExpr, {b1, b2} , <<SHOWDETAILS></SHOWDETAILS>
出力:
nParm=2 Newton ******************************************************
Iter nFree Objective RelGrad NormGrad2 Ridge nObj nGrad nHess Parm0 Parm1
0 2 149.7192 332.8046 182170.1 0 1 1 1 1 5
1 2 31.87877 101.5969 19003.84 0 1 1 1 1.010662 4.225573
2 2 4.215765 28.12531 1448.206 0 1 1 1 1.024865 3.630484
3 2 0.378951 7.636836 51.97781 0 1 1 1 1.058064 3.252922
4 2 0.153712 0.003012 0.615041 0.125 2 1 1 1.008287 3.272327
5 2 0.08553 0.100794 0.100071 0.031 1 1 1 0.937871 3.42031
6 2 0.035115 0.074061 0.132669 0.016 1 1 1 0.868411 3.588806
7 2 0.00829 0.164555 1.452852 0 1 1 1 0.772783 3.836035
8 2 0.00432 1.62e-5 0.00021 0 1 1 1 0.769751 3.858031
9 2 0.004317 2.313e-9 2.057e-8 0 1 1 1 0.768859 3.860414
Convergence SUCCESS: Gradient
Time: 0.033333333209157
b1 = 0.768858626467797;
b2 = 3.86041439611906;
objVal = 0.00431730849313329;
iters = 9;
gradient = [-0.000193577585687388, -0.000060622489899298];
hessian = [351.567213300015 123.108731500088, 123.108731500088 43.9222933905666];
Minimize() および Maximize() のすべてのオプション機能のリスト
- 上限と下限の設定: 変数の下限値および上限値を設定します。 例えば、 Minimize( x^2, x(1,5) ) は、x が 1 ~ 5 の間に収まるように制限します。 Minimize ( x^2, x(. , 5) ) は、x が下限なしで 5 未満であることを保証します。 。
- 最大反復回数の設定: 最大反復数のデフォルトは 250 ですが、< newMaxIter )。 デフォルトは 250 です。
- 収束の許容値を設定する: 収束基準は <新しい許容範囲)。 デフォルトは 10^-8 です。
- さらに詳細を表示: オプション <
- 導関数に数値近似を使用する注: デフォルトでは、Minimize() は解析的な導関数を見つけようとしますが、場合によっては、数値近似の方がうまく機能する場合があります。 このオプションを選択するには、関数呼び出しに「<
- ユーザー定義のグラデーションを入力: ほとんどの場合、Minimize() はデフォルトで分析勾配を計算できます。 万が一の場合に備えて、ユーザーは独自の勾配を入力できます。 これを行うには、<
- ユーザー定義のヘシアンを入力: ユーザー定義のヘシアンを入力するのはさらに面倒です。 構文はすぐに複雑になるため、これは最後の手段としてのみ使用することをお勧めします。 分析ヘシアンを入力するには、ヘシアンの上三角部分のみを行優先の順序で使用して、<
すべてのオプションの引数を含む単純な例
以下は、すべてのオプションの引数が選択された Minimize() の便利なテンプレートです。 JMP 13.2 では、この例は「JMP のスクリプト索引」の「最小化」にもあります。 これは例 3 です (例 1 の横にあるドロップダウン メニューを選択して選択します)。
x = 0;
y = 0;
{objVal, iters, gradient, hessian} =
Minimize(
((2 * x ^ 2 + 12 * x * y - y * 3)),
{x( -1, 1 ), y( -1, 1 )},
<<MAXITER></MAXITER>
非線形目的関数と線形制約の問題を最適化する新しい JSL 関数 Constrained Minimize() および Constrained Maximize() については、今後ブログ投稿する可能性があるので、続報をお待ちください。
こんにちは、ホックスウェンダーさん
ブログ投稿がお役に立ててうれしいです。
いい視点ね! Minimize() は、GIF 用に選択した (かなりひどい) 関数のデフォルト許容値では実際には収束しません。 私は純粋に見た目に基づいてその機能を選びました。 Minimize() では、勾配ベースの最適化メソッドは導関数が常に存在するとは限らない関数と格闘するため、これが困難です。 この場合、絶対値関数が問題を引き起こします。
場合によっては、次のように a を非負に制限するなど、簡単な解決策がいくつかあることがあります。
a = 2
xpr = expr(3^abs(a));
minimize(xpr, {a(0,.)}, <<SHOWDETAILS></SHOWDETAILS>
関数は放物線状の方が見栄えが良いと考えたので、GIF コードではこれを行いませんでした。 しかし、GIF でもアルゴリズムが収束するのに苦労していることがわかり、最後近くで矢印が真の最小値の周りを行ったり来たりしています。
詳細な説明をありがとうございます。 最小化ルーチンは、私にとって新しいプロジェクトに役立つはずです。
さまざまなセクションを分割しましたが、a = GIF プロットだけで問題が発生しました - xpr = expr(3^abs(a)); を最小化しようとしました。しかし、それは収束せず(最初の推測を変えました)、その後エラーが発生します。
スクリプト部分を添付します。 アドバイスをよろしくお願いします。
[スクリプトは簡潔にするために管理者によって削除されました。 ブログに添付されている JSL ファイルで入手できます。]