fitting data with a combination of exponential and linear form ( a*exp(-x/b)+c*x+d )

40 views (last 30 days)
Hello Altruists,
I have been trying to fit my data to a combination of exponential and linear form, i.e., a*exp(-x/b)+c*x+d . I am not getting a good fit (image attached). I am getting an warning as well (Warning: Start point not provided, choosing random start point). Could anyone offer some help?
I have tried with this code:
data= readmatrix('data');
x= data(:,1);
y = data(:,2);
% getting fitting parameters
explinearfit = fittype('a*exp(-x/b)+c*x+d')
fo = fitoptions(explinearfit);
fo.normalize = 'on';
myFit = fit(x,y,explinearfit);
%plot
plot(myFit,x,y)
ylabel('Y')
xlabel('X')
legend('Data','Fit', 'location', 'best')

Answers (4)

Matt J
Matt J on 4 Jul 2023
Edited: Matt J on 4 Jul 2023
If you download fminspleas, you can get a pretty good fit with a fairly naive initial guess [b,e,f]=[-1,0,0]:
[x,y]=readvars('data.csv');
flist={ @(p,x)exp(p(1)*x) ,@(p,x) x, 1, @(p,x)tanh(p(2)*x+p(3))};
warning off
[p,coeff]=fminspleas(flist,[-1,0,0],x,y,-inf(1,3),[0,inf,inf]); warning on
p(:).'
ans = 1×3
-0.0007 0.0005 0.0075
xs=linspace(min(x),max(x));
plot(x,y,'--g',xs, ffit(xs,p,coeff,flist));
function y=ffit(x,p,coeff,flist)
y=0;
for i=1:numel(flist)
f=flist{i};
if isnumeric(f)
y=y+coeff(i)*f;
else
y=y+coeff(i)*f(p,x);
end
end
end

Torsten
Torsten on 3 Jul 2023
Moved: Torsten on 3 Jul 2023
Try
f(x) = a*atan(b*x)
It's too steep at the beginning and too flat at the end, but better than your model function.
data= readmatrix('data');
x = data(:,1);
y = data(:,2);
f = @(p) p(1)*atan(p(2)*x);
fun = @(p) f(p) - y;
sol = lsqnonlin(fun,[2/pi 1])
Local minimum possible. lsqnonlin stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
sol = 1×2
0.6070 0.0006
hold on
plot(x,y,'o')
plot(x,f(sol))
hold off
  1 Comment
Md Shariful Islam
Md Shariful Islam on 3 Jul 2023
Thanks for your time answering my question. I appreciate this.
If I use 2 expoential functions (a*exp(b*x)+c*exp(d*x)), I could achieve a better fit as well. I used curve fitting tool achieve the fitting parameters. I was looking for something better; that is why I was exploring to linear+exponential form.
"
clc; clear; close all;
%%
data= readmatrix('data');
x= data(:,1);
y = data(:,2);
a = 0.7057;
b = 1.746e-05;
c = -0.6389;
d = -0.0006763;
y_f= a*exp(b*x)+c*exp(d*x);
figure;
plot(x,y, 's')
hold on
plot(x,y_f)
ylabel('X')
xlabel('Y')
legend('data', 'fit')
set(gca, 'fontname', 'times', 'fontsize', 12)
box on
"

Sign in to comment.


Alex Sha
Alex Sha on 4 Jul 2023
If taking fitting function as "y=a*exp(-x/b)+c*x+d", the result will be:
Sum Squared Error (SSE): 0.473516174967249
Root of Mean Square Error (RMSE): 0.0194398036424297
Correlation Coef. (R): 0.993172772220197
R-Square: 0.986392155479551
Parameter Best Estimate
--------- -------------
a -0.626947642051749
b 1365.46862978889
c 1.57136165222552E-5
d 0.682801486192597
If taking fitting function as "y=a*exp(b*x)+c*exp(d*x)", the result will be:
Sum Squared Error (SSE): 0.517841961771885
Root of Mean Square Error (RMSE): 0.0203293308633968
Correlation Coef. (R): 0.992531430423344
R-Square: 0.985118640378209
Parameter Best Estimate
--------- -------------
a -0.637793104918275
b -0.00067464442828496
c 0.705787394940032
d 1.74592589676531E-5
A much better result will be obtained if taking fitting function as "y=a*exp(b*x)+c*x+d+tanh(e*x+f)*p"
Sum Squared Error (SSE): 0.154723411889559
Root of Mean Square Error (RMSE): 0.0111122622277951
Correlation Coef. (R): 0.997774312797138
R-Square: 0.995553579277802
Parameter Best Estimate
--------- -------------
a -0.44380788683452
b -0.000338851451599573
c 1.0070723631259E-5
d 0.571547658395962
e 0.0025117355962601
f -0.850904593274322
p 0.195041944730927
  3 Comments
