Этот пример показывает, как выполнить нелинейный подбор кривой комплексных данных. В то время как большинство решателей Optimization Toolbox™ и алгоритмов работают только с реальными данными, решателями и fsolve
методом наименьших квадратов может работать как с реальными, так и со сложными данными для задач без ограничений. Целевая функция должна быть аналитической в смысле комплексной функции.
Не устанавливайте FunValCheck
опция для 'on'
при использовании комплексных данных. Ошибки решателя.
Модель данных является простой экспоненциальной:
Это входные данные, является откликом и является комплексным вектором коэффициентов. Цель состоит в том, чтобы оценить и зашумленные наблюдения. Модель данных аналитическая, поэтому можно использовать ее в комплексном решении.
Сгенерируйте искусственные данные для модели. Примите вектор комплексного коэффициента как [2;3+4i;-.5+.4i]
. Примите наблюдения как экспоненциально распределенные. Добавьте комплексный шум к откликам.
rng default % for reproducibility N = 100; % number of observations v0 = [2;3+4i;-.5+.4i]; % coefficient vector xdata = -log(rand(N,1)); % exponentially distributed noisedata = randn(N,1).*exp((1i*randn(N,1))); % complex noise cplxydata = v0(1) + v0(2).*exp(v0(3)*xdata) + noisedata;
Различие между ответом, предсказанным моделью данных, и наблюдением (xdata
для и cplxydata отклика
для) является:
objfcn = @(v)v(1)+v(2)*exp(v(3)*xdata) - cplxydata;
Используйте любой из lsqnonlin
или lsqcurvefit
для подгонки модели к данным. Этот пример сначала использует lsqnonlin
.
opts = optimoptions(@lsqnonlin,'Display','off'); x0 = (1+1i)*[1;1;1]; % arbitrary initial guess [vestimated,resnorm,residuals,exitflag,output] = lsqnonlin(objfcn,x0,[],[],opts); vestimated,resnorm,exitflag,output.firstorderopt
vestimated = 2.1582 + 0.1351i 2.7399 + 3.8012i -0.5338 + 0.4660i resnorm = 100.9933 exitflag = 3 ans = 0.0018
lsqnonlin
восстанавливает вектор комплексного коэффициента примерно до одной значащей цифры. Норма невязки значительна, что указывает на то, что шум мешает модели подгонять все наблюдения. Выходной флаг 3
, не предпочтительный 1
, потому что мера оптимальности первого порядка - это около 1e-3
, не ниже 1e-6
.
Для подгонки с помощью lsqcurvefit
, запишите модель, чтобы дать только ответы, а не ответы минус данные отклика.
objfcn = @(v,xdata)v(1)+v(2)*exp(v(3)*xdata);
Использование lsqcurvefit
опции и синтаксис.
opts = optimoptions(@lsqcurvefit,opts); % reuse the options
[vestimated,resnorm] = lsqcurvefit(objfcn,x0,xdata,cplxydata,[],[],opts)
vestimated = 2.1582 + 0.1351i 2.7399 + 3.8012i -0.5338 + 0.4660i resnorm = 100.9933
Результаты совпадают с результатами из lsqnonlin
, потому что базовые алгоритмы идентичны. Используйте любой решатель, который вы найдете более удобным.
Чтобы включить ограничения или просто остаться полностью в пределах вещественных значений, можно разделить действительные и комплексные части коэффициентов на отдельные переменные. Для этой задачи разделите коэффициенты следующим образом:
Напишите функцию отклика для lsqcurvefit
.
function yout = cplxreal(v,xdata) yout = zeros(length(xdata),2); % allocate yout expcoef = exp(v(5)*xdata(:)); % magnitude coscoef = cos(v(6)*xdata(:)); % real cosine term sincoef = sin(v(6)*xdata(:)); % imaginary sin term yout(:,1) = v(1) + expcoef.*(v(3)*coscoef - v(4)*sincoef); yout(:,2) = v(2) + expcoef.*(v(4)*coscoef + v(3)*sincoef);
Сохраните этот код как файл cplxreal.m
на пути MATLAB ®.
Разделите данные отклика на его реальную и мнимую части.
ydata2 = [real(cplxydata),imag(cplxydata)];
Вектор коэффициентов v
теперь имеет шесть размерностей. Инициализируйте его как все таковые и решите задачу используя lsqcurvefit
.
x0 = ones(6,1);
[vestimated,resnorm,residuals,exitflag,output] = ...
lsqcurvefit(@cplxreal,x0,xdata,ydata2);
vestimated,resnorm,exitflag,output.firstorderopt
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. vestimated = 2.1582 0.1351 2.7399 3.8012 -0.5338 0.4660 resnorm = 100.9933 exitflag = 3 ans = 0.0018
Интерпретируйте вектор с шестью vestimated
как трехэлементный комплексный вектор, и вы видите, что решение фактически совпадает с предыдущими решениями.