Entre las muchas características nuevas de JMP 13 Se han renovado las funciones Minimize() y Maximize() en JSL. Estas funciones JSL son optimizadores iterativos que encuentran los valores extremos de una función dados los valores iniciales. El GIF a continuación es una demostración visual para dar una idea de cómo funciona el algoritmo en un entorno unidimensional simple.

Mientras que la mayoría JMP Los usuarios encontrarán que las plataformas prediseñadas (como Fit Y by X y Nonlinear) son suficientes para sus problemas de optimización, pero este no es siempre el caso y estas funciones JSL ofrecen una gran flexibilidad y generalidad. Estas funciones brindan al usuario acceso a los mismos optimizadores que aprovechan los desarrolladores de JMP cuando crean plataformas JMP.
En términos generales, en cualquier lugar donde exista una probabilidad reportada en JMP , el modelo se ha ajustado con una técnica de optimización llamada Máxima Verosimilitud. De manera similar, el nombre Mínimos Cuadrados describe el método de optimización utilizado para ajustar modelos lineales. Si bien JMP tiene una amplia variedad de modelos disponibles, hay ocasiones en las que uno desea adaptar un modelo personalizado que no está prediseñado en JMP. Además, por motivos pedagógicos, puede resultar útil que los estudiantes conviertan programas de modelado estadístico en problemas de optimización para comprender cómo funciona el modelo.
Las siguientes secciones ilustran los conceptos básicos del uso de un optimizador general. Los usuarios que ya estén familiarizados con los optimizadores iterativos pueden querer pasar a la última sección para ver ejemplos de sintaxis para algunas de las funciones avanzadas de Minimize() y Maximize().
Durante el resto de este artículo, escribiré todo desde la perspectiva de Minimize(). Tenga en cuenta que minimizar una función, f(x), es equivalente a maximizar -1 * f(x), por lo que intercambiar “f(x)” por “–f(x)”, “minimizar” por “maximizar”, “cóncavo” ” con “convexo”, etc., generalizará los resultados a Maximizar().
Ejemplo sencillo
El problema de optimización más básico requiere dos argumentos de función: una expresión y las variables a optimizar. Como en el pasado, una llamada como Minimize( exprés , { x,y }) devuelve el valor mínimo obtenido. Para demostrar cómo funciona, el primer ejemplo minimiza una expresión cuadrática trivial.
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);
Producción:
minFun = 0;
x = 0;
y = 1;
Después de pensarlo un poco, podemos convencernos de que el mínimo de esta función debe ser 0 y ocurrir en x = 0 e y = 1. Después de ejecutar este script, vemos que ese es efectivamente el caso.
Observe que la función Minimize() ha cambiado x e y para reflejar los valores de los argumentos que alcanzaron el valor mínimo de la función. A continuación se muestra un gráfico de contorno para esta función:
Elegir valores iniciales
El optimizador tiene que comenzar con un conjunto particular de valores de parámetros, llamados valores iniciales, y luego intenta mejorarlos de forma iterativa. El éxito y el fracaso de la optimización dependen en gran medida de la calidad de los valores iniciales. Parte del arte de desarrollar software estadístico gira en torno a encontrar valores iniciales eficaces. Hay una variedad de maneras de pensar en ellos. Es esencial que la función pueda evaluarse en los valores iniciales (es decir, que no devuelva un valor faltante).A veces, lo mejor que puede hacer es crear valores 'predeterminados' sensatos que funcionen bien, como establecer parámetros de regresión iguales a cero. A menudo, los mejores valores iniciales se obtienen ajustando un modelo más simple a los datos y usando esos resultados, como por ejemplo usando estimaciones de mínimos cuadrados lineales como valores iniciales para una regresión logística.
Puntos críticos globales versus locales
Una advertencia importante a tener en cuenta es que Minimize encuentra puntos críticos locales, que pueden ser o no el mínimo global. El siguiente ejemplo es un polinomio simple que ilustra esto. Con los valores iniciales de x = 0, y = 0, se encuentra un mínimo local en x = 0,25 e y = -0,0833. Sin embargo, para x=-1 e y = -1, la respuesta es –infinito.
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);
Producción:
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);
Producción:
Optimization failed: Failed: Maximum Iterations Exceeded
x = -6.55731043158825e+85;
y = -1.31136919553771e+89;
minFun = -1.03197258530774e+176;
Observe que Minimize() no da ninguna advertencia para esto porque no sabe si alcanzó un mínimo local o global. De hecho, en este ejemplo, el primer conjunto de valores iniciales converge a un punto de silla , que, en este caso, es mínimo en una dirección y máximo en otra. Si se desea un mínimo global y el problema no es convexo (o si no está seguro), entonces una opción es probar varios valores iniciales para comprobar si todos convergen en la misma ubicación. Alternativamente, si hay dos o menos parámetros, se puede trazar la función, lo que facilita saber si es un mínimo local; por ejemplo, aquí está el gráfico del conteo de la última función con los dos valores iniciales diferentes:
Ejemplo realista 1: minimizar una función de pérdida
En estadística, las estimaciones de parámetros a menudo se determinan encontrando los valores de los parámetros que minimizan la suma de los términos de error al cuadrado, suma (observada – predicha) ^ 2. Como ejemplo, considere la Caso de prueba no lineal NIST Dan Wood (" " ).
Aquí queremos minimizar la suma de errores cuadrados dado el modelo, es decir, encontrar los argumentos para
y
que minimiza
.
El siguiente código JSL implementa esto.
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 );
Producción:
b1 = 0.768858626467797;
b2 = 3.86041439611906;
minFun = 0.00431730849313329;
Dibujo de contorno:
Ejemplo realista 2: regresión logística lineal simple
Como se mencionó, otro uso común de las rutinas de optimización es encontrar estimaciones de máxima verosimilitud. Por ejemplo, digamos que hemos observado 100 valores de respuesta binaria, y, y un predictor continuo asociado, x, y queremos ajustar un modelo de regresión logística. Para una regresión logística lineal simple, asumimos que para cada i,
, dónde
. La probabilidad logarítmica asociada es
. Por brevedad, me salté las derivaciones, pero se pueden encontrar más detalles. aquí .El siguiente código JSL maximiza esta probabilidad:
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);
Producción:
b0 = 0.169912186525928;
b1 = 2.37904556815702;
Por tanto, este modelo predice que para algún nuevo valor de x, las probabilidades estimadas son:

