Personal fit using lsq

1 view (last 30 days)
Fc Fc
Fc Fc on 9 Jun 2018
Commented: Fc Fc on 11 Jun 2018
Hi every one. I have a couple of data "t,y" file
i need to fit them by using this function
where a,b,c are parameters that I must get by the fit.
I wrote:
A=load('D:/datifit.txt')
t=A(:,1);
y=A(:,2);
plot(t,y,'ro');
title('Data');
to plot the data and I get the plot...later, to fit, I wrote:
F=@(x,xdata)(xdata/15+0.964)*(xdata/15+0.964)*x(1)+2*(xdata/15+0.964)*(xdata*xdata/15-0.36*xdata)*x(2)+(xdata*xdata/15-0.36*xdata)*(xdata*xdata/15-0.36*xdata)*x(3)
x0=[1 1 1];
[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)
but I get this error
Error using *
Inner matrix dimensions must agree.
Error in
@(x,xdata)(xdata/15+0.964)*(xdata/15+0.964)*x(1)+2*(xdata/15+0.964)*(xdata*xdata/15-0.36*xdata)*x(2)+(xdata*xdata/15-0.36*xdata)*(xdata*xdata/15-0.36*xdata)*x(3)
Error in lsqcurvefit (line 202)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial objective function evaluation. LSQCURVEFIT cannot continue.
Can someone help me please?
  1 Comment
Image Analyst
Image Analyst on 9 Jun 2018
Here I was getting all ready to help you and then I found out you forgot to attach 'D:/datifit.txt'. I'll check back later in the day. http://www.mathworks.com/matlabcentral/answers/6200-tutorial-how-to-ask-a-question-on-answers-and-get-a-fast-answer

Sign in to comment.

Answers (3)

Image Analyst
Image Analyst on 9 Jun 2018
Edited: Image Analyst on 9 Jun 2018
Since you didn't supply your actual data, I just made up some. Here is my program for you:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format short g;
format compact;
fontSize = 25;
% Define function that the X values obey.
X = sort(rand(1, 50));
a = 10 % Arbitrary sample values I picked.
b = 1
c = 1
% Get a vector. No noise in this Y yet.
Y = (X/15+0.964)*a + 2*(X/15+0.964).*(X.^2/15-0.36*X)*b+(X.^2/15-0.36).^2*c;
plot(X, Y, 'bd-');
grid on;
% Add noise to Y.
Y = Y + 0.001 * randn(1, length(Y));
% Now we have noisy training data that we can send to fitnlm().
% Plot the noisy initial data.
plot(X, Y, 'b*', 'LineWidth', 2, 'MarkerSize', 15);
grid on;
% Convert X and Y into a table, which is the form fitnlm() likes the input data to be in.
tbl = table(X', Y');
% Define the model as Y = (X/15+0.964)*a + 2*(X/15+0.964).*(X.^2/15-0.36*X)*b+(X.^2/15-0.36).^2*c
% Note how this "x" of modelfun is related to big X and big Y.
% x((:, 1) is actually X and x(:, 2) is actually Y - the first and second columns of the table.
modelfun = @(b,x) (x(:, 1)/15+0.964)*b(1) + 2*(x(:, 1)/15+0.964).*(x(:, 1).^2/15-0.36*x(:, 1))*b(2)+(x(:, 1).^2/15-0.36).^2*b(3);
beta0 = [10, .8, 1.2]; % Guess values to start with. Just make your best guess.
% Now the next line is where the actual model computation is done.
mdl = fitnlm(tbl, modelfun, beta0);
% Now the model creation is done and the coefficients have been determined.
% YAY!!!!
% Extract the coefficient values from the the model object.
% The actual coefficients are in the "Estimate" column of the "Coefficients" table that's part of the mode.
coefficients = mdl.Coefficients{:, 'Estimate'}
% Create smoothed/regressed data using the model:
a = coefficients(1)
b = coefficients(2)
c = coefficients(3)
yFitted = (X/15+0.964)*a + 2*(X/15+0.964).*(X.^2/15-0.36*X)*b+(X.^2/15-0.36).^2*c;
% Now we're done and we can plot the smooth model as a red line going through the noisy blue markers.
hold on;
plot(X, yFitted, 'r-', 'LineWidth', 2);
grid on;
title('Non-Linear Regression with fitnlm()', 'FontSize', fontSize);
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
legendHandle = legend('Noisy Y', 'Fitted Y', 'Location', 'north');
legendHandle.FontSize = 25;
message = sprintf('Coefficients : \n a = %8.5f\n b = %8.5f\n c = %8.5f',...
coefficients(1), coefficients(2), coefficients(3));
text(0.1, 9.778, message, 'FontSize', 23, 'Color', 'r', 'FontWeight', 'bold', 'Interpreter', 'none');
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0.04, 1, 0.96]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
and here is the result:
  3 Comments
