Curve fitter limitation for equations in the form f(x,y)=a*x^n/(y+b)^m

2 views (last 30 days)
Dear Community Members,
When I use curve fitter for equation in the form f(x,y)=a*x^n/(y+b)^m, the results are very bad (R-square is very, very low).
After removing "b" or changing it with a random number (for example 8, then f(x,y)=a*x^n/(y+8)^m), R-square is very good.
The question is: Is this a limitation of the software or there is a way to overcome this problem and to use "b", which value wiil be calculated by Curve fitter.
  5 Comments
Boyan
Boyan on 25 Sep 2024
Edited: Boyan on 25 Sep 2024
Dear all,
The surface looks like fig. 2. In Figure 1 are given just the points. These are three exponential curves, laying in vertical planes.
fig. 1
fig. 2
The data is given below in figure 3. I'm sorry for giving it in picture, not in table, but I don't know how to insert table.
fig. 3

Sign in to comment.

Accepted Answer

Sam Chak
Sam Chak on 25 Sep 2024
Given that there are only data points, employing a bivariate polynomial of degree two in x and degree four in y will ensure a perfect fit, resulting in an R-squared value of 1.
% Data
x = [ 1 4 5 1 4 5 1 4 5 1 4 5 1 4 5];
y = [ 5 5 5 10 10 10 15 15 15 20 20 20 25 25 25];
z = [257 410 455 185 306 322 151 246 261 125 191 205 109 159 169];
% p1*x^2 + p2*x + p3
[p21, gof] = fit([1 4 5]', [257 410 455]', 'poly2');
[p22, gof] = fit([1 4 5]', [185 306 322]', 'poly2');
[p23, gof] = fit([1 4 5]', [151 246 261]', 'poly2');
[p24, gof] = fit([1 4 5]', [125 191 205]', 'poly2');
[p25, gof] = fit([1 4 5]', [109 159 169]', 'poly2');
% p1*y^4 + p2*y^3 + p3*y^2 + p4*y + p5
[q14, gof] = fit([5 10 15 20 25]', [p21.p1 p22.p1 p23.p1 p24.p1 p25.p1]', 'poly4');
[q24, gof] = fit([5 10 15 20 25]', [p21.p2 p22.p2 p23.p2 p24.p2 p25.p2]', 'poly4');
[q34, gof] = fit([5 10 15 20 25]', [p21.p3 p22.p3 p23.p3 p24.p3 p25.p3]', 'poly4');
plot3(x, y, z, 'rp'), grid on, hold on
xlabel('x'), ylabel('y'), zlabel('z')
% Surface
XX = linspace(x(1), x(end), 101);
YY = linspace(y(1), y(end), 101);
[X, Y] = meshgrid(XX, YY);
% z(x, y) = f(y)*x^2 + g(y)*x + h(y)
f = q14.p1*Y.^4 + q14.p2*Y.^3 + q14.p3*Y.^2 + q14.p4*Y + q14.p5;
g = q24.p1*Y.^4 + q24.p2*Y.^3 + q24.p3*Y.^2 + q24.p4*Y + q24.p5;
h = q34.p1*Y.^4 + q34.p2*Y.^3 + q34.p3*Y.^2 + q34.p4*Y + q34.p5;
Z = f.*X.^2 + g.*X + h;
s = surf(X, Y, Z, 'FaceAlpha', 0.25); s.EdgeColor = 'none';
title('Surface fitting with bivariate polynomial, poly24(x,y)')
view(145, 30)
hold off
  7 Comments
Boyan
Boyan on 28 Sep 2024
I'm sorry but can't see your result in our discussion above. I see only your request to show my data. Maybe it's somehow hidden in the comments above. But anyway the problem is solved by the code of @Sam Chak.
Anyway, because you are mention it, could I ask what is this package "1stOpt"?
Sam Chak
Sam Chak on 28 Sep 2024
I am not affiliated with the product "1stOpt," but it is a very powerful third-party tool, as demonstrated by @Alex Sha in multiple curve-fitting problems. The initial guesses were made after he published his 1stOpt solution. If you are interested, please take a look at the product page:
I typically guess the starting point parameter values to be close to 0 (to avoid singularity), 1, or the midpoint between 0 and 1, and then gradually increase the magnitudes. In your case, since the z-axis data range is in the hundreds, an educated guess would be to set . See example below:
% your data
X = [ 1 4 5 1 4 5 1 4 5 1 4 5 1 4 5];
Y = [ 5 5 5 10 10 10 15 15 15 20 20 20 25 25 25];
Z = [257 410 455 185 306 322 151 246 261 125 191 205 109 159 169];
% flattening the matrices for fitting
xData = X(:);
yData = Y(:);
zData = Z(:);
% proposed fit model with parameters a, b, m, n
ft = fittype('(a*x^n)/(y + b)^m', 'independent', {'x', 'y'}, 'dependent', 'z');
% Initial guesses for a, b, m, n
% a b m n
% ↓ ↓ ↓ ↓
initialGuess = [100, 1, 1, 1];
% Enter the fit command and view the Goodness of Fit
[fitResult, gof] = fit([xData, yData], zData, ft, 'StartPoint', initialGuess)
fitResult =
General model: fitResult(x,y) = (a*x^n)/(y + b)^m Coefficients (with 95% confidence bounds): a = 1.163e+04 (-1.567e+04, 3.893e+04) b = 13.72 (3.139, 24.3) m = 1.298 (0.7447, 1.852) n = 0.3395 (0.3155, 0.3634)
gof = struct with fields:
sse: 388.7688 rsquare: 0.9973 dfe: 11 adjrsquare: 0.9965 rmse: 5.9450
% Plot the original data and the fit
figure;
plot(fitResult, [xData, yData], zData);
xlabel('X-axis');
ylabel('Y-axis');
zlabel('Z-axis');
title('Surface Fitting');
view(145, 30)

Sign in to comment.

More Answers (0)

Categories

Find more on Interpolation in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!