Банановая минимизация функции

В этом примере показано, как минимизировать "банановую функцию Розенброка":

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

f(x) вызван банановая функция из-за ее искривления вокруг источника. Это известно в примерах оптимизации из-за медленной сходимости большая часть выставки методов при попытке решить эту задачу.

f(x) имеет уникальный минимум в точке x=[1,1] где f(x)=0. Этот пример показывает много способов минимизировать f(x) запуск в точке x0=[-1.9,2].

Оптимизация без производных

fminsearch функция находит минимум для проблемы без ограничений. Это использует алгоритм, который не оценивает производных целевой функции. Скорее это использует геометрический метод поиска, описанный в fminsearch Алгоритме.

Минимизируйте банановую функцию использование fminsearch. Включайте выходную функцию, чтобы сообщить о последовательности итераций.

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'

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

Оптимизация с предполагаемыми производными

fminunc функция находит минимум для проблемы без ограничений. Это использует основанный на производной алгоритм. Алгоритм пытается оценить не только первую производную целевой функции, но также и матрицу вторых производных. fminunc обычно более эффективно, чем fminsearch.

Минимизируйте банановую функцию использование fminunc.

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

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

Оптимизация с наискорейшим спуском

При попытке минимизировать банановую функцию использование алгоритма наискорейшего спуска, высокое искривление проблемы делает процесс решения очень медленным.

Можно запустить fminunc с алгоритмом наискорейшего спуска путем установки скрытого HessUpdate опция к значению 'steepdesc' для 'quasi-newton' алгоритм. Определите больший, чем значение по умолчанию максимальный номер вычислений функции, потому что решатель не находит решение быстро. В этом случае решатель не находит решение даже после 600 вычислений функции.

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

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

Оптимизация с аналитическим градиентом

Если вы предоставляете градиент, fminunc решает оптимизацию с помощью меньшего количества вычислений функции. Когда вы предоставляете градиент, можно использовать 'trust-region' алгоритм, который часто быстрее и использует меньше памяти, чем 'quasi-newton' алгоритм. Сбросьте HessUpdate и MaxFunctionEvaluations опции к их значениям по умолчанию.

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'

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

Оптимизация с аналитическим гессианом

Если вы обеспечиваете Гессиан (матрица вторых производных), fminunc может решить оптимизацию, использующую даже меньше вычислений функции. Для этой проблемы результатами является то же самое с или без Гессиана.

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'

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

Оптимизация с решателем наименьших квадратов

Рекомендуемым решателем для нелинейной суммы квадратов является lsqnonlin. Этот решатель является четным более эффективный, чем fminunc без градиента для этого специального класса проблем. Использовать lsqnonlin, не пишите свою цель как сумму квадратов. Вместо этого запишите базовый вектор что lsqnonlin внутренне квадраты и суммы.

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'

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

Оптимизация с решателем наименьших квадратов и якобианом

Как в минимизации с помощью градиента для fminunc, lsqnonlin может использовать производную информацию, чтобы понизить количество вычислений функции. Обеспечьте якобиан нелинейного вектора целевой функции и запустите оптимизацию снова.

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'

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

Похожие темы