# curve fitting exponential function with two terms

19 views (last 30 days)
Briana Canet on 11 Nov 2023
Commented: Matt J on 13 Nov 2023
Update: I need help curve fitting this set of points with an exponential function with two terms nicely.
% Curve Fit
x = [6500 6350 6000 5400 4500];
y = [0 0.25 0.5 0.75 1.0];
theFit=fit(x' , y', 'exp2')
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) Coefficients (with 95% confidence bounds): a = 0.5 b = 0 c = 0 d = 0
Briana Canet on 11 Nov 2023
Moved: Matt J on 11 Nov 2023
x and y are as shown, but the plot just comes out like a line.
Image Analyst on 12 Nov 2023
Sorry, but I don't believe you. When I swap x and y, the fit looks great.
% Curve Fit
y = [6500 6350 6000 5400 4500];
x = [0 0.25 0.5 0.75 1.0];
theFit=fit(x' , y', 'exp2')
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) Coefficients (with 95% confidence bounds): a = -5.893e+07 (-5.463e+16, 5.463e+16) b = 0.5577 (-3.089e+04, 3.089e+04) c = 5.893e+07 (-5.463e+16, 5.463e+16) d = 0.5576 (-3.089e+04, 3.089e+04)
plot(theFit , x , y)

Matt J on 11 Nov 2023
Edited: Matt J on 11 Nov 2023
You should normalize your x data
% Curve Fit
x = [6500 6350 6000 5400 4500];
x=(x-mean(x))/std(x);
y = [0 0.25 0.5 0.75 1.0];
and using it to generate an initial guess for fit():
e=@(a,xd)exp(a*xd);
flist={@(p,xd) e(p(1),xd) , @(p,xd) e(p(2),xd)};
[bd,ac]=fminspleas(flist,[-1,1],x, y);
theFit=fit(x',y','exp2','StartPoint',[ac(1),bd(1),ac(2), bd(2) ])
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) Coefficients (with 95% confidence bounds): a = 0.6747 (0.0581, 1.291) b = -0.2594 (-0.9322, 0.4135) c = -0.04679 (-0.4881, 0.3946) d = 2.634 (-6.423, 11.69)
plot(theFit,x,y)
Torsten on 12 Nov 2023
Edited: Torsten on 12 Nov 2023
x = [6500 6350 6000 5400 4500];
xt = (x-mean(x))/std(x);
y = [0 0.25 0.5 0.75 1.0];
theFit=fit(xt',y','exp2')
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) Coefficients (with 95% confidence bounds): a = -0.04696 (-0.4897, 0.3958) b = 2.631 (-6.421, 11.68) c = 0.6749 (0.05714, 1.293) d = -0.2592 (-0.9328, 0.4145)
theFit.b = theFit.b/std(x);
Warning: Setting coefficient values clears confidence bounds information.
theFit.a = theFit.a*exp(-theFit.b*mean(x));
theFit.d = theFit.d/std(x);
theFit.c = theFit.c*exp(-theFit.d*mean(x));
theFit
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) Coefficients: a = -4.278e-10 b = 0.00322 c = 4.181 d = -0.0003172
plot(theFit,x,y)
Matt J on 12 Nov 2023
I mentioned in the comments that I needed to change my points (noticed an error in my work).

