2D data fitting - Surface

293 次查看(过去 30 天)
Paolo
Paolo 2014-2-25
回答: Umar 2024-8-12
I have some numbers as a function of 2 variables: ( x, y ) ↦ z.
I would like to know which function z = z( x, y ) best fits my data.
Unfortunately, I don't have any hint, I mean, there's no theoretical background on these numbers. They're the result ( z ) of some FEM simulations of a system, being the simulation a parametric sweep over two parameters ( x and y ) of the system.
Here's my data:
x = [1 2 4 6 8 10 13 17 21 25];
y = [0.2 0.5 1 2 4 7 10 14 18 22];
z = [1 0.6844 0.3048 0.2124 0.1689 0.1432 0.1192 0.1015 0.0908 0.0841;...
1.000 0.7096 0.3595 0.2731 0.2322 0.2081 0.1857 0.1690 0.1590 0.1529;...
1.000 0.7451 0.4362 0.3585 0.3217 0.2999 0.2797 0.2648 0.2561 0.2504;...
1.000 0.7979 0.5519 0.4877 0.4574 0.4394 0.4228 0.4107 0.4037 0.3994;...
1.000 0.8628 0.6945 0.6490 0.6271 0.6145 0.6027 0.5945 0.5896 0.5870;...
1.000 0.9131 0.8057 0.7758 0.7614 0.7531 0.7457 0.7410 0.7383 0.7368;...
1.000 0.9397 0.8647 0.8436 0.8333 0.8278 0.8228 0.8195 0.8181 0.8171;...
1.000 0.9594 0.9087 0.8942 0.8877 0.8839 0.8808 0.8791 0.8783 0.8777;...
1.000 0.9705 0.9342 0.9238 0.9190 0.9165 0.9145 0.9133 0.9131 0.9127;...
1.000 0.9776 0.9502 0.9425 0.9390 0.9372 0.9358 0.9352 0.9349 0.9348];
I tried with MATLAB with the Curve Fitting app, but I didn't succeed. The 'polynomial' fitting doesn't work well. I would like to use the 'custom equation' fitting, but I don't know what equation to start. I don't have much practice in data analysis.
Any hint?

回答(5 个)

Star Strider
Star Strider 2014-2-25
编辑:Star Strider 2014-2-25
You can experiment with different models (I called mine surfit here), but this code is what I came up with using lsqcurvefit:
[X Y] = meshgrid(x,y);
% Create input independent variable (10 x 10 x 2):
XY(:,:,1) = X;
XY(:,:,2) = Y;
% Create Objective Function:
surfit = @(B,XY) B(1)*exp(B(2).*XY(:,:,1)) + (1 - exp(B(3).*XY(:,:,2)));
% surfit = @(B,XY) exp(B(1).*XY(:,:,1)) + (1 - exp(B(2).*XY(:,:,2)));
% Do Regression
B = lsqcurvefit(surfit, [0.5 -0.5 -0.5], XY, z, [0 -10 -10], [1 10 10])
% Calculate Fitted Surface:
Z = surfit(B,XY);
% Plot:
figure(2)
stem3(x, y, z, 'k', 'fill') % Original Data
hold on
surf(X, Y, Z) % Fitted Surface
hold off
xlabel('X \rightarrow')
ylabel('\leftarrow Y')
zlabel('Z \rightarrow')
grid
You might also be able to use nlinfit, which should also give you statistics on the fit.
I chose the model simply because it ‘looked’ as though it would fit the data. (That’s usually a bad idea — it’s best to have some idea of the process that created your data so you can fit an appropriate model, but since I have no idea what generated your data, I did the best I could.)
I haven’t done surface fitting in a while, so I had some fun with this.
  2 个评论
Kenneth Fishbein
Kenneth Fishbein 2019-1-16
Thank you Star Strider, I have been struggling with this.
--RS
Minh Hoang Dang
Minh Hoang Dang 2021-4-10
How did you get that formula?

请先登录,再进行评论。


Alex Sha
Alex Sha 2019-5-28
The follow equation seems to be good, and simple enough:
z = (x^0.5)^(p1/(1+y))+p2*x*y;
Root of Mean Square Error (RMSE): 0.0284297771376312
Sum of Squared Residual: 0.080825222809538
Correlation Coef. (R): 0.99540576324566
R-Square: 0.990832633502676
Adjusted R-Square: 0.990546153299634
Determination Coef. (DC): 0.990647200774744
Chi-Square: 0.0847263676959977
F-Statistic: 10657.3637281945
Parameter Best Estimate
---------- -------------
p1 -2.00678197617142
p2 0.000172125783091927
c163.jpg
c162.jpg

