Main Content

야코비 행렬을 사용하지 않은 경우와 포함한 경우의 비선형 최소제곱

이 예제에서는 두 가지 방법으로 비선형 최소제곱 문제를 푸는 방법을 보여줍니다. 먼저, 야코비 행렬 함수를 사용하지 않고 문제를 풉니다. 그런 다음 야코비 행렬을 포함하는 방법을 설명하고, 그 결과 효율성이 향상되었음을 보여줍니다.

이 문제에는 2개의 미지수와 함께 10개 항이 있습니다. 다음을 최소화하는 2차원 벡터 x를 구합니다.

k=110(2+2k-ekx1-ekx2)2,

x0 = [0.3,0.4]에서 시작합니다.

lsqnonlin은 제곱합이 사용자 함수에서 명시적으로 구성되지 않는다고 가정하기 때문에 lsqnonlin에 전달되는 함수는 다음과 같은 벡터 값을 갖는 함수를 계산해야 합니다.

Fk(x)=2+2k-ekx1-ekx2,

여기서 k = 1부터 10까지입니다(즉, F는 10개의 성분을 가져야 함).

야코비 행렬을 사용하지 않고 문제 풀기

이 예제의 마지막 부분에 정의된 헬퍼 함수 myfun은 도함수 정보 없이 벡터 값을 갖는 목적 함수를 구현합니다. 점 x0부터 시작하여 최소화를 풉니다.

x0 = [0.3,0.4]; % Starting guess
[x,resnorm,res,eflag,output] = lsqnonlin(@myfun,x0); % Invoke optimizer
Local minimum possible.
lsqnonlin stopped because the size of the current step is less than
the value of the step size tolerance.

해와 함수 실행 횟수를 검토합니다.

disp(x)
    0.2578    0.2578
disp(resnorm)
  124.3622
disp(output.funcCount)
    72

야코비 행렬을 포함하여 문제 풀기

목적 함수는 단순해 야코비 행렬을 계산하기 좋습니다. 벡터 함수의 야코비 행렬의 정의에 따라 야코비 행렬 함수는 다음과 같은 행렬을 나타냅니다.

Jkj(x)=Fk(x)xj.

여기서 Fk(x)는 목적 함수의 k번째 성분입니다. 이 예제는 다음과 같이 구성되어 있습니다.

Fk(x)=2+2k-ekx1-ekx2,

따라서

Jk1(x)=-kekx1Jk2(x)=-kekx2.

이 예제의 마지막 부분에 정의된 헬퍼 함수 myfun2는 야코비 행렬을 포함하는 목적 함수를 구현합니다. 솔버가 야코비 행렬을 사용하도록 옵션을 설정합니다.

opts = optimoptions(@lsqnonlin,'SpecifyObjectiveGradient',true);

솔버를 실행합니다.

lb = []; % No bounds
ub = [];
[x2,resnorm2,res2,eflag2,output2] = lsqnonlin(@myfun2,x0,lb,ub,opts);
Local minimum possible.
lsqnonlin stopped because the size of the current step is less than
the value of the step size tolerance.

해는 이전 해와 동일합니다.

disp(x2)
    0.2578    0.2578
disp(resnorm2)
  124.3622

야코비 행렬 사용 시 이점은 솔버의 함수 실행 횟수가 훨씬 더 줄어든다는 점입니다.

disp(output2.funcCount)
    24

헬퍼 함수

다음 코드는 myfun 헬퍼 함수를 생성합니다.

function F = myfun(x)
k = 1:10;
F = 2 + 2*k-exp(k*x(1))-exp(k*x(2));
end

다음 코드는 myfun2 헬퍼 함수를 생성합니다.

function [F,J] = myfun2(x)
k = 1:10;
F = 2 + 2*k-exp(k*x(1))-exp(k*x(2));
if nargout > 1
    J = zeros(10,2);
    J(k,1) = -k.*exp(k*x(1));
    J(k,2) = -k.*exp(k*x(2));
end
end

관련 항목