メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

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

この例では、非線形最小二乗問題を解く 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.

<stopping criteria details>

解と関数評価回数を検証します。

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.

<stopping criteria details>

解は前の解と同じです。

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

参考

トピック