MATLAB Answers

How to fit a function to 2D array when some parts of the underlaying function are known?

1 ビュー (過去 30 日間)
Dominik Hiltbrunner
Dominik Hiltbrunner 2021 年 10 月 8 日
コメント済み: Alex Sha 2021 年 10 月 19 日
I have an unknown function Z=f(X,Y) where a subset of Z-values are known for a certain range of X and Y values.
Consider the following example
clc; clear; close all;
Z = [6.63900000000000e-09 3.92700000000000e-09 3.70100000000000e-09 3.37800000000000e-09 2.92600000000000e-09 2.57500000000000e-09 2.29900000000000e-09 1.89100000000000e-09 1.60700000000000e-09 1.39700000000000e-09 1.23600000000000e-09
1.13700000000000e-08 6.48300000000000e-09 6.10300000000000e-09 5.67100000000000e-09 5.02700000000000e-09 4.50200000000000e-09 4.07400000000000e-09 3.42200000000000e-09 2.95000000000000e-09 2.59200000000000e-09 2.31200000000000e-09
1.53100000000000e-08 8.55100000000000e-09 8.04300000000000e-09 7.54900000000000e-09 6.78500000000000e-09 6.14200000000000e-09 5.60700000000000e-09 4.77300000000000e-09 4.15500000000000e-09 3.67900000000000e-09 3.30000000000000e-09
1.87700000000000e-08 1.03400000000000e-08 9.72000000000000e-09 9.18400000000000e-09 8.33400000000000e-09 7.60300000000000e-09 6.98600000000000e-09 6.00700000000000e-09 5.26700000000000e-09 4.68900000000000e-09 4.22700000000000e-09
3.42700000000000e-08 1.83900000000000e-08 1.72600000000000e-08 1.66000000000000e-08 1.54900000000000e-08 1.44700000000000e-08 1.35600000000000e-08 1.20400000000000e-08 1.08200000000000e-08 9.83100000000000e-09 9.00500000000000e-09
5.17500000000000e-08 2.77800000000000e-08 2.60800000000000e-08 2.53000000000000e-08 2.40100000000000e-08 2.27700000000000e-08 2.16400000000000e-08 1.96600000000000e-08 1.80100000000000e-08 1.66200000000000e-08 1.54200000000000e-08
7.59600000000000e-08 4.14600000000000e-08 3.89400000000000e-08 3.79300000000000e-08 3.64600000000000e-08 3.50100000000000e-08 3.36600000000000e-08 3.12100000000000e-08 2.91000000000000e-08 2.72400000000000e-08 2.56100000000000e-08
1.23700000000000e-07 6.97800000000000e-08 6.54700000000000e-08 6.35700000000000e-08 6.17000000000000e-08 5.99600000000000e-08 5.83000000000000e-08 5.52400000000000e-08 5.24900000000000e-08 4.99900000000000e-08 4.77300000000000e-08
1.78100000000000e-07 1.03100000000000e-07 9.65000000000000e-08 9.27700000000000e-08 9.02000000000000e-08 8.80900000000000e-08 8.61500000000000e-08 8.25800000000000e-08 7.93200000000000e-08 7.63200000000000e-08 7.35500000000000e-08];
X = 1e-6*[0.5 0.75 1 2.5 5 7.5 10 15 20 25 30];
Y = [2.50000000000000e-07 5.00000000000000e-07 7.50000000000000e-07 1.00000000000000e-06 2.50000000000000e-06 5.00000000000000e-06 1.00000000000000e-05 2.50000000000000e-05 5.00000000000000e-05];
surf(X,Y,Z)
I want a function that predicts Z-values within the given range of X and Y values, and I know the following structure of the underlying function:
  • Z is proportional to where c is an unknown constant.
  • Z is proportional to where and are unknown constants.
How can I find the function f(X,Y) with Matlab?

採用された回答

