在眾多新功能中JMP 13修改了 JSL 中的 Minimize() 和 Maximize() 函數。 這些 JSL 函數是迭代最佳化器,可以找到給定起始值的函數的極值。 下面的 GIF 直觀地展示了演算法如何在簡單的一維設定中運作。

雖然大多數聯合管理計劃使用者會發現預先建置的平台(例如 Fit Y by X 和非線性)足以解決他們的最佳化問題,但情況並非總是如此,而這些 JSL 函數提供了極大的靈活性和通用性。 這些功能使用戶能夠存取 JMP 開發人員在創建 JMP 平台時所利用的相同優化器。
一般來說,任何有可能報告的地方聯合管理計劃,該模型已採用稱為最大似然的最佳化技術。 同樣,最小二乘這個名字本身描述了用於擬合線性模型的最佳化方法。 雖然 JMP 提供多種可用模型,但有時人們會想要擬合 JMP 中未預先建立的自訂模型。 此外,出於教學原因,學生將統計建模程序轉化為最佳化問題以了解模型的工作原理也很有用。
接下來的幾節將說明使用通用優化器的基礎知識。 已經熟悉迭代優化器的使用者可能會想要跳到最後一節,查看 Minimize() 和 Maximize() 中一些進階功能的範例語法。
在本文的其餘部分中,我將從 Minimize() 的角度來編寫所有內容。 請注意,最小化函數f(x) 相當於最大化-1 * f(x),因此將“f(x)”替換為“–f(x)”,“最小化”替換為“最大化” ,「凹」 」與「凸」等,會將結果推廣到 Maximize()。
簡單的例子
最基本的最佳化問題需要兩個函數參數:表達式和要最佳化的變數。 與過去一樣,諸如 Minimize(表達式, { x、y }) 傳回所得的最小值。 為了示範其工作原理,第一個範例最小化了一個簡單的二次表達式。
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 時。 運行這個腳本後,我們發現情況確實如此。
請注意,Minimize() 函數已變更 x 和 y,以反映實現最小函數值的參數值。 此函數的等值線圖如下所示:
選擇起始值
優化器必須從一組特定的參數值(稱為起始值)開始,然後迭代地嘗試改進它們。 優化的成功和失敗很大程度上取決於起始值的品質。 開發統計軟體的部分藝術圍繞著尋找有效的起始值。 有多種方法可以提出它們。 重要的是該函數可以在起始值處進行計算(即它不傳回缺失值)。有時,您能做的最好的事情就是提出有效的合理「預設」值,例如將迴歸參數設為零。 通常,最佳起始值是透過將更簡單的模型擬合到資料並使用這些結果來獲得的,例如使用線性最小二乘估計作為邏輯迴歸的起始值。
全域臨界點與局部臨界點
需要注意的一個重要警告是,最小化會找到局部臨界點,這可能是也可能不是全域最小值。 下一個例子是一個簡單的多項式來說明這一點。 當初始值 x = 0、y = 0 時,在 x = 0.25 和 y = -0.0833 處找到局部極小值。 然而,對於 x=-1 且 y = -1,答案為 –無限大。
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:最小化損失函數
在統計學中,參數估計值通常是透過尋找使誤差項平方和最小化的參數值來確定的,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:簡單線性 Logistic 迴歸
如前所述,最佳化例程的另一個常見用途是尋找最大似然估計。 例如,假設我們觀察到 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 值,估計機率為:

繪製擬合圖:

如果您有興趣,請參閱隨附的 JSL 腳本,以了解我在本範例中使用的 x 和 y 的特定值以及如何產生它們。
新的選用功能<
我最喜歡的新功能允許用戶使用可選參數 <
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,但可以使用 <新的最大迭代器)。 預設為 250。
- 設定收斂容差:收斂標準可以透過 <新的寬容度)。 預設值為 10^-8。
- 顯示更多詳情:選項<
- 使用導數的數值近似:預設情況下,Minimize() 會嘗試尋找解析導數,但在某些情況下,數值近似可能效果更好。 透過將“<
- 輸入使用者定義的漸變:大多數時候,Minimize()預設能夠計算解析梯度。 萬一需要的話,使用者可以輸入自己的梯度。 為此,請使用 <
- 輸入使用者定義的 Hessian :輸入使用者定義的hessian就更麻煩了。 語法很快就會變得複雜,我建議僅將其作為最後的手段。 若要輸入分析 hessian,請使用 <
帶有所有可選參數的簡單範例
下面是一個有用的 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 文件中找到。]