2D data fitting - Surface

288 Ansichten (letzte 30 Tage)
Paolo
Paolo am 25 Feb. 2014
Beantwortet: Umar am 12 Aug. 2024
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?

Antworten (5)

Star Strider
Star Strider am 25 Feb. 2014
Bearbeitet: Star Strider am 25 Feb. 2014
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 Kommentare
Kenneth Fishbein
Kenneth Fishbein am 16 Jan. 2019
Thank you Star Strider, I have been struggling with this.
--RS
Minh Hoang Dang
Minh Hoang Dang am 10 Apr. 2021
How did you get that formula?

Melden Sie sich an, um zu kommentieren.


Alex Sha
Alex Sha am 28 Mai 2019
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 am 23 Jul. 2023
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 am 29 Mär. 2016
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 Kommentar
Umar
Umar am 12 Aug. 2024

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.

Melden Sie sich an, um zu kommentieren.


Umar
Umar am 12 Aug. 2024

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!

Kategorien

Mehr zu Get Started with Curve Fitting Toolbox finden Sie in Help Center und File Exchange

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by