使用lsqcurvefit拟合 [英] fit using lsqcurvefit

查看:285
本文介绍了使用lsqcurvefit拟合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为Lorentz函数拟合一些数据,但是当我使用不同数量级的参数时,我发现拟合存在问题.

I want to fit some data to a lorentz function but I figure problems with fitting when I use parameters which are of different orders of magnitude.

这是我的lorentz函数:

This my lorentz function:

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

现在该脚本生成示例数据:

Now the script to generate sample data:

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

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

以及用于将lorentz拟合到示例数据的脚本:

And the script for fitting lorentz to the sample data:

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;

这仅改变最后一个参数(最小,即振幅).如果我不考虑所有指数,它将按预期工作.我认为可以对选择进行一些微调,但是我不知道该怎么做.任何想法如何做到这一点?

This only varies the last parameter (the smallest, which is the amplitude). If I leave all exponentials out it works as expected. I assume there is some finetuning of opts to be done, but I don't know how. Any ideas how to do this?

推荐答案

正如您所建议的,只要参数变化超过28(!)个数量级,就会遇到数值问题.例如,LSQCURVEFIT将尝试并估计适当的梯度步长,并且这些计算可能对数值稳定性敏感(取决于实际的实现方式-请参见

As you suggested, you're going to run into numerical issues whenever you have parameters that vary over 28 (!) orders of magnitude. LSQCURVEFIT, for example, will try and estimate proper gradient steps, and those calculations may be sensitive to numerical stability (depending on the actual implementation - see http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm for a summary of how all this is done).

以我的经验,您需要找到一种方法来标准化输入参数,使它们更具可比性.例如,您可以获取所有值的日志,然后在目标函数内部将它们exp()记录下来.

In my experience, you need to find a way to normalize the input parameters that make them more comparable. For example, you can take the log of all the values, and then exp() them inside you're objective function.

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

这可能会带来其他不稳定因素,但这应该可以帮助您入门.

That may introduce other instabilities, but it should get you started.

这篇关于使用lsqcurvefit拟合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