17

I have discrete regular grid of a,b points and their corresponding c values and I interpolate it further to get a smooth curve. Now from interpolation data, I further want to create a polynomial equation for curve fitting. How to fit 3D plot in polynomial?

I try to do this in MATLAB. I used Surface fitting toolbox in MATLAB (r2010a) to curve fit 3-dimensional data. But, how does one find a formula that fits a set of data to the best advantage in MATLAB/MAPLE or any other software. Any advice? Also most useful would be some real code examples to look at, PDF files, on the web etc.

This is just a small portion of my data.

a = [ 0.001 .. 0.011];

b = [1, .. 10];

c = [ -.304860225, .. .379710865]; 

Thanks in advance.

Syeda
  • 309
  • 2
  • 5
  • 14

3 Answers3

20

To fit a curve onto a set of points, we can use ordinary least-squares regression. There is a solution page by MathWorks describing the process.

As an example, let's start with some random data:

% some 3d points
data = mvnrnd([0 0 0], [1 -0.5 0.8; -0.5 1.1 0; 0.8 0 1], 50);

As @BasSwinckels showed, by constructing the desired design matrix, you can use mldivide or pinv to solve the overdetermined system expressed as Ax=b:

% best-fit plane
C = [data(:,1) data(:,2) ones(size(data,1),1)] \ data(:,3);    % coefficients

% evaluate it on a regular grid covering the domain of the data
[xx,yy] = meshgrid(-3:.5:3, -3:.5:3);
zz = C(1)*xx + C(2)*yy + C(3);

% or expressed using matrix/vector product
%zz = reshape([xx(:) yy(:) ones(numel(xx),1)] * C, size(xx));

Next we visualize the result:

% plot points and surface
figure('Renderer','opengl')
line(data(:,1), data(:,2), data(:,3), 'LineStyle','none', ...
    'Marker','.', 'MarkerSize',25, 'Color','r')
surface(xx, yy, zz, ...
    'FaceColor','interp', 'EdgeColor','b', 'FaceAlpha',0.2)
grid on; axis tight equal;
view(9,9);
xlabel x; ylabel y; zlabel z;
colormap(cool(64))

1st_order_polynomial


As was mentioned, we can get higher-order polynomial fitting by adding more terms to the independent variables matrix (the A in Ax=b).

Say we want to fit a quadratic model with constant, linear, interaction, and squared terms (1, x, y, xy, x^2, y^2). We can do this manually:

% best-fit quadratic curve
C = [ones(50,1) data(:,1:2) prod(data(:,1:2),2) data(:,1:2).^2] \ data(:,3);
zz = [ones(numel(xx),1) xx(:) yy(:) xx(:).*yy(:) xx(:).^2 yy(:).^2] * C;
zz = reshape(zz, size(xx));

There is also a helper function x2fx in the Statistics Toolbox that helps in building the design matrix for a couple of model orders:

C = x2fx(data(:,1:2), 'quadratic') \ data(:,3);
zz = x2fx([xx(:) yy(:)], 'quadratic') * C;
zz = reshape(zz, size(xx));

Finally there is an excellent function polyfitn on the File Exchange by John D'Errico that allows you to specify all kinds of polynomial orders and terms involved:

model = polyfitn(data(:,1:2), data(:,3), 2);
zz = polyvaln(model, [xx(:) yy(:)]);
zz = reshape(zz, size(xx));

2nd_order_polynomial

Community
  • 1
  • 1
