Улучшение точности и производительности в оптимизации

Этот пример демонстрирует, что Symbolic Math Toolbox помогает минимизировать ошибки при решении нелинейной системы уравнений.

Этот пример использует следующую поддержку Symbolic Math Toolbox:

  • Вычисление аналитического градиента с помощью gradient

  • Вычисление аналитического якобиана с помощью jacobian

  • Преобразование символьных результатов в числовые функции с помощью matlabFunction

  • Аналитическая визуализация с fplot

Цель состоит в том, чтобы найти минимум Функции Розенброка или так называемую "банановую" функцию.

f(x)=i=1n/2100(x2i-x2i-12)2+(1-x2i-1)2

Используйте fplot, чтобы создать быструю визуализацию Функции Розенброка двух переменных

syms x y
a=1;    b=100;
f(x,y)=(a-x)^2+b*(y-x^2)^2
f(x, y) = x-12+100y-x22
fsurf(f,[-2 2 -1 3])
view([-45 50])
colormap jet
caxis([0,1000])
colorbar

Мотивация

“Нелинейные уравнения с Аналитическим якобиевским” примером в Optimization Toolbox решают ту же проблему при помощи функции fsolve. Рабочий процесс, показанный в том примере, имеет два потенциальных источника ошибок. Вы должны были бы

  1. Переведите уравнения для Функции Розенброка и якобиана от математической формы в тексте к цифровому коду.

  2. Явным образом вычислите якобиан. Для сложных уравнений эта задача подвержена ошибкам.

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

Перепишите функцию Розенброка как систему нелинейных уравнений

Во-первых, преобразуйте Функцию Розенброка f в систему нелинейных уравнений F, где F является градиентом f.

clear
n = 64;
x = sym('x',[n,1]);
f = sum(100*(x(2:2:n)-x(1:2:n).^2).^2 + (1-x(1:2:n)).^2);
F = gradient(f,x);

Покажите первые 10 уравнений:

F(1:10)
ans = 

(2x1-400x1x2-x12-2200x2-200x122x3-400x3x4-x32-2200x4-200x322x5-400x5x6-x52-2200x6-200x522x7-400x7x8-x72-2200x8-200x722x9-400x9x10-x92-2200x10-200x92)

Чтобы совпадать с промежуточными результатами, показанными в примере Optimization Toolbox, используйте ту же форму F.

F(1:2:n) = simplify(F(1:2:n) + 2*x(1:2:n).*F(2:2:n));
F(1:2:n) = -F(1:2:n)/2;
F(2:2:n) = F(2:2:n)/20;

Теперь системы уравнений идентичны:

F(1:10)
ans = 

(1-x110x2-10x121-x310x4-10x321-x510x6-10x521-x710x8-10x721-x910x10-10x92)

Вычислите якобиан матрицы, представляющей систему уравнений

Используйте jacobian, чтобы вычислить якобиан F. Эта функция вычисляет якобиан символически, таким образом избегая ошибок, сопоставленных с числовыми приближениями производных.

JF = jacobian(F,x);

Покажите первые 10 строк и столбцов якобиевской матрицы.

JF(1:10,1:10)
ans = 

(-1000000000-20x1100000000000-1000000000-20x3100000000000-1000000000-20x5100000000000-1000000000-20x7100000000000-1000000000-20x910)

Большинство элементов якобиевского матричного JF является нулями. Тем не менее, когда вы преобразовываете эту матрицу в функцию MATLAB, результатом является плотная числовая матрица. Часто, операции на разреженных матрицах более эффективны, чем те же операции на плотных матрицах.

Поэтому, чтобы создать эффективный код, преобразуйте только ненулевые элементы JF к символьному вектору прежде, чем вызвать matlabFunction. is и js представляют шаблон разреженности JF.

[is,js] = find(JF);
JF = JF(JF~=0);

Преобразуйте Систему уравнений и якобиан к функции MATLAB

F системы уравнений, представляя Функцию Розенброка, является символьной матрицей, которая состоит из символьных выражений. Чтобы смочь решить его с функцией fsolve, преобразуйте эту систему в функцию MATLAB. На этом шаге удобно преобразовать и F и его якобиан, JF, к одной основанной на файле функции MATLAB, FJFfun. В принципе это позволяет F и JF снова использовать переменные. Также можно преобразовать их в отдельные функции MATLAB.

