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 находит намного лучшее решение, чем локальный решатель один.

Похожие темы