필터 지우기
필터 지우기

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

조회 수: 2 (최근 30일)
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
Dominik Hiltbrunner
Dominik Hiltbrunner 2021년 10월 8일
There is indeed a strong theoretical reason why the Z-values are proportional to 1/x, and a not-so-strong reason for the quadratic dependency on y.
But I conclude here that the provided code works correctly; it are the model functions that need re-work.
Thank you again for your effort.
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개)

카테고리

Help CenterFile Exchange에서 Creating and Concatenating Matrices에 대해 자세히 알아보기

제품


릴리스

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by