Main Content

La traducción de esta página aún no se ha actualizado a la versión más reciente. Haga clic aquí para ver la última versión en inglés.

Minimización de la función banana

Este ejemplo muestra cómo minimizar la "función banana" de Rosenbrock:

f(x)=100(x(2)-x(1)2)2+(1-x(1))2.

f(x) se denomina la función banana por su curvatura alrededor del origen. Es muy conocida en los ejemplos de optimización por la convergencia lenta que la mayoría de métodos muestran cuando intentan solucionar este problema.

f(x) tiene un mínimo único en el punto x=[1,1], donde f(x)=0. Este ejemplo muestra varias formas de minimizar f(x) comenzando en el punto x0=[-1.9,2].

Optimización sin derivadas

La función fminsearch encuentra un mínimo para un problema sin restricciones. Utiliza un algoritmo que no estima ninguna derivada en la función objetivo. En su lugar, utiliza un método de búsqueda geométrica descrito en Algoritmo fminsearch.

Minimice la función banana utilizando fminsearch. Incluya una función de salida para informar de la secuencia de iteraciones.

fun = @(x)(100*(x(2) - x(1)^2)^2 + (1 - x(1))^2);
options = optimset('OutputFcn',@bananaout,'Display','off');
x0 = [-1.9,2];
[x,fval,eflag,output] = fminsearch(fun,x0,options);
title 'Rosenbrock solution via fminsearch'

Figure contains an axes object. The axes object with title Rosenbrock solution via fminsearch, xlabel x(1), ylabel x(2) contains 121 objects of type surface, contour, line, text. This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for fminsearch was ',num2str(Fcount)])
Number of function evaluations for fminsearch was 210
disp(['Number of solver iterations for fminsearch was ',num2str(output.iterations)])
Number of solver iterations for fminsearch was 114

Optimización con derivadas estimadas

La función fminunc encuentra un mínimo para un problema sin restricciones. Utiliza un algoritmo basado en derivadas. El algoritmo trata de estimar no solo la primera derivada de la función objetivo, sino también la matriz de las segundas derivadas. fminunc suele ser más eficiente que fminsearch.

Minimice la función banana utilizando fminunc.

options = optimoptions('fminunc','Display','off',...
    'OutputFcn',@bananaout,'Algorithm','quasi-newton');
[x,fval,eflag,output] = fminunc(fun,x0,options);
title 'Rosenbrock solution via fminunc'

Figure contains an axes object. The axes object with title Rosenbrock solution via fminunc, xlabel x(1), ylabel x(2) contains 41 objects of type surface, contour, line, text. One or more of the lines displays its values using only markers This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for fminunc was ',num2str(Fcount)])
Number of function evaluations for fminunc was 150
disp(['Number of solver iterations for fminunc was ',num2str(output.iterations)])
Number of solver iterations for fminunc was 34

Optimización con descenso más pronunciado

Si trata de minimizar la función banana utilizando un algoritmo de descenso más pronunciado, la curvatura alta del problema hace que el proceso de resolución sea muy lento.

Puede ejecutar fminunc con el algoritmo de descenso más pronunciado estableciendo la opción oculta HessUpdate en el valor 'steepdesc' para el algoritmo 'quasi-newton'. Establezca un número máximo mayor que el predeterminado de evaluaciones de función, dado que el solver no encuentra la solución rápidamente. En este caso, el solver no encuentra la solución incluso después de 600 evaluaciones de función.

options = optimoptions(options,'HessUpdate','steepdesc',...
    'MaxFunctionEvaluations',600);
[x,fval,eflag,output] = fminunc(fun,x0,options);
title 'Rosenbrock solution via steepest descent'

Figure contains an axes object. The axes object with title Rosenbrock solution via steepest descent, xlabel x(1), ylabel x(2) contains 51 objects of type surface, contour, line, text. One or more of the lines displays its values using only markers This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for steepest descent was ',...
    num2str(Fcount)])
Number of function evaluations for steepest descent was 600
disp(['Number of solver iterations for steepest descent was ',...
    num2str(output.iterations)])
Number of solver iterations for steepest descent was 45

Optimización con gradiente analítico

Si proporciona un gradiente, fminunc resuelve la optimización utilizando menos evaluaciones de función. Cuando proporciona un gradiente, puede utilizar el algoritmo 'trust-region', que a menudo es más rápido y utiliza menos memoria que el algoritmo 'quasi-newton'. Restablezca las opciones HessUpdate y MaxFunctionEvaluations a sus valores predeterminados.

grad = @(x)[-400*(x(2) - x(1)^2)*x(1) - 2*(1 - x(1));
            200*(x(2) - x(1)^2)];
