Zu den vielen neuen Funktionen von JMP 13 sind überarbeitete Minimize()- und Maximize()-Funktionen in JSL. Diese JSL-Funktionen sind iterative Optimierer, die die Extremwerte einer Funktion anhand gegebener Startwerte finden. Das GIF unten ist eine visuelle Demonstration, um einen Eindruck davon zu vermitteln, wie der Algorithmus in einer einfachen eindimensionalen Umgebung funktioniert.

Während die meisten JMP Benutzer werden feststellen, dass vorgefertigte Plattformen (wie „Fit Y by Diese Funktionen ermöglichen dem Benutzer Zugriff auf dieselben Optimierer, die JMP-Entwickler beim Erstellen von JMP-Plattformen nutzen.
Im Allgemeinen überall dort, wo eine Wahrscheinlichkeit besteht JMP Das Modell wurde mit einer Optimierungstechnik namens „Maximum Likelihood“ angepasst. Ebenso beschreibt der Name „Kleinste Quadrate“ selbst die Optimierungsmethode, die zur Anpassung linearer Modelle verwendet wird. Während JMP über eine große Auswahl an Modellen verfügt, gibt es Zeiten, in denen man ein benutzerdefiniertes Modell anpassen möchte, das nicht in JMP vorgefertigt ist. Auch aus pädagogischen Gründen kann es für Studierende sinnvoll sein, statistische Modellierungsprogramme in Optimierungsprobleme umzuwandeln, um zu verstehen, wie das Modell funktioniert.
Die nächsten Abschnitte veranschaulichen die Grundlagen der Verwendung eines allgemeinen Optimierers. Benutzer, die bereits mit iterativen Optimierern vertraut sind, möchten möglicherweise zum letzten Abschnitt springen, um Beispielsyntax für einige der erweiterten Funktionen in Minimize() und Maximize() zu sehen.
Für den Rest dieses Artikels werde ich alles aus der Perspektive von Minimize() schreiben. Beachten Sie, dass das Minimieren einer Funktion f(x) dem Maximieren von -1 * f(x) entspricht, also „f(x)“ durch „–f(x)“, „minimieren“ durch „maximieren“, „konkav“ ersetzen ” mit „convex“ usw. verallgemeinert die Ergebnisse auf Maximize().
Einfaches Beispiel
Das grundlegendste Optimierungsproblem erfordert zwei Funktionsargumente: einen Ausdruck und die zu optimierenden Variablen. Wie in der Vergangenheit kann ein Aufruf wie Minimize( Ausdruck , { x, y }) gibt den erhaltenen Mindestwert zurück. Um zu demonstrieren, wie es funktioniert, minimiert das erste Beispiel einen trivialen quadratischen Ausdruck.
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);
Ausgabe:
minFun = 0;
x = 0;
y = 1;
Nach einigem Nachdenken können wir uns davon überzeugen, dass das Minimum dieser Funktion 0 sein und bei x = 0 und y = 1 auftreten sollte. Nachdem wir dieses Skript ausgeführt haben, sehen wir, dass dies tatsächlich der Fall ist.
Beachten Sie, dass x und y durch die Funktion Minimize() geändert wurden, um die Argumentwerte widerzuspiegeln, die den minimalen Funktionswert erreicht haben. Ein Konturdiagramm für diese Funktion wird hier gezeigt:
Startwerte wählen
Der Optimierer muss mit einem bestimmten Satz von Parameterwerten, sogenannten Startwerten, beginnen und versucht dann iterativ, diese zu verbessern. Der Erfolg und Misserfolg der Optimierung hängt stark von der Qualität der Startwerte ab. Ein Teil der Kunst bei der Entwicklung von Statistiksoftware besteht darin, effektive Startwerte zu finden. Es gibt verschiedene Möglichkeiten, sie zu finden. Es ist wichtig, dass die Funktion mit den Startwerten ausgewertet werden kann (dh sie gibt keinen fehlenden Wert zurück).Manchmal ist das Beste, was Sie tun können, sinnvolle „Standardwerte“ zu finden, die gut funktionieren, z. B. das Festlegen von Regressionsparametern auf Null. Häufig erhält man die besten Startwerte, indem man ein einfacheres Modell an die Daten anpasst und diese Ergebnisse verwendet, beispielsweise durch die Verwendung linearer Kleinste-Quadrate-Schätzungen als Startwerte für eine logistische Regression.
Globale vs. lokale kritische Punkte
Eine wichtige Einschränkung, die Sie beachten sollten, besteht darin, dass Minimize lokale kritische Punkte findet, die möglicherweise das globale Minimum sind oder nicht. Das nächste Beispiel ist ein einfaches Polynom, das dies veranschaulicht. Mit den Startwerten x = 0, y = 0 wird ein lokales Minimum bei x = 0,25 und y = -0,0833 gefunden. Für x=-1 und y = -1 geht die Antwort jedoch bis –unendlich.
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);
Ausgabe:
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);
Ausgabe:
Optimization failed: Failed: Maximum Iterations Exceeded
x = -6.55731043158825e+85;
y = -1.31136919553771e+89;
minFun = -1.03197258530774e+176;
Beachten Sie, dass Minimize() hierfür keine Warnungen ausgibt, da es nicht weiß, ob ein lokales oder globales Minimum erreicht wurde. Tatsächlich konvergiert in diesem Beispiel der erste Satz von Startwerten gegen a Sattelpunkt , die in diesem Fall in einer Richtung ein Minimum und in einer anderen ein Maximum darstellt. Wenn ein globales Minimum gewünscht ist, das Problem jedoch nicht besteht konvex (oder wenn Sie sich nicht sicher sind), besteht eine Möglichkeit darin, mehrere Startwerte auszuprobieren, um zu prüfen, ob sie alle an derselben Position konvergieren. Wenn zwei oder weniger Parameter vorhanden sind, kann die Funktion alternativ grafisch dargestellt werden, sodass leicht festgestellt werden kann, ob es sich um ein lokales Minimum handelt. Hier ist beispielsweise das Zählerdiagramm der letzten Funktion mit den beiden unterschiedlichen Startwerten:
Realistisches Beispiel 1: Minimierung einer Verlustfunktion
In der Statistik werden Parameterschätzungen häufig dadurch ermittelt, dass die Parameterwerte ermittelt werden, die die Summe der quadrierten Fehlerterme, Summe (beobachtet – vorhergesagt) ^ 2, minimieren. Betrachten Sie als Beispiel die Nichtlinearer NIST Dan Wood-Testfall („ ” ).
Hier wollen wir die Summe der quadratischen Fehler des Modells minimieren, also die Argumente dafür finden
Und
das minimiert
.
Der folgende JSL-Code implementiert dies.
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 );
Ausgabe:
b1 = 0.768858626467797;
b2 = 3.86041439611906;
minFun = 0.00431730849313329;
Konturdiagramm:
Realistisches Beispiel 2: Einfache lineare logistische Regression
Wie bereits erwähnt, werden Optimierungsroutinen auch häufig zum Finden von Maximum-Likelihood-Schätzungen verwendet. Angenommen, wir haben 100 binäre Antwortwerte (y) und einen zugehörigen kontinuierlichen Prädiktor (x) beobachtet und möchten ein logistisches Regressionsmodell anpassen. Für eine einfache lineare logistische Regression gehen wir davon aus, dass für jedes i
, Wo
. Die zugehörige Protokollwahrscheinlichkeit beträgt
. Der Kürze halber habe ich die Ableitungen übersprungen, es sind jedoch weitere Einzelheiten zu finden Hier .Der folgende JSL-Code maximiert diese Wahrscheinlichkeit:
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);
Ausgabe:
b0 = 0.169912186525928;
b1 = 2.37904556815702;
Somit sagt dieses Modell voraus, dass für einen neuen x-Wert die geschätzten Wahrscheinlichkeiten wie folgt sind:

