3

いくつかのデータをローレンツ関数に当てはめたいのですが、桁数が異なるパラメータを使用すると、当てはめの問題が発生します。

この私のローレンツ関数:

function [ value ] = lorentz( x,x0,gamma,amp )
    value = amp * gamma^2 ./ ((x-x0).^2 + gamma^2);
end

サンプルデータを生成するスクリプトは次のとおりです。

x = linspace(2e14,6e14,200);
x0 = 4.525e14;
gamma = 0.5e14;
amp = 2e-14;

y = lorentz(x,x0,gamma,amp);

ローレンツをサンプル データに適合させるスクリプトは次のとおりです。

params = [4.475e14;0.4e14;1.8e-14];
opts = optimset('TolFun',1e-60,'TolX',1e-50,'Display','Iter');
fitfunc = @(params,x) lorentz(x,params(1),params(2),params(3));
fitparams = lsqcurvefit(fitfunc,params,x,y,[],[],opts)

figure(1);hold on;
plot(x,y,'.');
plot(x,lorentz(x,params(1),params(2),params(3)),'--');
plot(x,lorentz(x,fitparams(1),fitparams(2),fitparams(3)));
hold off;

これは、最後のパラメーター (振幅である最小) のみを変更します。すべての指数を除外すると、期待どおりに機能します。オプションの微調整が必​​要だと思いますが、方法がわかりません。これを行う方法はありますか?

4

1 に答える 1

2

あなたが示唆したように、パラメータが 28 (!) 桁を超えて変化するときはいつでも、数値的な問題に遭遇するでしょう。たとえば、LSQCURVEFIT は適切な勾配ステップを試行して推定しますが、これらの計算は数値の安定性に影響される場合があります (実際の実装によっては、http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithmを参照してください)。これがどのように行われるかの要約)。

私の経験では、入力パラメーターを正規化して比較しやすくする方法を見つける必要があります。たとえば、すべての値のログを取得し、それらを目的関数内で exp() することができます。

params = log([4.475e14;0.4e14;1.8e-14])

function [ value ] = lorentz( x,x0,gamma,amp )
    gamma = exp(gamma); 
    amp = exp(amp);
    x0 = exp(x0);
    value = amp * gamma^2 ./ ((x-x0).^2 + gamma^2);
end

これにより、他の不安定性が生じる可能性がありますが、開始する必要があります。

于 2013-01-13T02:43:01.170 に答える