سؤال

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.

هل كانت مفيدة؟

المحلول

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.

نصائح أخرى

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');
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top