我想将一些数据拟合到lorentz函数中,但是当我使用不同数量级的参数时,我会发现拟合问题。
这是我的lorentz功能:
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);
用于将lorentz拟合到样本数据的脚本:
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;
这仅改变最后一个参数(最小值,即幅度)。如果我将所有指数都排除在外,它会按预期工作。我假设有一些微调的选择要做,但我不知道怎么做。任何想法如何做到这一点?
答案 0 :(得分: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
这可能会引入其他不稳定因素,但它应该让你开始。