복소수 값 데이터에 모델 피팅하기
이 예제에서는 복소수 값 데이터의 비선형 피팅을 수행하는 방법을 보여줍니다. 대부분의 Optimization Toolbox™ 솔버 및 알고리즘은 실수 값 데이터에서만 작동하는 반면, 최소제곱 솔버와 fsolve
는 제약 조건이 없는 문제에 대해 실수 값 데이터와 복소수 값 데이터 모두에서 작동할 수 있습니다. 목적 함수가 복소 함수 측면에서 해석적이어야 합니다.
복소수 데이터 사용 시 FunValCheck
옵션을 'on'
으로 설정하지 마십시오. 솔버에서 오류가 발생합니다. 'interior-point'
알고리즘을 lsqcurvefit
또는 lsqnonlin
과 함께 사용하지 마십시오. 이 알고리즘은 주로 제약 조건을 처리하기 위한 것이며, 복소수 데이터와 함께 사용하는 것에 대해서는 검증되지 않았습니다.
데이터 모델
데이터 모델은 다음과 같이 단순한 지수입니다.
는 입력 데이터이고, 는 응답 변수이고, 는 계수로 구성된 복소수 값 벡터입니다. 와 잡음 있는 관측값 에서 를 추정하는 것이 목적입니다. 데이터 모델은 해석적이므로 이를 복소수 해에서 사용할 수 있습니다.
잡음이 있는 인위적인 데이터
모델에 사용할 인위적인 데이터를 생성합니다. 복소수 계수 벡터 를 [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
이 바람직하지만), 그 이유는 1차 최적성 측정값이 1e-6
미만이 아니라 약 1e-3
이기 때문입니다.
대안: lsqcurvefit 사용
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);
이 코드를 MATLAB® 경로에 파일 cplxreal.m
으로 저장합니다.
응답 변수 데이터를 실수부와 허수부로 분리합니다.
ydata2 = [real(cplxydata),imag(cplxydata)];
계수 벡터 v
는 이제 6개 차원을 가집니다. 이를 모두 1로 초기화하고 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
요소를 6개 가진 벡터 vestimated
를 요소를 3개 가진 복소수형 벡터로 해석합니다. 해가 이전 해와 사실상 동일함을 알 수 있습니다.