Matlab function for Lorentz substitutions with global variables

I want to bind Lorentz to my data, so first I want to test my fitting procedure on simulated data:

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

      

initial parameters

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

      

find the minimum to fit

afinal = fminsearch(@devsum,a0);

      

afinal is a vector with parameters for my fit. If I check my function like this

d= devsum(a0)

      

then d = 0, but if I do exactly what in my function

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

      

then d is not zero. How is this possible? My function is super simple, so I don't know what will go wrong. my function:

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

      

Basically I just implement the things I found here http://www.home.uni-osnabrueck.de/kbetzler/notes/fitp.pdf page 7

+3


source to share


2 answers


It is usually best to avoid using global variables. I usually solve these problems by first defining the function that calculates the curve you want to fit as a function x

and parameters:

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

      

This way, you can reuse the function later to build the match result.

Then you define a small anonymous function with the property you want to keep to a minimum, with only one parameter, since that's the format you want fminsearch

. Instead of using global variables, the measured x

and Y

"captured" (the technical term makes a closure on these variables) in the definition of an anonymous function:

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

      



And finally, you approach your options while minimizing error with fminsearch

:

fitted_param = fminsearch(fit_error, starting_param);

      

Quick demo:

% 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')

      

Result: enter image description here

+3


source


Could you use cauchy_pdf instead of lorentz definition?



0


source







All Articles