matlabFunction([F;JF],'var',x,'file','FJFfun');

FJFfun принимает переменные как список, но fsolve ожидает вектор переменных. Функциональный genericObj преобразовывает вектор в список. Анонимная функция bananaObj задана, чтобы зафиксировать значения аргументов для genericObj. Отметьте использование шаблона разреженности в функциональном genericObj. Далее обратите внимание, что этот подход использования FJFfun и genericObj вместе не связывается к конкретному выражению, представленному F, и может быть использован как есть для любого F.

bananaobj = @(y) genericObj(y,@FJFfun,is,js)
bananaobj = function_handle with value:
    @(y)genericObj(y,@FJFfun,is,js)

Используйте fsolve, чтобы Численно Решить Систему Нелинейных уравнений

Используйте fsolve для системы уравнений, преобразованной в функцию MATLAB. Используйте отправную точку x (i) = –1.9 для нечетных индексов и x (i) = 2 для ровных индексов. Установите 'Display' to'iter' видеть прогресс решателя. Установите 'Jacobian' на 'on' использовать заданный in bananaobj якобиана.

x0(1:n,1) = -1.9;
x0(2:2:n,1) = 2;
options = optimoptions(@fsolve,'Display','iter','Jacobian','on');
[sol1,Fsol,exitflag,output,JAC] = fsolve(bananaobj,x0,options);
                                         Norm of      First-order   Trust-region
 Iteration  Func-count     f(x)          step         optimality    radius
     0          1         8563.84                           615               1
     1          2         3093.71              1            329               1
     2          3         225.104            2.5           34.8             2.5
     3          4          212.48           6.25           34.1            6.25
     4          5          212.48           6.25           34.1            6.25
     5          6         102.771         1.5625           6.39            1.56
     6          7         102.771        3.90625           6.39            3.91
     7          8         87.7443       0.976563           2.19           0.977
     8          9         74.1426        2.44141           6.27            2.44
     9         10         74.1426        2.44141           6.27            2.44
    10         11          52.497       0.610352           1.52            0.61
    11         12         41.3297        1.52588           4.63            1.53
    12         13         34.5115        1.52588           6.97            1.53
    13         14         16.9716        1.52588           4.69            1.53
    14         15         8.16797        1.52588           3.77            1.53
    15         16         3.55178        1.52588           3.56            1.53
    16         17         1.38476        1.52588           3.31            1.53
    17         18        0.219553        1.16206           1.66            1.53
    18         19               0      0.0468565              0            1.53

Equation solved.

fsolve completed because the vector of function values is near zero
as measured by the value of the function tolerance, and
the problem appears regular as measured by the gradient.

Используйте vpasolve, чтобы Численно Решить Систему Нелинейных уравнений

Система нелинейных уравнений, F, может быть альтернативно решена с функцией vpasolve, которая является числовым решателем, доступным в Symbolic Math Toolbox. Основное отличие between vpasolve и fsolve - то, что fsolve использует арифметику с двойной точностью, чтобы решить уравнения, тогда как vpasolve использует арифметику переменной точности и поэтому, позволяет вам управлять точностью вычислений.

sol2 = vpasolve(F);

Если вы присваиваете решение системы уравнений к одной переменной, sol2, то vpasolve возвращает решения в форме массива структур. Можно получить доступ к каждому решению (каждое поле массива структур):

sol2.x1
ans = 1.0

Также можно преобразовать sol2 в символьный вектор, и затем получить доступ к области значений решений. Например, отобразите 5-е к 25-м решениям:

for k=(1:64)
  sol2_array(k) = sol2.(char(x(k)));
end
sol2_array(5:25)
ans = (1.01.01.01.01.01.01.01.01.01.01.01.01.01.01.01.01.01.01.01.01.0)

Функции помощника

function [F,J] = genericObj(x,FJFfun,is,js)
% genericObj takes as input, vector x, Function and Jacobian evaluation 
% function handle FJFfun, and sparsity pattern is,js and returns as output,
% the numeric values of the Function and Jacobian: F and Jfunction 
% FJs(1:length(x)) is the numeric vector for the Function
% FJs(length(x)+1:end) is the numeric vector for the non-zero entries of the Jacobian

xcell = num2cell(x);
FJs = FJFfun(xcell{:});
F = FJs(1:length(x));
J = sparse(is,js,FJs(length(x)+1:end));

end

Copyright © 2016 MathWorks, Inc.