Main Content

このページは機械翻訳を使用して翻訳されました。元の英語を参照するには、ここをクリックします。

lsqcurvefit または lsqnonlin を使用したマルチスタート

この例では、lsqcurvefitMultiStart を組み合わせて使用して、関数をデータに適合させる方法を示します。例の最後では、lsqnonlin を使用した同じソリューションを示しています。

多くのフィッティング問題には複数のローカル ソリューションが存在します。MultiStart は、最適なフィッティングを意味するグローバル ソリューションを見つけるのに役立ちます。この例では、便利な構文のため、まず lsqcurvefit を使用します。

モデルは次のとおりです。

y=a+bx1sin(cx2+d),

ここで、入力データは x=(x1,x2) であり、パラメーター abc、および d は未知のモデル係数です。

手順 1: 目的関数を作成します。

N 行と 2 列のデータ マトリックス xdata を受け取り、N 行の応答ベクトルを返す匿名関数を記述します。この関数は、係数ベクトル (a,b,c,d) に対応する係数行列 p も受け取ります。

fitfcn = @(p,xdata)p(1) + p(2)*xdata(:,1).*sin(p(3)*xdata(:,2)+p(4));

手順 2: トレーニングデータを作成します。

200 個のデータ ポイントと応答を作成します。値 a=-3,b=1/4,c=1/2,d=1 を使用します。応答にランダムノイズを含めます。

rng default % For reproducibility
N = 200; % Number of data points
preal = [-3,1/4,1/2,1]; % Real coefficients

xdata = 5*rand(N,2); % Data points
ydata = fitfcn(preal,xdata) + 0.1*randn(N,1); % Response data with noise

手順 3: 境界と初期点を設定します。

lsqcurvefit の境界を設定します。正弦関数は幅 2π の任意の区間にわたってその全範囲の値を取るため、d が絶対値で π を超える理由はありません。高い周波数を許可すると応答が不安定になったり、収束が不正確になったりする可能性があるため、係数 c の絶対値は 20 より小さくする必要があると想定します。

lb = [-Inf,-Inf,-20,-pi];
ub = [Inf,Inf,20,pi];

初期点を任意に(5,5,5,0)に設定します。

p0 = 5*ones(1,4); % Arbitrary initial point
p0(4) = 0; % Ensure the initial point satisfies the bounds

手順 4: 最適なローカルフィットを見つけましょう。

p0 から始めて、パラメータをデータに適合させます。

[xfitted,errorfitted] = lsqcurvefit(fitfcn,p0,xdata,ydata,lb,ub)
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.
xfitted = 1×4

   -2.6149   -0.0238    6.0191   -1.6998

errorfitted = 28.2524

lsqcurvefit は、モデル パラメーター値 (–3,1/4,1/2,1) に特に近いわけではないローカル ソリューションを見つけます。

手順 5: MultiStart の問題を設定します。

MultiStart が同じ問題を解決できるように問題構造を作成します。

problem = createOptimProblem('lsqcurvefit','x0',p0,'objective',fitfcn,...
    'lb',lb,'ub',ub,'xdata',xdata,'ydata',ydata);

手順 6.グローバルな解決策を見つけましょう。

MultiStart を使用して 50 回の反復でフィッティング問題を解きます。最小誤差を MultiStart 反復回数としてプロットします。

ms = MultiStart('PlotFcns',@gsplotbestf);
[xmulti,errormulti] = run(ms,problem,50)

MultiStart completed the runs from all start points. 

All 50 local solver runs converged with a positive local solver exitflag.
xmulti = 1×4

   -2.9852   -0.2472   -0.4968   -1.0438

errormulti = 1.6464

MultiStart は、パラメータ値 (–3,–1/4,–1/2,–1) 付近のグローバル ソリューションを探します。(これは、preal = (–3,1/4,1/2,1) 付近の解に相当します。最初の係数を除くすべての係数の符号を変更すると、fitfcn と同じ数値が得られるためです。)残差誤差のノルムは約 28 から約 1.6 に減少し、10 倍以上の減少となります。

lsqnonlin の問題を定式化する

別の方法として、フィッティング関数として lsqnonlin を使用します。この場合、予測値と実際のデータ値の差を目的関数として使用します。

fitfcn2 = @(p)fitfcn(p,xdata)-ydata;
[xlsqnonlin,errorlsqnonlin] = lsqnonlin(fitfcn2,p0,lb,ub)
Local minimum possible.

lsqnonlin stopped because the final change in the sum of squares relative to 
its initial value is less than the value of the function tolerance.
xlsqnonlin = 1×4

   -2.6149   -0.0238    6.0191   -1.6998

errorlsqnonlin = 28.2524

同じ初期点 p0 から開始して、 lsqnonlinlsqcurvefit と同じ比較的貧弱な解を見つけます。

lsqnonlin をローカル ソルバーとして使用して MultiStart を実行します。

problem2 = createOptimProblem('lsqnonlin','x0',p0,'objective',fitfcn2,...
    'lb',lb,'ub',ub');
[xmultinonlin,errormultinonlin] = run(ms,problem2,50)

MultiStart completed the runs from all start points. 

All 50 local solver runs converged with a positive local solver exitflag.
xmultinonlin = 1×4

   -2.9852   -0.2472   -0.4968   -1.0438

errormultinonlin = 1.6464

ここでも、MultiStart はローカル ソルバーのみよりもはるかに優れたソリューションを見つけます。

関連するトピック