The issue of optimization (minimization) of the average relative error between experimental and calculated data

85 views (last 30 days)
hello
I want to share the difficulties that I faced. Can someone help
problem statement:
there is a 'x' column where the values ​​of the independent variable are written and there is a 'y' column where the experimental values ​​of the dependent variable are written.
approximation model is considered:
y_calculate=A*x^B+C,
and based on this model, an objective function is created, which is equal to the average value of the relative deviations between y and y_calculate:
error_function = mean(abs(y - y_calculate)) / y)=mean(abs(y - =A*x^B+C)) / y);
Our goal is to select parameters A,B,C in such a way that 'error_function' takes the value of the global minimum.
I calculated the optimal values ​​of A, B, C and got:
A = 85.5880, B = -0.0460, C = 4.8824,
at which error function value for optimized parameters: 0.0285.
but I know in advance the specific values ​​of A, B, C:
A = 1005.6335852931, B = -1.59745963925582, C = 73.54149744754400,
at which error function value for specific parameters: 0.002680472178434,
which is much better than with optimization
Below is the code with visualization, which confirms the above.
clear
close all
% Data
x = [7.3392, 14.6784, 22.0176, 29.3436, 36.6828, 44.0088, 51.3348, 58.674, 66, 73.3392, 80.6652, 88.0044, 95.3304, 102.6696, 109.9956, 117.3348, 124.6608, 132];
y = [115.1079, 87.7698, 80.5755, 78.1611, 76.5743, 75.7074, 74.9375, 74.9453, 74.59, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990];
% Initial guesses for parameters A, B, C
initial_guess = [1, 1, 1];
% Error function
error_function = @(params) mean(abs(y - (params(1) * x.^params(2) + params(3))) ./ y);
% Optimization of parameters
optimized_params = fminsearch(error_function, initial_guess);
% Results of optimization
A_optimized = optimized_params(1);
B_optimized = optimized_params(2);
C_optimized = optimized_params(3);
% Calculation of the fitted function for optimized parameters
y_calculate_optimized = A_optimized * x.^B_optimized + C_optimized;
% Calculate and display the error function value for optimized parameters
value_error_optimized = error_function(optimized_params);
fprintf('Optimized parameters:\nA = %.4f\nB = %.4f\nC = %.4f\n', A_optimized, B_optimized, C_optimized);
fprintf(' error function value for optimized parameters: %.4f\n', value_error_optimized);
% Other specific parameters A, B, C
A_specific = 1005.63358529310;
B_specific = -1.59745963925582;
C_specific = 73.541497447544;
% Calculation of the fitted function for specific parameters
y_calculate_specific = A_specific * x.^B_specific + C_specific;
% Calculate and display the error function value for specific parameters
value_error_specific = error_function([A_specific, B_specific, C_specific]);
fprintf('Specific parameters:\nA = %.10f\nB = %.14f\nC = %.14f\n', A_specific, B_specific, C_specific);
fprintf(' error function value for specific parameters: %.4f\n', value_error_specific);
% Visualization
figure;
plot(x, y, 'bo-', 'DisplayName', 'Experimental data');
hold on;
plot(x, y_calculate_optimized, 'r--', 'DisplayName', 'Fitted model (Optimized)');
plot(x, y_calculate_specific, 'g-.', 'DisplayName', 'Fitted model (Specific)');
xlabel('x');
ylabel('y');
legend('Location', 'best');
title('Approximation of experimental data');
grid on;
Obviously, my optimization code does not lead to a global minimum of the objective function, since there is a better approximation for specific values ​​of A,B,C. Maybe this is caused by a random selection of the initial values ​​of the parameters A=1, B=1, c=1 and therefore my code is stuck in a local minimum?
who can write a code that will select the A,B,C parameters so as to achieve the global minimum of the target function 'error_function', for any initial iteration data of the variables A,B,C. Thoughts for testing: the value of the target function 'error_function' should not be worse (that is, more) than 0.002680472178434, which is obtained with the specific value of A,B,C: A = 1005.6335852931, B = -1.59745963925582, C = 73.54149744754400

Accepted Answer