S0852306
S0852306 2023-7-23
Try nonlinear model, this is the result i got,
file exchange : surface fitting
you can see the fitted surface match the data perfectly.
Root Mean Square Error : 0.003
Mean Square Error :0.0025 
Solve the nonlinear least squares problems:
%% Reshape data to desire format
count=0;
for i=1:numel(x)
for j=1:numel(y)
count=count+1;
data(1,count)=x(i);
data(2,count)=y(j);
end
end
label=reshape(z,1,numel(x)*numel(y));
%% model set up
InSize=2; OutSize=1;
LayerStruct=[InSize,3,3,3,OutSize];
NN=Initialization(LayerStruct);
%% Solve nonlinear least squares
option.MaxIteration=1500;
NN=OptimizationSolver(data,label,NN,option);
Stats and Visualization
%% Stats
R=FittingReport(data,label,NN); MSE=mean(R.ErrorVector.^2); RMSE=sqrt(MSE);
%% Visualization
p=NN.Evaluate(data);
ValMatrix=reshape(p,numel(x),numel(y));
[X,Y]=meshgrid(x,y);
scatter3(data(1,:),data(2,:),label,'black')
hold on
surf(X,Y,ValMatrix)
legend('data point','fitted surface')
title('Surface Fitting')
the model used in this fitting is a neural net, it's a universal approximator,
this means that it can approximate any continuous function (given enough parameters).
the model is actually quite simple, for example, a neural net with 2 layer is :
, are weight matrices, are bias vectors.
and is a point wise nonlinear function, i.e.
in this fit, . (Gaussian)

Amritanshu Pandey
Amritanshu Pandey 2016-3-29
I have a follow up question to this thread. How will I modify the code above if the data is of the form: size(xdata)=Nx1 size(ydata)=Nx1 size(zdata)=Nx1
as compared to this problem where size of the data is of the form: size(xdata)=Nx1 size(ydata)=Nx1 size(zdata)=NxN
  1 个评论
Umar
Umar 2024-8-12

Hi @Amritanshu Pandey ,

To address your query regarding, “I have a follow up question to this thread. How will I modify the code above if the data is of the form: size(xdata)=Nx1 size(ydata)=Nx1 size(zdata)=Nx1as compared to this problem where size of the data is of the form: size(xdata)=Nx1 size(ydata)=Nx1 size(zdata)=NxN”

