Optimization single nonlinear equation to fit predicted data to actual data

10 views (last 30 days)
I am trying to come up with an equation that will use parameters of a given object to predict how it will function. I have actual performance data (call it ydata) and 3 parameters of 11 different objects as my data set. I start with a guess (call it xdata) for each object and am trying to optimize an equation of the format a * p1^w * p2^y * p3^z = xdata such that xdata is as close as possible to y data for each point (in this case, p1, p2, p3 are the known parameters and w, y, z are the variables that need to be changed to get xdata to match ydata and a is just a constant). What I want to end up with is one value for w, one value for y, and one value for z that optimizes all 11 data points at once, essentially making sure the R^2 value comparing xdata and ydata of all 11 points is >=0.9 but I cannot figure out a way to do this successfully. It seems like no matter what method I try (lsqcurvefit, surrogateopt, solve, fmincon, etc) runs into some sort of error or will not work with the problem I am trying to solve. For most of the optimization methods that look to minimize, I have tried setting up the equation like so: a * p1^w * p2^y * p3^z - xdata = 0 and setting the constraint that the function value must be greater than 0 but I can't figure out a way to constrain the function value itself, it seems only the variables you are trying to change (w,y,z) can be constrained.
Any thoughts, even a general direction, would be super helpful at this point.
  1 Comment
othman warde
othman warde on 14 Feb 2023
[١٥/٢, ١٢:٣٢ ص] .othman Alibory: % Define the function to be optimized fun = @(p, xdata) p(1) * xdata(:, 1).^p(2) .* xdata(:, 2).^p(3) .* xdata(:, 3).^p(4);
% Define the initial guess for the parameters p0 = [1, 1, 1, 1];
% Load the data load('data.mat'); % replace with the name of your data file xdata = data(:, 1:3); ydata = data(:, 4);
% Define the nonlinear least squares problem problem = struct; problem.objective = @(p) ydata - fun(p, xdata); problem.x0 = p0; problem.lb = [0, -Inf, -Inf, -Inf]; % Lower bounds on the parameters problem.ub = [Inf, Inf, Inf, Inf]; % Upper bounds on the parameters
% Solve the nonlinear least squares problem options = optimoptions('lsqnonlin', 'Algorithm', 'trust-region-reflective', 'Display', 'iter'); [p, resnorm, residual, exitflag, output, lambda, jacobian] = lsqnonlin(problem);
% Extract the optimized parameters a = p(1); w = p(2); y = p(3); z = p(4);
% Evaluate the model with the optimized parameters xdata_fit = xdata; ydata_fit = fun(p, xdata);
% Compute the R^2 value R2 = 1 - sum((ydata - ydata_fit).^2) / sum((ydata - mean(ydata)).^2);
% Plot the results figure; scatter(ydata, ydata_fit); xlabel('Actual Performance Data'); ylabel('Predicted Performance Data'); title(sprintf('R^2 = %.2f', R2)); [١٥/٢, ١٢:٣٢ ص] .othman Alibory: This code defines a function fun that computes the predicted performance data given the parameters and the input data, and sets up a nonlinear least squares problem using the lsqnonlin function. The initial guess for the parameters is set to p0 = [1, 1, 1, 1], but you can modify this as needed. The lower and upper bounds on the parameters are set to [0, -Inf, -Inf, -Inf] and [Inf, Inf, Inf, Inf], respectively, to ensure that the parameters are positive. The lsqnonlin function then searches for the values of the parameters that minimize the sum of squared residuals between the observed and predicted values.
After finding the optimized parameters, the code evaluates the model with these parameters and computes the R^2 value to evaluate the goodness of fit. Finally, the code plots the actual versus predicted performance data to visualize the results.
Note that this is just an example, and you may need to modify the code to fit your specific problem. In particular, you should replace data.mat with the name of your data file and modify the input and output variables of the fun function to match your parameter and data format.

Sign in to comment.

Answers (1)

Torsten
Torsten on 2 Feb 2023
Edited: Torsten on 2 Feb 2023
"nonlcon" as the nonlinear constraint function from "fmincon" can constrain a*p1(i)^w * p2(i)^y * p3(i)^z as well, if this is what you want.
But maybe - to get a good initial guess for a,w,y and z - you should first take log of your model and thus fit a linear model
log(ydata) = log(a) + w*log(p1) + y*log(p2) + z*log(p3)
where ydata are your (measured) performance data and p1, p2 and p3 are the factors that influence this performance.
  8 Comments
Mckenzie
Mckenzie on 6 Feb 2023
The goal is to have it come up with 11 different solutions (one for each data point) for x1, x2, and x3 which is why I was looking into the for loop, so a simple summation would not work in this context.
Torsten
Torsten on 6 Feb 2023
Edited: Torsten on 6 Feb 2023
You want different parameters for each measurement ? But then you have 11x1 equation for 11x3 unknowns which will give you -eh, bullshit.
The parameters will be almost arbitrary because you can always fix 2 parameters and find a remaining one that makes
num(:,2) .* num(:,3).^p(1) .* num(:,4).^p(2) .* num(:,5).^p(3) - num(:,1) == 0
Take e.g.
p(1) = p(2) = 0
and
p(3) = log(num(:,1)/num(:,2)) / log(num(:,5))

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!