В этом примере показано, как минимизировать «функцию банана» Розенброка:
(1-x (1)) 2.
) называется банановой функцией из-за ее кривизны вокруг начала координат. Это печально известно в примерах оптимизации из-за медленной сходимости большинство методов проявляют при попытке решить эту проблему.
) имеет уникальный минимум в точке 1,1], x) = 0. В этом примере показан ряд способов минимизации f (x), начиная с [-1.9,2].
fminsearch функция находит минимум для проблемы без ограничений. Он использует алгоритм, который не оценивает какие-либо производные целевой функции. Скорее, он использует метод геометрического поиска, описанный в fminsearch Algorithm.
Минимизировать функцию банана с помощью 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
Авторское право 2006 - 2020 The MathWorks, Inc.