I have an extremely basic question seeking to answer why the following function in MatLab does not properly fit the given data to a logistic curve, given the correct equation for one. The solution to this is likely quite simple, but I am entirely unfamiliar with the MatLab curve fitting toolbox. My code is as follows:
function [fitresult, gof] = createFit1(Dose, Response)
%CREATEFIT1(DOSE,RESPONSE)
% Create a fit.
%
% Data for 'untitled fit 1' fit:
% X Input : Dose
% Y Output: Response
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 08-Sep-2022 20:16:26
%% Fit: 'untitled fit 1'.
Dose = [1.6*10^4;1.84*10^4;2.08*10^4;2.32*10^4; 2.56*10^4;2.8*10^4;3.04*10^4;3.28*10^4;3.52*10^4;3.76*10^4;4*10^4;4.24*10^4]
Response = [0;0.1004;0.2830;0.4338;0.5638;0.6834;0.8030;0.8680;0.9294;0.9614;0.9978;1]
[xData, yData] = prepareCurveData( Dose, Response );
% Set up fittype and options.
ft = fittype( '1/(1+exp(-k*Dose))', 'independent', 'Dose', 'dependent', 'Response' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = 0.0755269568571602;
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
legend( h, 'Response vs. Dose', 'untitled fit 1', 'Location', 'NorthEast', 'Interpreter', 'none' );
% Label axes
xlabel( 'Dose', 'Interpreter', 'none' );
ylabel( 'Response', 'Interpreter', 'none' );
grid on
They are probably two causses of bad fitting.
First : Obviously the points are not located close to a simple logistic curve but close to a shifted logistic curve. So, it is suggested to change the model equation in your code.
Second : The non-linear regression is an iterative process requiring to set some guessed initial values of parameters. If the initial values are too far from the unknown exact values the calculus might fail to achieve a good fit.
If you don't know how to guess some initial values of the parameters better use a not iterative method which doesn't requires initial values as shown below.
Numerical example with your data :
If you want to use your non-linear regression software you can use the above good approximates of the parameters to initiate the iterative process.
An even better fitting would be obtained with a not only horizontal shift (horizontal and vertical shifts).
For information on the non-iterative method used above (linear fitting of an integral equation to which the logistic function is solution ) : https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales .
In addition : FOUR PARAMETERS LOGISTIC CURVE FITTING
Related
I used matlab's CFtool to generate a fit based on a custom function, however, when I generate that code and call it to my main script file the curves are slightly different. My generated code does not cross the y -int, although it does in CFtool. Does any body know what the issue is? I have tried setting different start points and it didn't change anything.
Suggestions
Generated code:
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( I100M, P100M );
% Set up fittype and options.
ft = fittype( 'a*tanh(-b*x/300)+c', 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = [0.990128346443291 0.106912965297856 0.94637904214048];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
CFtool fit
generated code
Having 2 vectors vec_x and vec_y, i perform a fitting with a non-linear least squares like this :
%%myfunction.m
function F = myfun(x,vec_x)
F = 10*(erfc((x(1)+x(2)*vec_x)/sqrt(2))/2);
end
%%console
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
x = lsqcurvefit(#myfun, [0 1], vec_x, vec_y,[],[],options); %here i obtain x(1) and x(2).
When i want to plot the fitting curve with the associated points(vec_x .vs vec_y), i perform it like this :
y_fit=10*erfc((x(1)+x(2)*vec_x)/sqrt(2))/2
plot(vec_x,y_fit)
The problem is that i have a weird curve not similar to the one i have automatically when i'm using the "Curv-fit App" tool of Matlab (i use the same custom function and vectors as the console).
In the Curve-fitting GUI, i got this : see the image below
snapshot-curveFitting-GUI
How can i have the right plot so i can more mange the plot ?
I found the answer on the doc of Matlab. For plotting the curve fit from the Cftool, we should select File->Generate code. The Curve Fitting app generates code from the current session and displays the file in the MATLAB Editor. The file includes all fits and plots in the current session. We have to execute the code to have the plot.
this is the code that was generated by Matlab:
function [fitresult, gof] = createFit_MSSI_Venus(RockerArm, mos)
%CREATEFIT1(ROCKERARM,MOS)
% Create a fit.
%
% Data for 'Psychometric curve fitting MSSI-RockeArm 3D mesh' fit:
% X Input : RockerArm
% Y Output: mos
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 08-Jan-2016 15:40:41
%% Fit: 'Psychometric curve fitting MSSI-RockeArm 3D mesh'.
[xData, yData] = prepareCurveData( RockerArm, mos );
% Set up fittype and options.
ft = fittype( 'erfc((a+b*x)/sqrt(2))/2', 'independent', 'x',
'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Algorithm = 'Levenberg-Marquardt';
opts.Display = 'Off';
opts.StartPoint = [0.655477890177557 0.171186687811562];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'Psychometric curve fitting MSSI-RockeArm 3D mesh' );
h = plot( fitresult, xData, yData);
set(h, 'Markersize',20);
legend( h, 'mos vs. RockerArm', 'Psychometric curve fitting MSSI-
RockeArm 3D mesh', 'Location', 'NorthEast' );
% Label axes
xlabel MSSI-RockerArm 3D mesh
ylabel mos
grid on
Thanks again
I used the MATLAB curve fitting tool to do a spline smoothing fit and created a function from it. How can I access the Y fit values so I can output them to a file? Seems I am only seeing the x values, and all of the coefs from fitresult. Here is the matlab code. Thanks!
function [fitresult, gof] = createFit(Freq, AmplNew)
%CREATEFIT(FREQ,AMPLNEW)
% Create a fit.
%
% Data for 'untitled fit 1' fit:
% X Input : Freq
% Y Output: AmplNew
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( Freq, AmplNew );
% Set up fittype and options.
ft = fittype( 'smoothingspline' );
opts = fitoptions( 'Method', 'SmoothingSpline' );
opts.SmoothingParam = 0.998;
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
Simply use feval:
y = feval(fitresult,x);
or just use
y = fitresult(x);
I am using Matlab's curve fitting tool, cftool, to fit a set of points which I have. The problem I am facing is that the generate code function will not give me the same fit as produced in the cftool.
This is not what I want because I want to be able to retrieve the data from the residual plot. I could also just copy the function from cftool and do it manually. But I do not understand why the generated code will not just give me the same curve fit.
The cftool session file: http://dl.dropbox.com/u/20782274/test.sfit
The generated code from Matlab:
function [fitresult, gof] = createFit1(Velocity, kWhPerkm)
%CREATEFIT1(VELOCITY,KWHPERKM)
% Create a fit.
%
% Data for 'untitled fit 3' fit:
% X Input : Velocity
% Y Output: kWhPerkm
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 02-Dec-2012 16:36:19
%% Fit: 'untitled fit 3'.
[xData, yData] = prepareCurveData( Velocity, kWhPerkm );
% Set up fittype and options.
ft = fittype( 'a/(0.008*x) + c*x^2 + d*90', 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( ft );
opts.DiffMaxChange = 0.01;
opts.Display = 'Off';
opts.Lower = [-Inf -Inf -Inf];
opts.MaxFunEvals = 1000;
opts.MaxIter = 1000;
opts.StartPoint = [0 0 0];
opts.Upper = [Inf Inf Inf];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Create a figure for the plots.
figure( 'Name', 'untitled fit 3' );
% Plot fit with data.
subplot( 2, 1, 1 );
plot( fitresult, xData, yData, 'predobs' );
% Label axes
xlabel( 'Velocity' );
ylabel( 'kWhPerkm' );
grid on
% Plot residuals.
subplot( 2, 1, 2 );
plot( fitresult, xData, yData, 'residuals' );
% Label axes
xlabel( 'Velocity' );
ylabel( 'kWhPerkm' );
grid on
The curve I get with the generated code:
http://i.stack.imgur.com/65d1P.jpg
The curve I need:
http://i.stack.imgur.com/p3Egp.jpg
So does anyone know what goes wrong?
-edit-
And the Velocity and WhPerkm data file: http://dl.dropbox.com/u/20782274/data.mat
RE: I want to be able to retrieve the data from the residual plot
One way to do this is:
Select "Save to Workspace..." from the Fit menu
Ensure that "Save fit output to MATLAB struct named" is checked.
Note the name of variable. By default, it is output.
Click "OK" to send data to the MATLAB workspace.
In the MATLAB workspace, the residuals will be in output.residuals. For your example, you can plot the residuals via, e.g.,
>> plot( Velocity, output.residuals, '.' )
Is there any way to use cftool non-interactively. For example, given x, y and the fitting function, calling cftool to generate and returned the fitted data without using opening the toolbox GUI. Thanks
I don't know, but there's another way.
File/Generate Code
You can use the fit function that comes with Curve Fitting Toolbox. To find out more, type doc fit. Or you can use cftool interactively, then use Generate Code from the File menu to create a function that uses the fit command to repeat your interactive work programmatically. Use this as a template example.
function [fitresult, gof] = Custom_fit(x,y,My_Equation)
% example -->My_Equation = 'a*exp(-b*x)+c*exp(-d*x)' % y=f(x)
[xData, yData] = prepareCurveData( x, y );
% Set up fittype and options.
ft = fittype(My_Equation, 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = [0.0376273842264444 0.821185653244809 0.81656489972889 0.961898080855054];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
end
code.