用于lorentzian的Matlab函数与全局变量拟合

时间:2015-05-07 13:30:17

标签: matlab curve-fitting

我想让Lorentzian适合我的数据,所以首先我要测试我对模拟数据的拟合程序:

X = linspace(0,100,200);
Y = 20./((X-30).^2+20)+0.08*randn(size(X));

启动参数

a3 = ((max(X)-min(X))/10)^2;
a2 = (max(X)+min(X))/2;
a1 = max(Y)*a3;
a0 = [a1,a2,a3];

找到合适的最小值

afinal = fminsearch(@devsum,a0);

afinal是带有参数的矢量。如果我按如下方式测试我的功能

d= devsum(a0)

然后d = 0,但如果我确实在我的功能中做了什么

a=a0;
d = sum((Y - a(1)./((X-a(2)).^2+a(3))).^2)

然后d不等于零。这怎么可能?我的功能非常简单,所以我不知道出了什么问题。 我的职责:

%devsum.m
function d = devsum(a)
global X Y
d = sum((Y - a(1)./((X-a(2)).^2+a(3))).^2);
end

基本上我只是实现了我在这里找到的东西 http://www.home.uni-osnabrueck.de/kbetzler/notes/fitp.pdf 第7页

1 个答案:

答案 0 :(得分:3)

通常最好避免使用全局变量。我通常解决这些问题的方法是首先定义一个函数,该函数根据x和参数来评估您想要拟合的曲线:

% lorentz.m
function y = lorentz(param, x)
y = param(1) ./ ((x-param(2)).^2 + param(3))

通过这种方式,您可以稍后重复使用该函数来绘制拟合的结果。

然后,使用要最小化的属性定义一个小的匿名函数,只使用一个参数作为输入,因为这是fminsearch所需的格式。在匿名函数的定义中,测量的XY不是使用全局变量,而是“捕获”(技术术语对这些变量做closure):

fit_error = @(param) sum((y_meas - lorentz(param, x_meas)).^2)

最后,您通过使用fminsearch

最小化错误来调整参数
fitted_param = fminsearch(fit_error, starting_param);

快速演示:

% simulate some data
X = linspace(0,100,200);
Y = 20./((X-30).^2+20)+0.08*randn(size(X));

% rough guess of initial parameters
a3 = ((max(X)-min(X))/10)^2;
a2 = (max(X)+min(X))/2;
a1 = max(Y)*a3;
a0 = [a1,a2,a3];

% define lorentz inline, instead of in a separate file
lorentz = @(param, x) param(1) ./ ((x-param(2)).^2 + param(3));

% define objective function, this captures X and Y
fit_error = @(param) sum((Y - lorentz(param, X)).^2);

% do the fit
a_fit = fminsearch(fit_error, a0);

% quick plot
x_grid = linspace(min(X), max(X), 1000); % fine grid for interpolation
plot(X, Y, '.', x_grid, lorentz(a_fit, x_grid), 'r')
legend('Measurement', 'Fit')
title(sprintf('a1_fit = %g, a2_fit = %g, a3_fit = %g', ...
    a_fit(1), a_fit(2), a_fit(3)), 'interpreter', 'none')

结果: enter image description here