# fitting a dual exponential function using nlinfit

9 views (last 30 days)
Angelavtc on 13 Jan 2020
Commented: the cyclist on 15 Jan 2020
I am trying to use nlinfit to find the function that best fits the following set of points:
According to some litterature review this curve could be best described by a dual exponential model defined as:
where a, b, c, d an h are parameters that need to be calibrated using nlinfit.
However, when I use nlinfit my calibration goes terrible and I when I plot the approximation I get something like this:
when what I want is to get something like this:
Is there a way to know which could be the ideal initial conditions?
This is the code that I use to fit the function:
where y axis=Price and x axis=x
%Defining the function to fit
f = @(c,x) (c(5)+(exp((x-c(1))./c(2))-exp(-(x-c(3))./c(4)))./2);
%Setting a guess to start the fit
a=max(x)/10;
initials=[a a a a a];
%Making the curve fit
new_coeffs=nlinfit(x,Price,f,initials)
%Evaluate the new coefficients into the function
new_y=f(new_coeffs,x);
%Plot the approximation
figure(2)
plot(x,Price,...
x,new_y)
Any suggestion of how to get me closer to what I want are really welcome!

the cyclist on 13 Jan 2020
It would be helpful if you uploaded your data and code. Otherwise, it's not possible to see if you just made some simple coding error.
Also, how are you plotting the fit? I assume the lines going back and forth are due to the fact that your x values are not monotonically increasing. You might want to change that, to see what the fit curve really looks like. (But it certainly looks poor, regardless.)
You might also try simply plotting that function for S(t) with arbitrary parameters, and not superimposed on the data, to get a feel for how it behaves. This might also allow you to choose starting values better.
Angelavtc on 13 Jan 2020
Thanks for your answer, as you can see I uploaded my code. Yes, the lines going back and forth are due to a not monotonically increasing movement. But how can I change this to see what the fit curve really looks like?
the cyclist on 14 Jan 2020
Please take my advice about plotting S(t) for different parameters, and using that to guide your initial guess at parameters (your variable initials). Those guesses are probably terrible. Are you getting convergence warnings from nlinfit?
To plot the fit, don't use the original data. Just create values of x that are uniformly spaced. For example
new_x = 1.e4 * (1:0.05:4);
new_y=f(new_coeffs,x);
and then plot the data as points, and the fit as a line:
plot(x,Price,'o',...
x,new_y,'-')

the cyclist on 14 Jan 2020
Edited: the cyclist on 14 Jan 2020
I made up some pretend data that looks a little bit like yours, and did your fit. Here is my code:
% Make up some pretend data
rng default
N = 1000;
xL = 1e4 * (2.1 + 1.5*rand(N,1));
PriceL = 0 + 3000*rand(N,1);
xR = 1e4 * (1.2 + 1.1*rand(N,1));
PriceR = 0 - 3000*rand(N,1);
x = [xL;xR];
Price = [PriceL; PriceR];
%Defining the function to fit
f = @(c,x) c(5) + (exp((x-c(1))./c(2)) - exp(-(x-c(3))./c(4)))./2;
%Setting a guess to start the fit
a=max(x)/10;
initials=[a a a a a];
%Making the curve fit
new_coeffs=nlinfit(x,Price,f,initials);
% Define x values for plotting the fit
fit_x = 1.e4 * (1:0.05:3.6);
% What the initial coefficients produce
init_y = f(initials,fit_x);
% %Evaluate the new coefficients into the function
new_y=f(new_coeffs,fit_x);
% %Plot the approximation
figure
% plot(x,Price,...
% x,new_y)
plot(x,Price,'o',...
fit_x,new_y,'-',...
fit_x,init_y)
legend({'data','new coef','initial coef'},'Location','NorthWest')
Here is what the output looks like:
nlinfit does give a warning about the fit:
==========================================
Warning: Some columns of the Jacobian are effectively zero at the solution, indicating that the model is insensitive to some of its parameters. That may be because those parameters
are not present in the model, or otherwise do not affect the predicted values. It may also be due to numerical underflow in the model function, which can sometimes be avoided by
choosing better initial parameter values, or by rescaling or recentering. Parameter estimates may be unreliable.
==========================================
If I plot the output from the initial coefficients against the random x (instead of monotonically increasing x, as I suggested), it looks like this:
So, it definitely looks like your attempt at fitting is somehow not getting anything much different from your initial (poor) guess. I'm not sure why.
You might want to try my code on your original data.

Angelavtc on 15 Jan 2020
Your answer was really helpful, you are right about plotting S(t) for different parameters, I think the problem starts there but still dont know how to fix it. According to the paper that I am trying to do when the initial values are: 0.694, 0.063,1.144, 0.145 and 53.658 I should get the following graph, but when I try to do it, it does not appear, therefore something should be wrong:
See just the dual-exponential shape and ignore the data points...
any other ideas? Thanks a lot @thecyclist
the cyclist on 15 Jan 2020
This code
guess = [0.694, 0.063,1.144, 0.145, 53.658];
x_test = 0.4 : 0.05 : 1;
f = @(c,x) c(5) + (exp((x-c(1))./c(2)) - exp(-(x-c(3))./c(4)))./2;
figure
plot(x_test,f(guess,x_test))
produces this plot for me:
which looks as expected.
But the x values for your actual fit are 4 orders of magnitude larger than the example plot. So, you'll need to re-scale either your data or the coefficients.