Problem in curve fitting using curvefitter app

I am trying to curvefit some data on a customised exponential equation: y=A*exp(-(x-x0)/t) using curvefitter application in MATLAB.
While doing so, for x ranging from 30 to 70, the curvefitter is not able to curve fit though I was able to do the same when I was using the equation y=A*(1-exp(-(x-x0)/t)) when x ranges from 70 to 80.
Also, the curvefitting was successful when I tried to curvefit for the equation y=A*(1-exp(-x/t)), x0 being omitted here because the starting point is of x is 0 and x ranges from 0 to 30.
For the curvefitting, A, t and x0 are the parameters to be found by curvefitting the data.
x0 is close to the starting point of x, it is being included to avoid very large exponent values.
The curvefitter is giving a horizontal line only.
I have attached images for both cases.
Case 1:
Case 2:
Case 3:

8 Comments

From my initial understanding, it seems the issue might be related to the initial conditions for A,x0 and t.
Could you please provide the data, if possible, so I can examine the issue more closely?
The curve fitter application gives random starting points in case of customised equation. For the case when it is giving curve fit with acceptable RMSE, then only upper and lower bounds were taken care of from user's end.
In case of custom equation, you can set the start points by going to the Advanced options as shown.
Please find the .mat file for the case when the curve fitter application is giving horizontal line only.
You may take the x values from 30.1 to 70 with 0.1 gap.
Could you provide or attach the data for analysis?
From the trend, I believe that data may be fitted using the piecewise function:
.
Yes, you are right, it is a piecewise exponential function.
Please find the .mat file I have just attached to my previous reply to @Shashi Kiran
Try adding a constant term to the custom equation and set intial alue of x0 to 30(as x starts from 30) as shown.
This helps in corrrect fit.
Thank you for your response, is there any way to fit it without using constant term? I know that it may need a constant term but I am trying to simply keep one exponent term only. Because for previous cases, as shared in the images attached, I was able to do it roughly without using the constant term.

Sign in to comment.

Answers (1)

I fitted the data using a logarithm function:
%% Data
load('yvalues_curvefit_case.mat');
y = y3a_DOD_dot1;
x = linspace(30, 70, numel(y))';
%% Fitting model
fo = fitoptions('Method', 'NonlinearLeastSquares',...
'Lower', [0.01, 200, 28, 0.21, 85, 1.03],...
'Upper', [0.03, 220, 30, 0.23, 95, 1.05],...
'StartPoint', [0.02, 210, 29, 0.22, 90, 1.04]);
ft = fittype('a*log(b*(x - c)^d + e*(x - c)^f)', ...
'dependent', {'prob'}, 'independent', {'x'}, ...
'coefficients', {'a', 'b', 'c', 'd', 'e', 'f'}, ...
'options', fo);
%% Fit curve to data
[yfit, gof] = fit(x, y, ft)
yfit =
General model: yfit(x) = a*log(b*(x - c)^d + e*(x - c)^f) Coefficients (with 95% confidence bounds): a = 0.02118 (0.01775, 0.02461) b = 207.9 (9.807, 405.9) c = 30 (30, 30) d = 0.2246 (0.1566, 0.2927) e = 85.89 (13.01, 158.8) f = 1.035 (0.892, 1.179)
gof = struct with fields:
sse: 1.1873e-05 rsquare: 0.9999 dfe: 394 adjrsquare: 0.9999 rmse: 1.7360e-04
%% Plot results
plot(yfit, x, y), grid on
xlabel('t'), ylabel('x(t)')
legend('Data', 'Fitted model')

5 Comments

Thank you for your response but my required equation for fitting must have only single exponential or in other words logarithmic term only. For two exponents, it is giving a fit but I am trying to fit it roughly for one exponent term.
You can fit the data using any desired model; however, the best fit always depends on the constraints of the parameters you supply to the curve-fitting algorithm.
Additionally, you should already know that your model is an exponentially decaying function for the amplitude . Since your data shows a monotonically increasing trend, the exponentially decaying function must be reflected about the x-axis so that the parameter .
The reason @Shashi Kiran added a constant k is to provide a bias to the function, allowing the fitted model to be adjusted up or down along the y-axis.
%% Data
load('yvalues_curvefit_case.mat');
y = y3a_DOD_dot1;
x = linspace(30, 70, numel(y))';
%% Fitting model
fo = fitoptions('Method', 'NonlinearLeastSquares',...
'Lower', [-0.07, 0.17, 11, 29],...
'Upper', [-0.05, 0.19, 13, 31]);
ft = fittype('A*exp(-(x-x0)/t) + d', ...
'dependent', {'prob'}, 'independent', {'x'}, ...
'coefficients', {'A', 'd', 't', 'x0'});
%% Fit curve to data
[yfit, gof] = fit(x, y, ft, 'StartPoint', [-0.06, 0.18, 12, 30])
yfit =
General model: yfit(x) = A*exp(-(x-x0)/t) + d Coefficients (with 95% confidence bounds): A = -0.06049 (-5.089e+04, 5.089e+04) d = 0.177 (0.1762, 0.1778) t = 11.85 (11.31, 12.4) x0 = 30 (-9.97e+06, 9.97e+06)
gof = struct with fields:
sse: 0.0025 rsquare: 0.9746 dfe: 396 adjrsquare: 0.9744 rmse: 0.0025
%% Plot results
plot(yfit, x, y), grid on
xlabel('t'), ylabel('x(t)')
legend('Data', 'Fitted model')
Thank you for your indepth response. I also realised that the fitting is possible by adding a constant term to the equation in this case.
@Sam Chak: the fitting function of "a*log(b*(x - c)^d + e*(x - c)^f)" gives wonderful result, however, the best solution will be as fellow, the objective function value of SSE is little better, but with much different parameters:
Sum Squared Error (SSE): 2.3362432323886E-6
Root of Mean Square Error (RMSE): 7.64238711462033E-5
Correlation Coef. (R): 0.999988328851169
R-Square: 0.999976657838553
Parameter Best Estimate
--------- -------------
a 0.00767031100705701
b 5971471.14414276
c 30.0935323605759
d 1.00821070650148
e 911138.477416586
f 2.54707754950121
Hey @Alex Sha,
Thank you for providing the values with a better sum of squared errors. I forgot to mention to the OP (@Farkhanda Azmi) that the constraint for parameter c should be less than 30 (), rather than exactly 30, as displayed due to rounding. The reason for this is that the data begins at , and the initial value of should be finite. If , then the fitting function will produce complex values.
Another candidate function is the surd function; however, I did not conduct a more thorough investigation.
format long g
%% Fit curve to data
[yfit, gof] = fit(x, y, ft)
yfit =
General model: yfit(x) = a*log(b*(x - c)^d + e*(x - c)^f) Coefficients (with 95% confidence bounds): a = 0.02118 (0.01775, 0.02461) b = 207.9 (9.807, 405.9) c = 30 (30, 30) d = 0.2246 (0.1566, 0.2927) e = 85.89 (13.01, 158.8) f = 1.035 (0.892, 1.179)
gof = struct with fields:
sse: 1.18733567720894e-05 rsquare: 0.999881369453811 dfe: 394 adjrsquare: 0.999879863990027 rmse: 0.000173595573905024
c = yfit.c
c =
29.998908662656

Sign in to comment.

Categories

Products

Release

R2024a

Asked:

on 20 Sep 2024

Commented:

on 21 Sep 2024

Community Treasure Hunt

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

Start Hunting!