주요 콘텐츠

복소수 값 데이터에 모델 피팅하기

이 예제에서는 복소수 값 데이터의 비선형 피팅을 수행하는 방법을 보여줍니다. 대부분의 Optimization Toolbox™ 솔버 및 알고리즘은 실수 값 데이터에서만 작동하는 반면, 최소제곱 솔버와 fsolve는 제약 조건이 없는 문제에 대해 실수 값 데이터와 복소수 값 데이터 모두에서 작동할 수 있습니다. 목적 함수가 복소 함수 측면에서 해석적이어야 합니다.

복소수 데이터 사용 시 FunValCheck 옵션을 "on"으로 설정하지 마십시오. 솔버에서 오류가 발생합니다. "interior-point" 알고리즘을 lsqcurvefit 또는 lsqnonlin과 함께 사용하지 마십시오. 이 알고리즘은 주로 제약 조건을 처리하기 위한 것이며, 복소수 데이터와 함께 사용하는 것에 대해서는 검증되지 않았습니다. 코드 생성 시 복소수 데이터는 사용할 수 없습니다.

데이터 모델

데이터 모델은 다음과 같이 단순한 지수입니다.

y(x)=v1+v2ev3x.

x는 입력 데이터이고, y는 응답 변수이고, v는 계수로 구성된 복소수 값 벡터입니다. x와 잡음 있는 관측값 y에서 v를 추정하는 것이 목적입니다. 데이터 모델은 해석적이므로 이를 복소수 해에서 사용할 수 있습니다.

잡음이 있는 인위적인 데이터

모델에 사용할 인위적인 데이터를 생성합니다. 복소 계수 벡터 v[2;3+4i;-.5+.4i]로 지정합니다. 관측값 x를 지수 분포로 지정합니다. 응답 변수 y에 복소수 값 잡음을 추가합니다.

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;  

계수 벡터를 복구하기 위해 모델 피팅하기

데이터 모델이 예측한 응답 변수와 관측값(x에 해당하는 xdatay에 해당하는 응답 변수 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 = 3×1 complex

   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 = 3×1 complex

   2.1582 + 0.1351i
   2.7399 + 3.8012i
  -0.5338 + 0.4660i

resnorm = 
100.9933

기본 알고리즘이 동일하기 때문에 결과는 lsqnonlin의 결과와 일치합니다. 더 편리하다고 생각되는 솔버를 사용하십시오.

대안: 실수부와 허수부 분리

범위를 포함하려면 또는 단순히 실수 값 내에 온전히 유지하려면, 계수의 실수부와 허수부를 별도의 변수로 분리할 수 있습니다. 이 문제에서 계수를 다음과 같이 분리합니다.

y=v1+iv2+(v3+iv4)exp((v5+iv6)x)=(v1+v3exp(v5x)cos(v6x)-v4exp(v5x)sin(v6x))+i(v2+v4exp(v5x)cos(v6x)+v3exp(v5x)sin(v6x)).

lsqcurvefit에 대한 응답 함수를 작성합니다.

<include>cplxreal.m</include>

이 코드를 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);
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.

<stopping criteria details>
vestimated,resnorm,exitflag,output.firstorderopt 
vestimated = 6×1

    2.1582
    0.1351
    2.7399
    3.8012
   -0.5338
    0.4660

resnorm = 
100.9933
exitflag = 
3
ans = 
0.0018

요소를 6개 가진 벡터 vestimated를 요소를 3개 가진 복소수형 벡터로 해석합니다. 해가 이전 해와 사실상 동일함을 알 수 있습니다.

참고 항목

도움말 항목