Kh_Ameen
Kh_Ameen

Reputation: 97

curve-fitting for linear and exponential function in Matlab

I have an array of data which, when plotted, looks wave.I need to determine the best fitting (linear and exponential) for these data and find the value of lambda 1,lambda 2 and tau in this function ((L=lambda 1*t+lambda 2*(1-exp(-t/tau). Some friends advice my to use((polyfit)) but I couldn't understanding the applicability of the command after reading the help file and searching in Google. Any help would be greatly appreciated. I will be grateful to you.

my attempt was as following:

%% data 1

file1 = dlmread('outfile_rate_add0.5_depGDP_GTP0.1.txt');
t1      = file1 (:,1);
d1      = file1 (:,2);

% Then call plot()

plot(t1, d1, 'b*-', 'LineWidth', 2, 'MarkerSize', 15);
% Then get a fit

coeffs1 = polyfit(t1, d1, 1)
% Get fitted values
fittedX1 = linspace(min(t1), max(t1), 1001);
fittedY1 = polyval(coeffs1, fittedX1);
% Plot the fitted line
hold on;
plot(fittedX1, fittedY1, 'r-', 'LineWidth', 3);
hold off
hleg = legend('Data','lam*t + c','Location','northEast');

 grid on; 
 title('Line fitting ','fontsize',13,'fontweight','b','color','k')
 xlabel('Time ms','fontsize',13,'fontweight','b','color','k');
 ylabel('Averge length','fontsize',13,'fontweight','b','color','k');

Upvotes: 1

Views: 1458

Answers (1)

Nras
Nras

Reputation: 4311

If you have access to the Optimization toolbox, you can formulate this problem, such that it can be solved with fminsearch(). Here is how it can be done: The parameter to optimize (lambda1, lambda2 and tau) are stored in one parameter-vector, which will be used by the fit_function, which is the function that you proposed.

function main

% some data
t = sort(rand(50,1)*10);
lambda1 = 0.5;
lambda2 = 1;
tau = 2.0;
par = [lambda1, lambda2, tau];
y = fit_function(t, par) + (rand(size(t))-0.5)*0.2;

par0 = [1,2,3]; % initial guess
par_fit = fminsearch(@objFun, par0);

% nested objective function, this one will be minimized
function e = objFun(par)
    yfitted = fit_function(t, par);
    e = sum((yfitted-y).^2);
end

% plotting some results
figure
plot(t,fit_function(t,par),'k-')
hold on
plot(t,y,'ko')
plot(t,fit_function(t,par_fit),'rx-')
legend('original','noisy','optimization')
par
par_fit

end

function yfitted = fit_function(t, par)
% y = lambda1*t + lambda2*(1-exp(-t/tau))
    lambda1 = par(1);
    lambda2 = par(2);
    tau = par(3);
    yfitted = lambda1*t + lambda2*(1-exp(-t/tau)); 
end

The result looks like this: enter image description here The parameters i used for the unnoisy data and the parameters which came out of the optimization are like this

par =

    0.5000    1.0000    2.0000


par_fit =

    0.4949    1.0433    2.1792

Best, Nras.

Update for your use-case

function main
%% ----- DATA ----- 
file1 = dlmread('outfile_rate_add0.5_depGDP_GTP0.1.txt');
t = file1(:,1);
y = file1(:,2);

%% ----- OPTIMIZATION ----- 
par0 = [1,2,3]; % initial guess <--- Here you have to make a good guess 
par_fit = fminsearch(@objFun, par0);

%% ----- OBJECTIVE FUNCTION (will be minimized) ----- 
function e = objFun(par)
    yfitted = fit_function(t, par); % result of model function with current parameter
    e = sum((yfitted-y).^2); % minimize squared distance between model and observation
end

%% ----- VSIUALIZING RESULTS ----- %
figure
plot(t,y,'ko')
hold on
plot(t,fit_function(t,par_fit),'rx-')
legend('original','optimization')
end

%% ----- MODEL FUNCTION ----- %
function yfitted = fit_function(t, par)
% the model function reads as:  y = lambda1*t + lambda2*(1-exp(-t/tau))
    lambda1 = par(1);
    lambda2 = par(2);
    tau = par(3);
    yfitted = lambda1*t + lambda2*(1-exp(-t/tau)); 
end

Upvotes: 3

Related Questions