Image Analyst
Image Analyst on 9 Jun 2018
Stephan, do you like it enough to "Accept this Answer" and "Vote" for it?
For the others, don't be afraid that the code looks long and complicated. It's not. Most of the code is just comment lines, lines to create a sample data set, and code to make a fancy plot. The actual code that does the fit/regressions and get the coefficients is only 3 lines!
modelfun = @(b,x) (x(:, 1)/15+0.964)*b(1) + 2*(x(:, 1)/15+0.964).*(x(:, 1).^2/15-0.36*x(:, 1))*b(2)+(x(:, 1).^2/15-0.36).^2*b(3);
beta0 = [10, .8, 1.2];
mdl = fitnlm(tbl, modelfun, beta0);
Stephan
Stephan on 9 Jun 2018
Edited: Stephan on 9 Jun 2018
Hi,
I already voted for this answer. If i could i would accept this answer but i was not the one who asked the question. Im only the guy which tried to answer this question in a convetional way.
Best regards
Stephan

Sign in to comment.


Stephan
Stephan on 9 Jun 2018
Edited: Stephan on 9 Jun 2018
Hi,
try this:
F = @(x,xdata)x(1).*(xdata.*(1.0./1.5e1)+2.41e2./2.5e2).^2+x(3).*(xdata.*(9.0./2.5e1)-xdata.^2.*(1.0./1.5e1)).^2-x(2).*(xdata.*(2.0./1.5e1)+2.41e2./1.25e2).*(xdata.*(9.0./2.5e1)-xdata.^2.*(1.0./1.5e1))
do not worry - matlab symbolic toolbox has reshaped your equation slightly. But this should work.
Best regards
Stephan

Fc Fc
Fc Fc on 10 Jun 2018
Hi, thank you to the both.
1) @Stefan Jung. By your code I get a,b,c values, but when I add the code
hold on
plot(t,F(x,t))
hold off
to plot also the fit function, it changes all the graph...What I mean is that first I've this plot
Lastly I get this one
2) @ImageAnalyst: I changed your code to get x,y values by my datafile... First I wrote:
A=load('D:/Datifit.txt');
then I replaced this line X = sort(rand(1, 50));
with this one
X = A(:,1);
and this line:
Y = Y + 0.001 * randn(1, length(Y));
with this one
Y = A(:,2);
but I get this error
Error using nlinfit (line 211)
MODELFUN must be a function that returns a vector of fitted values the same size as Y (1-by-15). The model function you provided
returned a result that was 1-by-1.
One common reason for a size mismatch is using matrix operators (*, /, ^) in your function instead of the corresponding elementwise
operators (.*, ./, .^).
Error in NonLinearModel/fitter (line 1123)
nlinfit(X,y,F,b0,opts,wtargs{:},errormodelargs{:});
Error in classreg.regr.FitObject/doFit (line 94)
model = fitter(model);
Error in NonLinearModel.fit (line 1430)
model = doFit(model);
Error in fitnlm (line 94)
model = NonLinearModel.fit(X,varargin{:});
Error in personal_fit (line 32)
mdl = fitnlm(tbl, modelfun, beta0);
  6 Comments
Image Analyst
Image Analyst on 10 Jun 2018
"I'm not free to choose the..." -- does this mean it's your homework?
Fc Fc
Fc Fc on 11 Jun 2018
No...it isn't matlab homework! I'm just writing a laboratory report!

Sign in to comment.

Tags

Community Treasure Hunt

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

Start Hunting!