Этот пример показывает, как минимизировать «функцию бананаРозенбрка:
называется функцией банана из-за ее кривизны вокруг источника. Это печально известно в примерах оптимизации из-за медленной сходимости, большинство методов проявляются при попытке решить эту задачу.
имеет уникальный минимум в точке где . Этот пример показывает ряд способов минимизации начало в точке .
The 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
The 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.