Matt J
Matt J on 22 Aug 2024
Edited: Matt J on 5 Sep 2024
If you download minL1lin from
then you can do,
% Data
x = [7.3392, 14.6784, 22.0176, 29.3436, 36.6828, 44.0088, 51.3348, 58.674, 66, 73.3392, 80.6652, 88.0044, 95.3304, 102.6696, 109.9956, 117.3348, 124.6608, 132];
y = [115.1079, 87.7698, 80.5755, 78.1611, 76.5743, 75.7074, 74.9375, 74.9453, 74.59, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990];
% Initial guess for parameter B
initial_guess = 1;
% Error function
error_function = @(B) objFun(B, x,y);
% Optimization of parameters
B = fminsearch(error_function, initial_guess);
[fval,ABC]=error_function(B);
[A,B,C]=deal(ABC{:})
A = 1.0460e+03
B = -1.6184
C = 73.5535
fval
fval = 0.0025
function [fval,p]=objFun(theta, x,y)
arguments
theta; x (:,1); y(:,1);
end
B=theta;
d=ones(size(y));
Q=[x.^B, d]./y;
[AC,fval]=minL1lin(Q,d,[],[],[],[],[],[],[],optimoptions('linprog','Display','off'));
fval=fval/numel(y);
A=AC(1); C=AC(2);
p={A, B, C};
end
  45 Comments
Torsten
Torsten on 21 Nov 2024 at 21:08
Edited: Torsten on 22 Nov 2024 at 11:14
I don't get errors in all the three cases. You should update to the most recent MATLAB release.
clear
% Data
% the first series of x , y values, at which the script works successfully and gives the result fval=0.0015:
% x = [7.3392, 14.6784, 22.0176, 29.3436, 36.6828, 44.0088, 51.3348, 58.674, 66, 73.3392, 80.6652, 88.0044, 95.3304, 102.6696, 109.9956, 117.3348, 124.6608, 132];
% y = [115.1079, 87.7698, 80.5755, 78.1611, 76.5743, 75.7074, 74.9375, 74.9453, 74.59, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990, 74.2990];
%the second series of x , y values, at which the script also works successfully, but gives the message:
% x = [14.6784, 22.0176, 29.3436, 36.6828, 44.0088, 51.3348, 58.6740, 66, ...
% 73.3392, 80.6652, 88.0044, 95.3304, 102.6696, 109.9956, 117.3348, 124.6608, 132];
% y = [8.80982634, 9.359883, 8.83235329, 9.05116997, 8.640265855, 8.87955602, 8.90198004, 8.351331895, ...
% 8.435, 8.23, 8.22833633, 8.15836833, 8.0604534, 8.15348853, 7.671930455, 8.346546765, 8.15];
% the third series of x, y values at which the script fails and returns an error
x = [14.6784; 22.0176; 29.3436; 36.6828; 44.0088; 51.3348; 58.6740; 66; ...
73.3392; 80.6652; 88.0044; 95.3304; 102.6696; 109.9956; 117.3348; 124.6608; 132];
y = [6.53; 6.714628295; 5.75798471; 5.75746671; 5.75884823; 6.17125225; 5.75928009; 6.4; ...
6.0475162; 6.28375061; 5.75971201; 5.981722515; 6.17125225; 6.34975669; 6.325585625; ...
6.304601135; 6.285626125];
% Initial guess for parameter theta
initial_guess = [1,1];
% Error function
error_function = @(theta) objFun(theta, x,y);
% Optimization of parameters
%Bounds on lambda and m
lambda0 = 0;
lambda1 = 3;
m0 = 0;
m1 = inf;
%Call the optimizer
theta = fminsearchbnd(error_function, initial_guess,[lambda0,m0],[lambda1,m1]);
%theta = fminsearch(error_function, initial_guess);
[fval,AthetaC]=error_function(theta);
[A, theta,C]=deal(AthetaC{:})
A = 0.3587
theta = 1×2
0.0418 461.2531
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
C = 6.1713
fval
fval = 0.0343
function [fval,p]=objFun(theta, x,y)
x=x(:);y=y(:); theta=theta(:)';
lambda=theta(1); m=theta(2);
d=ones(size(y));
Q=[ 1./(1 + (lambda * x).^m), d]./y;
%Bounds on A and C
A0 = 0;
A1 = inf;
C0 = 0.9*min(y);
C1 = 1.1*min(y);
lb=[A0,C0];
ub=[A1,C1];
%Call the optimizer
[AC,fval]=minL1lin(Q,d,[],[],[],[],lb,ub,[],optimoptions('linprog','Display','off'));
fval=fval/numel(y);
A=AC(1); C=AC(2);
p={A, theta, C};
end
roborrr
roborrr on 22 Nov 2024 at 7:29
Torsten: I don't get errors in all the three cases. You should update to the most recent MATLAB release.
Thanks for the advice. I will install the latest version of matlab.

Sign in to comment.

More Answers (0)

Products


Release

R2018b

Community Treasure Hunt

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

Start Hunting!