Matt J on 12 Nov 2023
Edited: Matt J on 12 Nov 2023
You can also use fit()'s normalizer,
x = [6500 6350 6000 5400 4500];
y = [0 0.25 0.5 0.75 1.0];
theFit=fit(x',y','exp2','Normalize','on')
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) where x is normalized by mean 5750 and std 817 Coefficients (with 95% confidence bounds): a = -0.04696 (-0.4897, 0.3958) b = 2.631 (-6.421, 11.68) c = 0.6749 (0.05714, 1.293) d = -0.2592 (-0.9328, 0.4145)
plot(theFit,x,y)
Briana Canet on 12 Nov 2023
Edited: Briana Canet on 12 Nov 2023
Thanks. Also I know, I can plot the 'theFit' directly. But, why isn't line 32 plotting CurveY (see last plot)? I need those a, b, c, and d values/the equation to work for future steps in the code I am developing.
clear;
clc;
close all;
% Curve Fit
x = [6500 6350 6000 5400 4500];
y = [0 0.25 0.5 0.75 1.0];
theFit=fit(x',y','exp2','Normalize','on')
theFit =
General model Exp2: theFit(x) = a*exp(b*x) + c*exp(d*x) where x is normalized by mean 5750 and std 817 Coefficients (with 95% confidence bounds): a = -0.04696 (-0.4897, 0.3958) b = 2.631 (-6.421, 11.68) c = 0.6749 (0.05714, 1.293) d = -0.2592 (-0.9328, 0.4145)
plot(theFit,x,y)
% Monthly Cost
cost = [6500 6350 6000 5400 4500];
costUtility = [0 0.25 0.5 0.75 1.0];
% Plot Utility Points
figure;
plot(cost,costUtility,'*');
xlim([4500 6500]);ylim([0 1.25]);
yticks([costUtility 1.25]);
grid on;
xlabel('Monthly Cost (\$)');
ylabel('Utility');
legend('Utility Points');
a = -0.04696;
b = 2.631;
c = 0.6749;
d = -0.2592;
curveX = linspace(4500,6500);
curveY = a*exp(b*curveX) + c*exp(d*curveX);
hold on;
plot(curveX,curveY,'Color','b');
legend('Utility Points','Utility Curve Fit');
Matt J on 12 Nov 2023
Edited: Matt J on 12 Nov 2023
If you need to explicitly manipulate the coefficients and fit function, you'll have to do the normalization manually:
% Curve Fit
x = [6500 6350 6000 5400 4500];
xmu=mean(x);
xstd=std(x);
y = [0 0.25 0.5 0.75 1.0];
theFit=fit((x-xmu)'/xstd,y','exp2');
% Monthly Cost
cost = x;
costUtility = y;
% Plot Utility Points
figure;
plot(cost,costUtility,'*');
xlim([4500 6500]);ylim([0 1.25]);
yticks([costUtility 1.25]);
grid on;
xlabel('Monthly Cost (\$)');
ylabel('Utility');
legend('Utility Points');
coeff=num2cell(coeffvalues(theFit));
[a,b,c,d]=deal(coeff{:});
curveX = linspace(4500,6500);
X=(curveX-xmu)/xstd;
curveY = a*exp(b*X) + c*exp(d*X);
hold on;
plot(curveX,curveY,'Color','b');
legend('Utility Points','Utility Curve Fit');

Alex Sha on 12 Nov 2023
Edited: Alex Sha on 12 Nov 2023
If taking the fitting function as: y=a*exp(b*x) + c*exp(d*x);
and also taking the data like below directly;
x = [6500 6350 5800 4900 4500];
y = [0 0.25 0.5 0.75 1.0];
The unique stable result should be:
Sum Squared Error (SSE): 0.00221359211819696
Root of Mean Square Error (RMSE): 0.0210408750682901
Correlation Coef. (R): 0.998229714370904
R-Square: 0.996462562653016
Parameter Best Estimate
--------- -------------
a 11.4185972844776
b -0.000545792212445247
c -1.22298024843855E-22
d 0.00759142468815435
If add one more parameter, that is the fitting function become: y=a*exp(b*x)+c*exp(d*x)+e; the result will be perfect:
Sum Squared Error (SSE): 4.41584921368883E-29
Root of Mean Square Error (RMSE): 2.97181736103982E-15
Correlation Coef. (R): 1
R-Square: 1
Parameter Best Estimate
--------- -------------
a -2.47788945923639E-15
b 0.00505297753885221
c 332.002937639918
d -0.00141137023194644
e 0.420769231934917
Alex Sha on 13 Nov 2023
It would be a good suggestion for Mathwork, although not claer how 1stOpt process such problem internally.
Matt J on 13 Nov 2023
MathWorks' fit() routine does have an internal normalization step which can be enabled,
However, if 1stOpt does something similar, it appears to be smart enough to post-transform the parameters and undo the effect of the data normalization. fit() does not do that.