2D data fitting - Surface
0 comentarios
Respuestas (5)
2 comentarios
0 comentarios
0 comentarios
1 comentario
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.
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!
0 comentarios
Ver también
Categorías
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!