To modify the MATLAB code provided by @Star Strider for you regarding the case where `xdata`, `ydata`, and `zdata` are all in the form of `Nx1` vectors, I have to adjust the way @Star Strider created the meshgrid and how he handled the data for regression. The code mentioned by him assumes that `zdata` is a matrix of size `NxN`, which is suitable for a grid-based surface fitting but when all three datasets are column vectors, I need to fit a model to these points instead. The key difference between the two scenarios is in how the data is structured, Original case: ‘zdata` is a matrix corresponding to a grid of `xdata` and `ydata`. The Modified case will be all data will be column vectors, meaning each `(x, y, z)` point is treated independently without an inherent grid structure. Here is the modified code,

   % Assume xdata, ydata, zdata are Nx1 column vectors
   % Example initialization (you would replace these with your actual data)
   N = 100; % Example size
   xdata = linspace(0, 10, N)'; % Column vector
   ydata = linspace(0, 10, N)'; % Column vector
   zdata = sin(xdata) + cos(ydata); % Example response variable
   % Define the objective function for curve fitting
   surfit = @(B, XY) B(1)*exp(B(2).*XY(:,1)) + (1 - exp(B(3).*XY(:,2)));
   % Combine xdata and ydata into a single matrix XY
    XY = [xdata, ydata];
   % Initial guess for parameters B
   initialGuess = [0.5 -0.5 -0.5];
   % Perform regression using lsqcurvefit
   options = optimset('Display','off'); % Suppress output display
   B = lsqcurvefit(surfit, initialGuess, XY, zdata, [0 -10 -10], [1 10 10], options);
   % Calculate fitted values based on optimized parameters
   Z_fitted = surfit(B, XY);
   % Plotting original data and fitted surface
   figure;
   scatter3(xdata, ydata, zdata, 'k', 'filled'); % Original Data Points
   hold on;
   % Create a grid for plotting the fitted surface
    [Xq, Yq] = 
   meshgrid(linspace(min(xdata), max(xdata), 50), linspace(min(ydata), 
   max(ydata), 50));
    XYq = [Xq(:), Yq(:)];
    Zq = surfit(B, XYq);
    Zq = reshape(Zq, size(Xq));
    surf(Xq, Yq, Zq); % Fitted Surface
     hold off;
     xlabel('X \rightarrow');
     ylabel('\leftarrow Y');
     zlabel('Z \rightarrow');
     grid on;
     title('Surface Fit to Data');

Please see attached plot.

Explanation of Modifications

I created ‘XY’ as a two-column matrix containing `xdata` and `ydata`. Each row corresponds to a single `(x,y)` pair. I made sure that the fitting function remains similar but directly utilized the combined `XY` matrix for independent variables. Also, the initial guess and bounds should remain the same but you have to make sure that they are set appropriately based on your specific use case.Since I no longer have a grid structure inherently defined by `z`, I generated a meshgrid for plotting purposes using interpolated values (`Xq`, `Yq`) based on the fitted model. This approach now should allow you to work with independent `(x,y,z)` datasets while still performing a meaningful surface fit. Hope this helps. Please let me know if you have any further questions.

请先登录,再进行评论。


Umar
Umar 2024-8-12

Hi @Paolo ,

Addressing your query regarding, “I tried with MATLAB with the Curve Fitting app, but I didn't succeed. The 'polynomial' fitting doesn't work well. I would like to use the 'custom equation' fitting, but I don't know what equation to start. I don't have much practice in data analysis. Any hint?”

Please see my response to your comments below.

Before fitting a model, it is essential to visualize the data to understand its structure. You can create a surface plot to observe how (z) varies with (x) and (y).

% Define data
x = [1 2 4 6 8 10 13 17 21 25];
y = [0.2 0.5 1 2 4 7 10 14 18 22];
z = [1 0.6844 0.3048 0.2124 0.1689 0.1432 0.1192 0.1015 0.0908 0.0841;...
   1.000 0.7096 0.3595 0.2731 0.2322 0.2081 0.1857 0.1690 0.1590 0.1529;...
   1.000 0.7451 0.4362 0.3585 0.3217 0.2999 0.2797 0.2648 0.2561 0.2504;...
   1.000 0.7979 0.5519 0.4877 0.4574 0.4394 0.4228 0.4107 0.4037 0.3994;...
   1.000 0.8628 0.6945 0.6490 0.6271 0.6145 0.6027 0.5945 0.5896 0.5870;...
   1.000 0.9131 0.8057 0.7758 0.7614 0.7531 0.7457 0.7410 0.7383 0.7368;...
   1.000 0.9397 0.8647 0.8436 0.8333 0.8278 0.8228 0.8195 0.8181 0.8171;...
   1.000 0.9594 0.9087 0.8942 0.8877 0.8839 0.8808 0.8791 0.8783 0.8777;...
   1.000 0.9705 0.9342 0.9238 0.9190 0.9165 0.9145 0.9133 0.9131 0.9127;...
   1.000 0.9776 0.9502 0.9425 0.9390 0.9372 0.9358 0.9352 0.9349 0.9348];
% Create a meshgrid for plotting
[X, Y] = meshgrid(x, y);
Z = z;
% Plot the surface
figure;
surf(X, Y, Z);
xlabel('X-axis');
ylabel('Y-axis');
zlabel('Z-axis');
title('Surface Plot of Z as a Function of X and Y');
colorbar;

Since you are interested in custom fitting, I can define a general form of a function and use MATLAB's fit function. For instance, I will try a polynomial surface fit which is defined below.

% Define the custom fit function
customFit = 
@(b, x, y) b(1) + b(2)*x + b(3)*y + b(4)*x.^2 + b(5)*y.^2 + 
b(6)*x.*y;
% Generate sample data for fitting
x = linspace(-10, 10, 20); % Example x data
y = linspace(-10, 10, 20); % Example y data
[X, Y] = meshgrid(x, y);
z = sin(sqrt(X.^2 + Y.^2)); % Example z data based on a function
% Prepare the data for fitting
xData = repmat(x, length(y), 1);
yData = repmat(y', 1, length(x));
zData = z(:);
% Initial guess for the coefficients
initialGuess = [1, 1, 1, 1, 1, 1];
% Define upper bounds for the coefficients
upperBounds = [Inf, Inf, Inf, Inf, Inf, Inf]; % No upper limits
% Use lsqcurvefit to fit the model
options = optimset('Display', 'off');
beta = 
lsqcurvefit(@(b, x) customFit(b, x(:,1), x(:,2)), initialGuess, [xData(:), 
yData(:)], zData, [], upperBounds, options);
% Display the coefficients
disp('Fitted coefficients:');
disp(beta);

After fitting the model, it is crucial to evaluate how well it fits the data. I can visualize the fitted surface alongside the original data as defined below.

% Calculate the fitted values
Z_fit = customFit(beta, X, Y);
% Plot the original and fitted surfaces
figure;
surf(X, Y, z, 'FaceAlpha', 0.5); % Original data
hold on;
surf(X, Y, Z_fit, 'FaceColor', 'r', 'FaceAlpha', 0.5); % Fitted data
xlabel('X-axis');
ylabel('Y-axis');
zlabel('Z-axis');
title('Comparison of Original and Fitted Surfaces');
legend('Original Data', 'Fitted Data');
colorbar;

Please see attached.

Final plot

Feel free to customize this code by exploring different fitting functions to find the one that best represents your data. The choice of the model can significantly impact the results, so it may be beneficial to experiment with various forms and evaluate their performance. Remember, the goal is to find a balance between complexity and accuracy. If you have further questions or need assistance with specific aspects of the fitting process, feel free to ask!

类别

Help CenterFile Exchange 中查找有关 Get Started with Curve Fitting Toolbox 的更多信息

产品

Community Treasure Hunt

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

Start Hunting!

Translated by