В этом примере показано, как выполнить нелинейный фитинг кривой наименьших квадратов с помощью рабочего процесса оптимизации на основе проблем.
Модельное уравнение для этой задачи:
(r2t),
где , , и - неизвестные параметры, - ответ, t - время. Проблема требует данных для времени tdata и (шумные) измерения отклика ydata. Цель состоит в том, чтобы найти лучшие и , то есть те значения, которые минимизируют
) 2.
Как правило, у вас есть данные для проблемы. В этом случае генерируйте искусственные шумные данные для проблемы. Использовать A = [1,2] и r = [-1,-3] в качестве базовых значений и использовать 200 случайных значений из 0 до 3 в качестве временных данных. Постройте график результирующих точек данных.
rng default % For reproducibility A = [1,2]; r = [-1,-3]; tdata = 3*rand(200,1); tdata = sort(tdata); % Increasing times for easier plotting noisedata = 0.05*randn(size(tdata)); % Artificial noise ydata = A(1)*exp(r(1)*tdata) + A(2)*exp(r(2)*tdata) + noisedata; plot(tdata,ydata,'r*') xlabel 't' ylabel 'Response'

Данные шумные. Поэтому решение, вероятно, не будет соответствовать исходным параметрам. A и r очень хорошо.
Поиск наиболее подходящих параметров A и r, сначала определите переменные оптимизации с этими именами.
A = optimvar('A',2); r = optimvar('r',2);
Создайте выражение для целевой функции, представляющее собой сумму квадратов для минимизации.
fun = A(1)*exp(r(1)*tdata) + A(2)*exp(r(2)*tdata); obj = sum((fun - ydata).^2);
Создание проблемы оптимизации с целевой функцией obj.
lsqproblem = optimproblem("Objective",obj);Для подхода, основанного на проблемах, укажите начальную точку как структуру, а имена переменных - как поля структуры. Укажите начальный A = [1/2,3/2] и начальный r = [-1/2,-3/2].
x0.A = [1/2,3/2]; x0.r = [-1/2,-3/2];
Просмотрите формулировку проблемы.
show(lsqproblem)
OptimizationProblem :
Solve for:
A, r
minimize :
sum(arg6)
where:
arg5 = extraParams{3};
arg6 = (((A(1) .* exp((r(1) .* extraParams{1}))) + (A(2) .* exp((r(2) .* extraParams{2})))) - arg5).^2;
extraParams
Решите проблему.
[sol,fval] = solve(lsqproblem,x0)
Solving problem using lsqnonlin. Local minimum found. Optimization completed because the size of the gradient is less than the value of the optimality tolerance. <stopping criteria details>
sol = struct with fields:
A: [2×1 double]
r: [2×1 double]
fval = 0.4724
Постройте график полученного решения и исходных данных.
figure responsedata = evaluate(fun,sol); plot(tdata,ydata,'r*',tdata,responsedata,'b-') legend('Original Data','Fitted Curve') xlabel 't' ylabel 'Response' title("Fitted Response")

График показывает, что подогнанные данные достаточно хорошо соответствуют исходным шумным данным.
Узнайте, насколько точно подогнанные параметры соответствуют исходным параметрам A = [1,2] и r = [-1,-3].
disp(sol.A)
1.1615
1.8629
disp(sol.r)
-1.0882 -3.2256
Установленные параметры отключены примерно на 15% в A и 8% в r.
fcn2optimexprЕсли целевая функция не состоит из элементарных функций, необходимо преобразовать функцию в выражение оптимизации с помощью fcn2optimexpr. См. раздел Преобразование нелинейной функции в выражение оптимизации. Для настоящего примера:
fun = @(A,r) A(1)*exp(r(1)*tdata) + A(2)*exp(r(2)*tdata); response = fcn2optimexpr(fun,A,r); obj = sum((response - ydata).^2);
Остальные шаги в решении проблемы одинаковы. Единственное другое отличие - в подпрограмме построения графика, куда вы звоните response вместо fun:
responsedata = evaluate(response,sol);
Список поддерживаемых функций см. в разделе Поддерживаемые операции с переменными и выражениями оптимизации.