Mit einer Darstellung der Passform:

Bei Interesse sehen Sie sich bitte das beigefügte JSL-Skript für die spezifischen Werte von x und y an, die ich für dieses Beispiel verwendet habe, und um zu sehen, wie ich sie generiert habe.
Neue optionale Funktion <
Meine liebste neue Funktion ermöglicht es dem Benutzer, Ausgabedetails mithilfe des optionalen Arguments <
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>
Ausgabe:
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];
Liste aller optionalen Funktionen für Minimize() und Maximize()
- Legen Sie Ober- und Untergrenzen fest : Unter- und/oder Obergrenzen für Variablen festlegen. Zum Beispiel, Minimize( x^2, x(1,5) ) schränkt x so ein, dass es zwischen 1 und 5 bleibt, und Minimize( x^2, x(. , 5) ) stellt sicher, dass x kleiner als 5 ist und keine Untergrenze hat .
- Legen Sie die maximale Anzahl von Iterationen fest : Die maximale Anzahl der Iterationen beträgt standardmäßig 250, kann aber mit < newMaxIter ). Der Standardwert ist 250.
- Legen Sie die Toleranz für die Konvergenz fest : Das Konvergenzkriterium kann mit < neuToleranz ). Der Standardwert ist 10^-8.
- Weitere Details anzeigen : Die Option <
- Verwenden Sie die numerische Näherung für Ableitungen : Standardmäßig versucht Minimize(), analytische Ableitungen zu finden, aber in einigen Fällen funktionieren numerische Näherungen möglicherweise besser. Wählen Sie diese Option aus, indem Sie „<
- Geben Sie einen benutzerdefinierten Farbverlauf ein : Meistens ist Minimize() standardmäßig in der Lage, die analytischen Gradienten zu berechnen. Im unwahrscheinlichen Fall, dass dies gewünscht wird, kann ein Benutzer seinen eigenen Farbverlauf eingeben. Verwenden Sie dazu <
- Geben Sie benutzerdefiniertes Hessisch ein : Die Eingabe eines benutzerdefinierten hessischen Zeichens ist noch umständlicher. Die Syntax wird sehr schnell kompliziert und ich würde empfehlen, dies nur als letzten Ausweg zu verwenden. Um einen analytischen Hesse-Wert einzugeben, verwenden Sie <
Einfaches Beispiel mit allen optionalen Argumenten
Unten finden Sie eine nützliche Vorlage von Minimize() mit allen ausgewählten optionalen Argumenten. In JMP 13.2 ist dieses Beispiel auch unter Minimieren im Scripting Index mit JMP zu finden. Es ist Beispiel 3 (wählen Sie es aus, indem Sie das Dropdown-Menü neben Beispiel 1 auswählen).
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>
Bleiben Sie auf dem Laufenden für einen möglichen zukünftigen Blogbeitrag zu den neuen JSL-Funktionen Constrained Minimize() und Constrained Maximize(), die Probleme mit nichtlinearen Zielfunktionen und linearen Einschränkungen optimieren.
Hallo Hockswender,
Ich freue mich, dass Sie den Blogbeitrag nützlich fanden!
Guter Punkt! Minimize() konvergiert nicht wirklich mit der Standardtoleranz für die (ziemlich schreckliche) Funktion, die ich für mein GIF ausgewählt habe. Ich habe diese Funktion nur aufgrund ihres Aussehens ausgewählt. Minimize() hat damit Schwierigkeiten, weil Gradienten-basierte Optimierungsmethoden mit Funktionen zu kämpfen haben, bei denen die Ableitung nicht immer existiert. In diesem Fall verursacht die Absolutwertfunktion Probleme.
Manchmal gibt es einige einfache Lösungen, wie z. B. die Beschränkung von a auf nichtnegativ, wie in:
a = 2
xpr = expr(3^abs(a));
minimize(xpr, {a(0,.)}, <<SHOWDETAILS></SHOWDETAILS>
Ich habe das im GIF-Code nicht gemacht, weil ich dachte, dass die Funktion mit einer parabolisch aussehenden Form besser aussieht. Aber Sie können sehen, dass der Algorithmus selbst im GIF Probleme mit der Konvergenz hat, wo gegen Ende die Pfeile um das wahre Minimum hin und her springen.