Amro
  • 121,265
  • 25
  • 232
  • 431
  • 1
    How can I perform same kind of operation in python..!? Bit help would be appreciating... @Amro – diffracteD Feb 20 '15 at 12:09
  • 3
    @diffracteD: I translated the code into Python: https://gist.github.com/amroamroamro/1db8d69b4b65e8bc66a6 – Amro Feb 20 '15 at 18:40
  • Thanks for your help... i'll surely try it.. ! – diffracteD Feb 21 '15 at 08:05
  • (asking about your github code) is it logical to go for a higher order polynomial fitting to evaluate the surface ? – diffracteD Jun 16 '15 at 09:23
  • @diffracteD: yes you can, although you should be [cautious](https://en.wikipedia.org/wiki/Runge's_phenomenon) of fitting models that are too high of an order.. – Amro Jun 16 '15 at 11:25
  • ok. Can you suggest me a way to get the minima/maxima value from the fitted surface using the python code ? thank you. – diffracteD Jun 17 '15 at 05:30
  • @diffracteD: Please create a new question, formulate your problem, and link to this post and gist code. – Amro Jun 17 '15 at 07:08
3

There might be some better functions on the file-exchange, but one way to do it by hand is this:

x = a(:); %make column vectors
y = b(:);
z = c(:);

%first order fit
M = [ones(size(x)), x, y];
k1 = M\z; 
%least square solution of z = M * k1, so z = k1(1) + k1(2) * x + k1(3) * y

Similarly, you can do a second order fit:

%second order fit
M = [ones(size(x)), x, y, x.^2, x.*y, y.^2];
k2 = M\z;

which seems to have numerical problems for the limited dataset you gave. Type help mldivide for more details.

To make an interpolation over some regular grid, you can do like so:

ngrid = 20;
[A,B] = meshgrid(linspace(min(a), max(a), ngrid), ...
                 linspace(min(b), max(b), ngrid));
M = [ones(numel(A),1), A(:), B(:), A(:).^2, A(:).*B(:), B(:).^2];
C2_fit = reshape(M * k2, size(A)); % = k2(1) + k2(2)*A + k2(3)*B + k2(4)*A.^2 + ...

%plot to compare fit with original data
surfl(A,B,C2_fit);shading flat;colormap gray
hold on
plot3(a,b,c, '.r')

A 3rd-order fit can be done using the formula given by TryHard below, but the formulas quickly become tedious when the order increases. Better write a function that can construct M given x, y and order if you have to do that more than once.

Bas Swinckels
  • 16,651
  • 3
  • 38
  • 58
  • 1
    +1 -- third order fit with `M = [ones(size(x)), x, y, x.^2, x.*y, y.^2, x.^3, x.^2.*y, x.*y.^2, y.^3]` does a pretty good job... – Buck Thorn Aug 31 '13 at 21:08
  • Sorry for late response! Thankyou for replying Bas Swinckels and Try hard. Nice solution. But, is there any method to find a the best fit formula/equation through code or by using any tool in MATLAB? How one find a formula that best fits above given set of data? – Syeda Sep 01 '13 at 09:08
  • I am getting this warning as well. Warning: Rank deficient, rank = 5, tol = 9.9961e-013. Could you please help me understand what this means? Thank you. – Syeda Sep 01 '13 at 09:28
  • Googling for any combination of polyfit, 2D, 3D, fit, matlab, etc., turns up a lot of answers, that is what I always do for problems I don't know. For sure you will find some recipes on the [file-exchange](http://www.mathworks.com/matlabcentral/fileexchange/). But you will have to do that yourself, we are not here to do all your (home)work ... – Bas Swinckels Sep 01 '13 at 09:30
  • You said that you only gave a small portion of your data, try to fit to the whole dataset and see if that changes anything. The data you provided only have 2 distinct values for `a` (0.001 and 0.0011), so trying to fit that with a 2nd order polynomial is ill-undefined ... – Bas Swinckels Sep 01 '13 at 09:31
2

This sounds like more of a philosophical question than specific implementation, specifically to bit - "how does one find a formula that fits a set of data to the best advantage?" In my experience that is a choice you have to make depending on what you're trying to achieve.

What defines "best" for you? For a data fitting problem you can keep adding more and more polynomial coefficients and making a better R^2 value... but will eventually "over fit" the data. A downside of high order polynomials is behavior outside the bounds of the sample data which you've used to fit your response surface - it can quickly go off in some wild direction which may not be appropriate for whatever it is you're trying to model.

Do you have insight into the physical behavior of the system / data you're fitting? That can be used as a basis for what set of equations to use to create a math model. My recommendation would be to use the most economical (simple) model you can get away with.

Tom S
  • 135
  • 7