MultiStart Используя lsqcurvefit или lsqnonlin

Этот пример показывает, как соответствовать функции к данным с помощью lsqcurvefit вместе с MultiStart. Конец примера показывает то же решение с помощью lsqnonlin.

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

Модель

y=a+bx1sin(cx2+d),

где входные данные x=(x1,x2), и параметры a, b, c, и d неизвестные коэффициенты модели.

Шаг 1. Создайте целевую функцию.

Запишите анонимную функцию, которая берет матрицу данных xdata со строками N и двумя столбцами, и возвращает вектор отклика со строками N. Функция также берет матрицу коэффициентов p, соответствуя вектору коэффициентов (a,b,c,d).

fitfcn = @(p,xdata)p(1) + p(2)*xdata(:,1).*sin(p(3)*xdata(:,2)+p(4));

Шаг 2. Создайте данные тренировки.

Создайте 200 точек данных и ответы. Используйте значения a=-3,b=1/4,c=1/2,d=1. Включайте случайный шум в ответ.

rng default % For reproducibility
N = 200; % Number of data points
preal = [-3,1/4,1/2,1]; % Real coefficients

xdata = 5*rand(N,2); % Data points
ydata = fitfcn(preal,xdata) + 0.1*randn(N,1); % Response data with noise

Шаг 3. Установите границы и начальную точку.

Установите границы для lsqcurvefit. Нет никакой причины d превысить π в абсолютном значении, потому что синусоидальная функция принимает значения в своем полном спектре на любом интервале ширины 2π. Примите что коэффициент c должно быть меньшим, чем 20 в абсолютном значении, потому что разрешение высокой частоты может вызвать нестабильные ответы или неточную сходимость.

lb = [-Inf,-Inf,-20,-pi];
ub = [Inf,Inf,20,pi];

Установите начальную точку произвольно на (5,5,5,0).

p0 = 5*ones(1,4); % Arbitrary initial point
p0(4) = 0; % Ensure the initial point satisfies the bounds

Шаг 4. Найдите лучшую локальную подгонку.

Соответствуйте параметрам к данным, запускающимся в p0.

[xfitted,errorfitted] = lsqcurvefit(fitfcn,p0,xdata,ydata,lb,ub)
Local minimum possible.

lsqcurvefit stopped because the final change in the sum of squares relative to 
its initial value is less than the value of the function tolerance.
xfitted = 1×4

   -2.6149   -0.0238    6.0191   -1.6998

errorfitted = 28.2524

lsqcurvefit находит локальное решение, которое не является особенно близко к значениям параметра модели (–3,1/4,1/2,1).

Шаг 5. Настройте проблему для MultiStart.

Создайте структуру задачи, таким образом, MultiStart может решить ту же проблему.

problem = createOptimProblem('lsqcurvefit','x0',p0,'objective',fitfcn,...
    'lb',lb,'ub',ub,'xdata',xdata,'ydata',ydata);

Шаг 6. Найдите глобальное решение.

Решите подходящую проблему с помощью MultiStart с 50 итерациями. Постройте самую маленькую ошибку как количество итераций MultiStart.

ms = MultiStart('PlotFcns',@gsplotbestf);
[xmulti,errormulti] = run(ms,problem,50)

MultiStart completed the runs from all start points.

All 50 local solver runs converged with a positive local solver exit flag.
xmulti = 1×4

   -2.9852   -0.2472   -0.4968   -1.0438

errormulti = 1.6464

MultiStart находит глобальное решение около значений параметров (–3, –1/4, –1/2, –1). (Это эквивалентно решению около preal = (–3,1/4,1/2,1), потому что изменение знака всех коэффициентов кроме первого дает те же численные значения fitfcn.) Норма остаточной ошибки уменьшается от приблизительно 28 до приблизительно 1,6, уменьшения больше, чем фактор 10.

Сформулируйте проблему для lsqnonlin

Для альтернативного подхода используйте lsqnonlin в качестве подходящей функции. В этом случае используйте различие между ожидаемыми значениями и фактическими значениями данных как целевая функция.

fitfcn2 = @(p)fitfcn(p,xdata)-ydata;
[xlsqnonlin,errorlsqnonlin] = lsqnonlin(fitfcn2,p0,lb,ub)
Local minimum possible.

lsqnonlin stopped because the final change in the sum of squares relative to 
its initial value is less than the value of the function tolerance.
xlsqnonlin = 1×4

   -2.6149   -0.0238    6.0191   -1.6998

errorlsqnonlin = 28.2524

Запуская с той же начальной точки p0, lsqnonlin находит то же относительно плохое решение как lsqcurvefit.

Запустите MultiStart с помощью lsqnonlin в качестве локального решателя.

problem2 = createOptimProblem('lsqnonlin','x0',p0,'objective',fitfcn2,...
    'lb',lb,'ub',ub');
[xmultinonlin,errormultinonlin] = run(ms,problem2,50)

MultiStart completed the runs from all start points.

All 50 local solver runs converged with a positive local solver exit flag.
xmultinonlin = 1×4

   -2.9852   -0.2472   -0.4968   -1.0438

errormultinonlin = 1.6464

Снова, MultiStart находит намного лучшее решение, чем локальный решатель один.

Похожие темы