Question

I'm given data for x,y, and z. I am trying to fit a set of data into a model of functional form as described below:

z(x, y) = c0 + c1.* exp(-(c2 .* x)) + c3.* (y.^1)

where c0, c1, c2 and c3 are the coefficients to be found.

I tried John D'Errico's polyfitn(). But, how can I fit my proposed model in this function?.

% So far I have tried

clc

x= [1 .. 60];

y= [0.001 .. 0.8];

z= [0.996297743 .. 0.095331687];

model= c0 + c1.* exp(-(c2 .* x)) + c3.* (y.^1);

p = polyfitn([x(:),y(:)], z(:),  'model')

% Here x,y are independent variables and z is dependent variable. I'm not sure how to pass the arguments.

Était-ce utile?

La solution

In my eyes there is no need for an external tool, the convenient cftool can help you in most of the cases. It will generate you the following function:

function [fitresult, gof] = expfit(x, y, z)

[xData, yData, zData] = prepareSurfaceData( x, y, z );

% Set up fittype and options.
ft = fittype( 'c0 + c1.* exp(-(c2 .* x)) + c3.* (y.^1);', 'independent', {'x', 'y'}, 'dependent', 'z' );
opts = fitoptions( ft );
opts.Display = 'Off';
opts.Lower = [-Inf -Inf -Inf -Inf];
opts.StartPoint = [0.0975404049994095 0.278498218867048 0.546881519204984 0.957506835434298];
opts.Upper = [Inf Inf Inf Inf];

% Fit model to data.
[fitresult{1}, gof(1)] = fit( [xData, yData], zData, ft, opts );

% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult{1}, [xData, yData], zData );
legend( h, 'untitled fit 1', 'z vs. x, y', 'Location', 'NorthEast' );
% Label axes
xlabel( 'x' );
ylabel( 'y' );
zlabel( 'z' );
grid on

Finally you just need a script to evaluate your fitobject:

[res,gof] = expfit(x,y,z)
% gives you the coeffcients
coeffvalues(res{1})

The short version (without additional function and plot) would be:

[xData, yData, zData] = prepareSurfaceData( x, y, z );
functionToFit = 'c0 + c1.* exp(-(c2 .* x)) + c3.* (y.^1);';
ft = fittype( functionToFit, 'independent', {'x', 'y'}, 'dependent', 'z' );
fitobj = fit( [xData, yData], zData, ft );
coeffvalues( fitobj{1} )

Be aware that for 2-dimensional fits you need to use prepareCurveData instead of prepareSurfaceData. These are Matlab built-in functions somehow similiar to meshgrid, but especially "prepared" for curve/surface fits.

Autres conseils

You have a model that is not a polynomial, and it can also not be converted to a polynomial that polyfitn can solve.

To see this, re-write your equation. Make the substitution u = exp(x), so that

z(ln(u), y) = c0 + c1·u^(-c2) + c3·y

This is a 2 dimensional polynomial with degree -c2 for u and degree 1 for y.

polyfitn is not designed to solve for unknown and non-integer powers of the independent variables; it solves only (well, mostly) for the coefficients. In your case, it would solve for c0, c1 and c3 if c2 is known.

What I would do is the folllowing:

%// function that computes the sum-of-squares for some estimate
model = @(c) sum((c(1) + c(2)*exp(-c(3)*x) + c(4)*y - z).^2);

%// optimize the fit 
C = fminsearch(model, [1 1 1 1]) %// NOTE: random starting values

With these two lines of code, I get

%// c0             c1             c2            c3
C = 2.3445e-001    8.4158e-001    1.5817e-001   -1.5584e-001     

which looks pretty reasonable if I plot the model and the data, and the differences.

If you have the optimization toolbox, the following might be a bit more robust:

%// function that computes the difference of the model to the data
model = @(c) c(1) + c(2)*exp(-c(3)*x) + c(4)*y - z;

%// optimize the fit 
C = lsqnonlin(model, [1 1 1 1]) %// NOTE: random starting values

Assume you have an independent variable C and a Dependent variable D with data and a function for D=f(C) as defined by ft. This works great:

ft = fittype('a*log(C)+b*cos(C)+c*exp(C)','independent','C','dependent','D');

fitobj = fit( x, D, ft );
KC=coeffvalues( fitobj )

plot(fitobj,C,D);
% 
txt = ['D= ' num2str(KC(1)) ' ln(C)' '+' num2str(KC(2))  ' cos(C)' '+'  num2str(KC(3))  ' exp(C)' ];
  annotation('textbox','String',txt,'FitBoxToText','on');
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top