How can I fit this data?

12 次查看(过去 30 天)
Toon
Toon 2020-2-24
评论: Rik 2020-2-28
Hi everyone,
I am struggling with the following problem:
I have a dataset (Map3D.mat file is included) for which I am trying to fit a function where I have 3 variables and one value for a combination of these 3 variables.
The variables are engine power, altitude and speed. The value is the fuel consumption of the engine. I want to fit this fuel consumption data with a function in such a way that engine power, altitude and speed are input variables and fuel consumption is the output variable. Is this possible? I have been trying stuff with fitnlm but I cannot get it working. I dont get how I can change my data structure to the required format. The Map3D.mat file is structured as follows: 7x21x4 (speed x power x altitude). With a speedvector from as Speed = 0:10:60, a powervector as Power = 5:10:205 and an altitudevector as Altitude = [0 300 600 700].
Currently I found a workaround with the interp3 function which works okay, however it increases the computation time of my code significantly compared to a function evaluation because it gets called often as it is within an iteration loop. I also expect my code to converge faster with a function which fits the desribed dataset.
I am really looking forward to see what you guys think!
Toon
  3 个评论
Toon
Toon 2020-2-24
I would expect something in the form of
function val=MyFun(b,Power,Speed,Altitude)
val = Power^-b(1)+b(2) + b(3)*Speed^2+b(4)*Speed+b(5) + b(6)*Altitude^2+b(7)*Altitude+b(8);
end
How would I find these coefficients though? What fitting tools do you have in mind?
darova
darova 2020-2-24
What about griddedInterpolant / scatteredInterpolant? It creates function only once

请先登录,再进行评论。

采纳的回答

Rik
Rik 2020-2-24
编辑:Rik 2020-2-24
Your model function contains some redundant terms that should be merged. Below you find the code to estimate your parameters and how to use that fit. Note that your model returns inf for most parameter sets for the cases where speed is 0. How to deal with that is up to you.
You should note that fminsearch is fairly sensitive to the initial guess, so if you have better ones you might not even have to remove the speed==0. It is also possible to implement bounds by letting the OLS return inf for fit values outside of an allowed range.
%load data from mat file
Map3D=load('Map3D');Map3D=Map3D.Map3D;
Speed = 0:10:60;
Power = 5:10:205;
Altitude = [0 300 600 700];
[S,P,A]=ndgrid(Speed,Power,Altitude);
%remove all speed==0 since that returns a value of inf when evaluated
L_speed_nonzero=S~=0;
[P,S,A,Map3D]=deal(P(L_speed_nonzero),S(L_speed_nonzero),...
A(L_speed_nonzero),Map3D(L_speed_nonzero));
b_initial_guess=[-10 0.1 -200 -0.05 50 40];
%objective least squares function (requires scalar/vector input)
OLS=@(b,x,y,z,v) sum((MyFun(b,x,y,z) - v).^2);
opts = optimset('MaxFunEvals',50000, 'MaxIter',10000);
% Use fminsearch to minimise the 'OLS' function
b_fitted=fminsearch(OLS, b_initial_guess(:), opts,S(:),P(:),A(:),Map3D(:));
clc
fprintf('b_fitted=[')
fprintf('%.4e ',b_fitted)
fprintf('];\n')
%%
%you can calculate the predicted values like this:
%(copied from before, but you should keep it as a variable)
b_fitted=[1.6348e+02 1.0524e-05 -3.2690e-03 6.0934e-08 -1.8714e-04 5.3567e-01 ];
Speed = 0:10:60;
Power = 5:10:205;
Altitude = [0 300 600 700];
[S,P,A]=ndgrid(Speed,Power,Altitude);
predicted_value=MyFun(b_fitted,S,P,A);
%check quality of fit:
real_value=load('Map3D');real_value=real_value.Map3D;
delta=predicted_value-real_value;
delta(i
sinf(delta))=[];
fprintf(['difference between non-inf fitted values and true values ',...
'is:\nmean= %.2e\nabs max= %.2e\n\n'],mean(delta),max(abs(delta)))
function val=MyFun(b,Power,Speed,Altitude)
% val = Power.^-b(1) ...
% +b(2) ...
% +b(3)*Speed.^2 ...
% +b(4).*Speed ...
% +b(5) ...
% +b(6)*Altitude.^2 ...
% +b(7)*Altitude ...
% +b(8);
val = Power.^-b(1) ...
+b(2)*Speed.^2 ...
+b(3).*Speed ...
+b(4)*Altitude.^2 ...
+b(5)*Altitude ...
+b(6);
end
  3 个评论
Toon
Toon 2020-2-28
With some tweaking and by using a different function form I managed to get rid of the inf values and got a reasonably good fit. Thank you for your help!
Rik
Rik 2020-2-28
You're welcome, glad to be of help.

请先登录,再进行评论。

更多回答(1 个)

Alex Sha
Alex Sha 2020-2-25
Hi, toon, how about the model function below:
z = (p1+p2*x+p3*x^2+p4*y+p5*y^2)/(1+p6*x+p7*x^2+p8*x^3+p9*y+p10*y^2);
where x: speedvector, y:Power
Root of Mean Square Error (RMSE): 0.00691844326129822
Sum of Squared Residual: 0.007036134002491
Correlation Coef. (R): 0.998274976728469
R-Square: 0.996552929162226
Adjusted R-Square: 0.996480612990804
Determination Coef. (DC): 0.996552929142504
Chi-Square: 0.0077055307148613
F-Statistic: 4400.72826907425
Parameter Best Estimate
---------- -------------
p1 0.819461830220929
p2 -0.00987471483675952
p3 0.000133551058989172
p4 0.103028178545445
p5 0.00153694829659665
p6 0.00317128381400631
p7 9.70005191197044E-5
p8 3.74684931649973E-6
p9 0.0777991586491392
p10 0.00764599134548915
  1 个评论
Toon
Toon 2020-2-25
Hi Alex,
This seems promising, but how did you get to this function and the coefficients if I may ask? I also cannot find an altitude variable in your model function, is this correct? Also, The fit doesn’t seem that smooth to me, this will lead to convergence issues with my code.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Get Started with Curve Fitting Toolbox 的更多信息

产品


版本

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by