Main Content

이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

비선형 최소제곱, 문제 기반

이 예제에서는 문제 기반 최적화 워크플로를 사용하여 비선형 최소제곱 곡선 피팅을 수행하는 방법을 보여줍니다.

모델

이 문제의 모델 방정식은 다음과 같습니다.

y(t)=A1exp(r1t)+A2exp(r2t),

여기서 A1, A2, r1, r2는 알려지지 않은 파라미터이며, y는 응답 변수, t는 시간입니다. 이 문제를 풀려면 시간 데이터 tdata와 (잡음 있는) 응답 측정 데이터 ydata가 필요합니다. 최상의 Ar을 찾는 것이 목적이며 이는 다음을 최소화하는 값을 의미합니다.

ttdata(y(t)-ydata)2.

샘플 데이터

대개 문제를 설명하는 데이터가 있습니다. 이 경우 문제에 대해 인위적으로 잡음이 있는 데이터를 생성합니다. A = [1,2]r = [-1,-3]을 기본 값으로 사용하고 시간 데이터로 0에서 3 사이의 랜덤 값 200개를 사용합니다. 결과 데이터 점을 플로팅합니다.

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'

Figure contains an axes object. The axes object with xlabel t, ylabel Response contains a line object which displays its values using only markers.

데이터에 잡음이 있습니다. 따라서, 해가 원래 파라미터 Ar과 완전히 일치하지 않을 수 있습니다.

문제 기반 접근법

최적의 파라미터 Ar을 구하기 위해 먼저 이러한 이름을 가진 최적화 변수를 정의합니다.

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{1}:

         0.0139
         0.0357
         0.0462
         0.0955
         0.1033
         0.1071
         0.1291
         0.1385
         0.1490
         0.1619
         0.1793
         0.2276
         0.2279
         0.2345
         0.2434
         0.2515
         0.2533
         0.2894
         0.2914
         0.2926

         :
         :

       extraParams{2}:

         0.0139
         0.0357
         0.0462
         0.0955
         0.1033
         0.1071
         0.1291
         0.1385
         0.1490
         0.1619
         0.1793
         0.2276
         0.2279
         0.2345
         0.2434
         0.2515
         0.2533
         0.2894
         0.2914
         0.2926

         :
         :

       extraParams{3}:

         2.9278
         2.7513
         2.7272
         2.4199
         2.3172
         2.3961
         2.2522
         2.1974
         2.1666
         2.0944
         1.9566
         1.7989
         1.7984
         1.7540
         1.8318
         1.6745
         1.6874
         1.5526
         1.5229
         1.5680

         :
         :

문제 기반 해

문제를 풉니다.

[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.
sol = struct with fields:
    A: [2x1 double]
    r: [2x1 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")

Figure contains an axes object. The axes object with title Fitted Response, xlabel t, ylabel Response contains 2 objects of type line. One or more of the lines displays its values using only markers These objects represent Original Data, Fitted Curve.

이 플롯은 피팅된 데이터가 원래 잡음이 있는 데이터와 상당히 잘 일치함을 보여줍니다.

피팅된 파라미터가 원래 파라미터 A = [1,2]r = [-1,-3]과 얼마나 근접한지 살펴보십시오.

disp(sol.A)
    1.1615
    1.8629
disp(sol.r)
   -1.0882
   -3.2256

피팅된 파라미터는 A의 경우 약 15%, r의 경우 약 8% 차이가 납니다.

지원되지 않는 함수는 fcn2optimexpr을 필요로 함

목적 함수가 기본 함수로 구성되지 않은 경우 fcn2optimexpr을 사용하여 함수를 최적화 표현식으로 변환해야 합니다. Convert Nonlinear Function to Optimization Expression 항목을 참조하십시오. 현재 예제의 경우 다음과 같습니다.

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);

문제 풀이의 나머지 단계는 동일합니다. 유일한 차이점은 플로팅 루틴에서 fun 대신 response를 호출하는 것입니다.

responsedata = evaluate(response,sol);

지원되는 함수 목록은 Supported Operations for Optimization Variables and Expressions 항목을 참조하십시오.

참고 항목

관련 항목