Con una trama del ajuste:

Si está interesado, consulte el script JSL adjunto para conocer los valores específicos de xey que utilicé para este ejemplo, así como para ver cómo los generé.
Nueva característica opcional <
Mi nueva característica favorita permite al usuario recuperar detalles de salida utilizando el argumento opcional <
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>
Producción:
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];
Lista de todas las funciones opcionales para Minimize() y Maximize()
- Establecer límites superiores e inferiores : establece límites inferiores y/o superiores para las variables. Por ejemplo, Minimizar (x^2, x(1,5)), restringe x para que permanezca entre 1 y 5, y Minimizar (x^2, x(., 5)), garantiza que x sea menor que 5 sin límite inferior .
- Establecer el número máximo de iteraciones : El número máximo de iteraciones por defecto es 250 pero se puede cambiar con < nuevoMaxIter ). El valor predeterminado es 250.
- Establecer tolerancia para la convergencia : El criterio de convergencia se puede cambiar con < nuevoTolerancia ). El valor predeterminado es 10^-8.
- Mostrar más detalles : La opción <
- Utilice la aproximación numérica para derivados : De forma predeterminada, Minimize() intentará encontrar derivadas analíticas, pero en algunos casos, las aproximaciones numéricas pueden funcionar mejor. Seleccione esta opción agregando "<
- Entrada de gradiente definido por el usuario : La mayoría de las veces, Minimize() podrá calcular los gradientes analíticos de forma predeterminada. En el improbable caso de que así lo desee, el usuario puede ingresar su propio gradiente. Para hacer esto, use <
- Entrada de arpillera definida por el usuario : Introducir una arpillera definida por el usuario es aún más engorroso. La sintaxis se complica muy rápidamente y recomendaría usar esto sólo como último recurso. Para ingresar una arpillera analítica, use <
Ejemplo simple con todos los argumentos opcionales
A continuación se muestra una plantilla útil de Minimize() con todos los argumentos opcionales seleccionados. En JMP 13.2, este ejemplo también se puede encontrar en Minimizar en el Índice de secuencias de comandos con JMP. Es el Ejemplo 3 (selecciónelo eligiendo el menú desplegable junto al Ejemplo 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>
Manténgase informado para una posible publicación de blog futura sobre las nuevas funciones JSL, Constrained Minimize() y Constrained Maximize(), que optimizan problemas con funciones objetivo no lineales y restricciones lineales.