lsqcurvefit
или lsqnonlin
Этот пример показывает аппроксимацию функции к данным с помощью lsqcurvefit
совместно с MultiStart
. В конце примера показано то же решение с использованием lsqnonlin
.
Многие аппроксимации имеют несколько локальных решений. MultiStart
может помочь найти глобальное решение, означающее лучшую подгонку. Этот пример сначала использует lsqcurvefit
из-за его удобного синтаксиса.
Модель является
где входные данные , и параметры , , , и являются неизвестными коэффициентами модели.
Написание анонимной функции, которая принимает матрицу данных xdata
с N
строки и два столбца, и возвращает вектор отклика с N
строки. Функция также принимает матрицу коэффициентов p
, соответствующий вектору коэффициента .
fitfcn = @(p,xdata)p(1) + p(2)*xdata(:,1).*sin(p(3)*xdata(:,2)+p(4));
Создайте 200 точек данных и ответов. Используйте значения . Включите случайный шум в ответ.
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
Установите границы для lsqcurvefit
. Нет никаких причин для превысить в абсолютном значении, потому что функция синуса принимает значения во всей области значений на любом интервале ширины . Примите, что коэффициент должно быть меньше 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
Подгонка параметров к данным, начиная с 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).
MultiStart
.Создайте структуру задачи так MultiStart
может решить ту же задачу.
problem = createOptimProblem('lsqcurvefit','x0',p0,'objective',fitfcn,... 'lb',lb,'ub',ub,'xdata',xdata,'ydata',ydata);
Решите задачу аппроксимации, используя 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
находит намного лучшее решение, чем только локальный решатель.