fungrad = @(x)deal(fun(x),grad(x));
options = resetoptions(options,{'HessUpdate','MaxFunctionEvaluations'});
options = optimoptions(options,'SpecifyObjectiveGradient',true,...
    'Algorithm','trust-region');
[x,fval,eflag,output] = fminunc(fungrad,x0,options);
title 'Rosenbrock solution via fminunc with gradient'

Figure contains an axes object. The axes object with title Rosenbrock solution via fminunc with gradient, xlabel x(1), ylabel x(2) contains 38 objects of type surface, contour, line, text. One or more of the lines displays its values using only markers This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for fminunc with gradient was ',...
    num2str(Fcount)])
Number of function evaluations for fminunc with gradient was 32
disp(['Number of solver iterations for fminunc with gradient was ',...
    num2str(output.iterations)])
Number of solver iterations for fminunc with gradient was 31

Optimización con matriz hessiana analítica

Si proporciona una matriz hessiana (matriz de segundas derivadas), fminunc puede resolver la optimización utilizando incluso menos evaluaciones de función. Para este problema, los resultados son los mismos con o sin la matriz hessiana.

hess = @(x)[1200*x(1)^2 - 400*x(2) + 2, -400*x(1);
            -400*x(1), 200];
fungradhess = @(x)deal(fun(x),grad(x),hess(x));
options.HessianFcn = 'objective';
[x,fval,eflag,output] = fminunc(fungradhess,x0,options);
title 'Rosenbrock solution via fminunc with Hessian'

Figure contains an axes object. The axes object with title Rosenbrock solution via fminunc with Hessian, xlabel x(1), ylabel x(2) contains 38 objects of type surface, contour, line, text. One or more of the lines displays its values using only markers This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for fminunc with gradient and Hessian was ',...
    num2str(Fcount)])
Number of function evaluations for fminunc with gradient and Hessian was 32
disp(['Number of solver iterations for fminunc with gradient and Hessian was ',num2str(output.iterations)])
Number of solver iterations for fminunc with gradient and Hessian was 31

Optimización con un solver de mínimos cuadrados

El solver recomendado para una suma no lineal de cuadrados es lsqnonlin. Este solver es incluso más eficiente que fminunc sin un gradiente para esta clase especial de problemas. Para utilizar lsqnonlin, no escriba su objetivo como una suma de cuadrados. En su lugar, escriba el vector subyacente que lsqnonlin eleva al cuadrado y suma internamente.

options = optimoptions('lsqnonlin','Display','off','OutputFcn',@bananaout);
vfun = @(x)[10*(x(2) - x(1)^2),1 - x(1)];
[x,resnorm,residual,eflag,output] = lsqnonlin(vfun,x0,[],[],options);
title 'Rosenbrock solution via lsqnonlin'

Figure contains an axes object. The axes object with title Rosenbrock solution via lsqnonlin, xlabel x(1), ylabel x(2) contains 35 objects of type surface, contour, line, text. One or more of the lines displays its values using only markers This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for lsqnonlin was ',...
    num2str(Fcount)])
Number of function evaluations for lsqnonlin was 87
disp(['Number of solver iterations for lsqnonlin was ',num2str(output.iterations)])
Number of solver iterations for lsqnonlin was 28

Optimización con un solver de mínimos cuadrados y una matriz jacobiana

Al igual que en la minimización que utiliza un gradiente para fminunc, lsqnonlin puede utilizar información de las derivadas para reducir el número de evaluaciones de función. Proporcione la matriz jacobiana del vector de la función objetivo no lineal y ejecute de nuevo la optimización.

jac = @(x)[-20*x(1),10;
           -1,0];
vfunjac = @(x)deal(vfun(x),jac(x));
options.SpecifyObjectiveGradient = true;
[x,resnorm,residual,eflag,output] = lsqnonlin(vfunjac,x0,[],[],options);
title 'Rosenbrock solution via lsqnonlin with Jacobian'

Figure contains an axes object. The axes object with title Rosenbrock solution via lsqnonlin with Jacobian, xlabel x(1), ylabel x(2) contains 35 objects of type surface, contour, line, text. One or more of the lines displays its values using only markers This object represents Iterative steps.

Fcount = output.funcCount;
disp(['Number of function evaluations for lsqnonlin with Jacobian was ',...
    num2str(Fcount)])
Number of function evaluations for lsqnonlin with Jacobian was 29
disp(['Number of solver iterations for lsqnonlin with Jacobian was ',...
    num2str(output.iterations)])
Number of solver iterations for lsqnonlin with Jacobian was 28

Copyright 2006–2020 The MathWorks, Inc.

Temas relacionados