Main Content

非線形最小二乗法とヤコビアンの有無

この例では、非線形最小二乗問題を解く 2 つの方法を説明します。この例では、まず、ヤコビ関数を使わずに問題を解きます。次いで、ヤコビアンを含める方法と、それによる効率性の改善について説明します。

この問題には 10 個の項と 2 個の未知数があります。次を最小化する、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

関連するトピック