Alan Weiss
Alan Weiss 2021 年 10 月 8 日
Well, it depends what you mean by "Z is proportional to c/X and Z is proportional to c2 + c3Y + c4Y^2". You could mean that Z is proportional to c/X + c2 + c3Y + c4Y^2. In that case, you can solve for the coefficients c using backslash.
Alternatively, you could mean that Z is proportional to (c1/X + c2) * (c3 + c4Y + c5Y^2). In that case, the c vector enters nonlinearly, and you need to use lsqcurvefit. Here is a script that shows both ways. I took the liberty of scaling things to be more order one, but feel free to unscale.
Z = [6.63900000000000e-09 3.92700000000000e-09 3.70100000000000e-09 3.37800000000000e-09 2.92600000000000e-09 2.57500000000000e-09 2.29900000000000e-09 1.89100000000000e-09 1.60700000000000e-09 1.39700000000000e-09 1.23600000000000e-09
1.13700000000000e-08 6.48300000000000e-09 6.10300000000000e-09 5.67100000000000e-09 5.02700000000000e-09 4.50200000000000e-09 4.07400000000000e-09 3.42200000000000e-09 2.95000000000000e-09 2.59200000000000e-09 2.31200000000000e-09
1.53100000000000e-08 8.55100000000000e-09 8.04300000000000e-09 7.54900000000000e-09 6.78500000000000e-09 6.14200000000000e-09 5.60700000000000e-09 4.77300000000000e-09 4.15500000000000e-09 3.67900000000000e-09 3.30000000000000e-09
1.87700000000000e-08 1.03400000000000e-08 9.72000000000000e-09 9.18400000000000e-09 8.33400000000000e-09 7.60300000000000e-09 6.98600000000000e-09 6.00700000000000e-09 5.26700000000000e-09 4.68900000000000e-09 4.22700000000000e-09
3.42700000000000e-08 1.83900000000000e-08 1.72600000000000e-08 1.66000000000000e-08 1.54900000000000e-08 1.44700000000000e-08 1.35600000000000e-08 1.20400000000000e-08 1.08200000000000e-08 9.83100000000000e-09 9.00500000000000e-09
5.17500000000000e-08 2.77800000000000e-08 2.60800000000000e-08 2.53000000000000e-08 2.40100000000000e-08 2.27700000000000e-08 2.16400000000000e-08 1.96600000000000e-08 1.80100000000000e-08 1.66200000000000e-08 1.54200000000000e-08
7.59600000000000e-08 4.14600000000000e-08 3.89400000000000e-08 3.79300000000000e-08 3.64600000000000e-08 3.50100000000000e-08 3.36600000000000e-08 3.12100000000000e-08 2.91000000000000e-08 2.72400000000000e-08 2.56100000000000e-08
1.23700000000000e-07 6.97800000000000e-08 6.54700000000000e-08 6.35700000000000e-08 6.17000000000000e-08 5.99600000000000e-08 5.83000000000000e-08 5.52400000000000e-08 5.24900000000000e-08 4.99900000000000e-08 4.77300000000000e-08
1.78100000000000e-07 1.03100000000000e-07 9.65000000000000e-08 9.27700000000000e-08 9.02000000000000e-08 8.80900000000000e-08 8.61500000000000e-08 8.25800000000000e-08 7.93200000000000e-08 7.63200000000000e-08 7.35500000000000e-08];
Z = Z*1e8;
X = 1e-6*[0.5 0.75 1 2.5 5 7.5 10 15 20 25 30];
X = X*1e6;
Y = [2.50000000000000e-07 5.00000000000000e-07 7.50000000000000e-07 1.00000000000000e-06 2.50000000000000e-06 5.00000000000000e-06 1.00000000000000e-05 2.50000000000000e-05 5.00000000000000e-05];
Y = Y*1e6;
[xx,yy] = meshgrid(X,Y);
surf(xx,yy,Z)
z1 = Z(:);
x1 = xx(:);
y1 = yy(:);
v1 = [1./x1 ones(size(x1)) y1 y1.^2]; % linear problem Z ~ c1/X + c2 + c3*Y + c4*Y^2
r1 = v1\z1;
zout = v1*r1; % Implied response
zout = reshape(zout,size(Z)); % Get ready to plot
figure
surf(xx,yy,zout)
xdata = [x1 y1]; % Nonlinear response problem
rng default
x0 = randn(1,5);
options = optimoptions("lsqcurvefit","MaxFunctionEvaluations",5e5,"MaxIterations",1e5);
cout = lsqcurvefit(@twofun,x0,xdata,z1,[],[],options); % Find nonlinear parameters
Local minimum possible. lsqcurvefit stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
zout2 = twofun(cout,xdata); % Get implied response
zout2 = reshape(zout2,size(Z)); % Get ready to plot
figure
surf(xx,yy,zout2)
function r = twofun(c,xdata)
x = xdata(:,1);
y = xdata(:,2);
r = (c(1)./x + c(2)) .* ( c(3) + c(4)*y + c(5)*y.^2 );
end
Alan Weiss
MATLAB mathematical toolbox documentation
  4 件のコメント
Alex Sha
Alex Sha 2021 年 10 月 19 日
Hi, Dominik, the fitting function below should be much better, and simple enough:
z = p1*power(y,p2+p3/x)+p4
Root of Mean Square Error (RMSE): 4.96676186258674E-9
Sum of Squared Residual: 2.44220361656497E-15
Correlation Coef. (R): 0.988334476564506
R-Square: 0.976805037566037
Parameter Best Estimate
---------- -------------
p1 3.00671529372895E-5
p2 0.59991103826544
p3 -0.0367412799143221
p4 -1.63336827935451E-9

サインインしてコメントする。

その他の回答 (0 件)

製品


リリース

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by