Torsten
Torsten on 4 Jul 2023
Edited: Torsten on 4 Jul 2023
Try if you can reproduce the results if you use the fitting parameters as initial guesses in MATLAB.
@Alex Sha has his "special tool" to do the fitting (not part of MATLAB), and I think he invests quite a long time to adequate initial guesses for the parameters.
Alex Sha
Alex Sha on 5 Jul 2023
I'm ashamed that it's not my product, although hopefully it's a commercial optimization solver package, I just like to use it because it's simple to use but works well.

Sign in to comment.


Sam Chak
Sam Chak on 5 Jul 2023
The data seems to exhibit the pattern of an nth-root function (a form of the power function), given by
where is a negative exponent function that varies with x. Because the data is bounded by 1, we can assume that . Since the exponential function-based models yield some good results in @Alex Sha's fitting, I attempted with the following model:
Fit model #1
% Data Sets
[x, y] = readvars('data.csv');
% Curve-fitting
fo = fitoptions('Method', 'NonlinearLeastSquares', ...
'Lower', [-0.9, -0.006, -0.07, -0.0002, -1.2, -0.04, -0.2, -0.0008], ...
'Upper', [0, 0, 0, 0, 0, 0, 0, 0], ...
'StartPoint', [1 1 1 1 1 1 1 1]);
ft = fittype('x^(a*exp(b*x) + c*exp(d*x) + e*exp(f*x) + g*exp(h*x))', 'options', fo);
[yfit, gof] = fit(x, y, ft)
yfit =
General model: yfit(x) = x^(a*exp(b*x) + c*exp(d*x) + e*exp(f*x) + g*exp(h*x)) Coefficients (with 95% confidence bounds): a = -0.289 (-0.5166, -0.06147) b = -0.003427 (-0.004609, -0.002245) c = -0.06304 (-0.06519, -0.06088) d = -0.0001293 (-0.0001322, -0.0001264) e = -0.975 (-1.186, -0.7636) f = -0.008562 (-0.01062, -0.006502) g = -0.1089 (-0.1211, -0.09673) h = -0.0007063 (-0.0007685, -0.0006441)
gof = struct with fields:
sse: 0.1447 rsquare: 0.9958 dfe: 1245 adjrsquare: 0.9958 rmse: 0.0108
figure
plot(x, y, '.', 'color', '#A7B7F7'), hold on
plot(yfit, 'r'), hold off, grid on
legend('Data', 'Fitted curve', 'location', 'best')
Note that the coefficients are not unique. In my machine, I got different results"
Fit model #2
General model:
f(x) = x^(a*exp(b*x) + c*exp(d*x) + e*exp(f*x) + g*exp(h*x))
Coefficients (with 95% confidence bounds):
a = -0.1227 (-0.1285, -0.1169)
b = -0.0007697 (-0.0008078, -0.0007315)
c = -0.06455 (-0.06617, -0.06292)
d = -0.0001311 (-0.0001335, -0.0001288)
e = -1.12 (-1.968, -0.2716)
f = -0.03423 (-0.0573, -0.01116)
g = -0.8431 (-0.929, -0.7572)
h = -0.005286 (-0.005609, -0.004962)
Goodness of fit:
SSE: 0.1438
R-square: 0.9959
Adjusted R-square: 0.9958
RMSE: 0.01075
Fit model #3
General model:
f(x) = x^(a*exp(b*x) + c*exp(d*x) + e*exp(f*x) + g*exp(h*x))
Coefficients (with 95% confidence bounds):
a = -0.8429 (-0.9291, -0.7566)
b = -0.005285 (-0.00561, -0.00496)
c = -0.06455 (-0.06617, -0.06292)
d = -0.0001311 (-0.0001335, -0.0001288)
e = -1.107 (-1.94, -0.2753)
f = -0.03402 (-0.05694, -0.01109)
g = -0.1227 (-0.1285, -0.1169)
h = -0.0007697 (-0.0008078, -0.0007315)
Goodness of fit:
SSE: 0.1438
R-square: 0.9959
Adjusted R-square: 0.9958
RMSE: 0.01075
  3 Comments
Alex Sha
Alex Sha on 5 Jul 2023
For fitting function provided by @Sam Chak, the results are actually unique, only the order is different
Sum Squared Error (SSE): 0.143801140894944
Root of Mean Square Error (RMSE): 0.0107128649564239
Correlation Coef. (R): 0.997931669471303
R-Square: 0.995867616933781
Parameter Best Estimate
--------- -------------
a -0.842982011054431
b -0.00528502909652476
c -0.122676258206711
d -0.000769613241785951
e -0.0645440331501187
f -0.000131143071549622
g -1.11996380236003
h -0.0342317204260728

Sign in to comment.

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!