Piece-wise non-linear fitting with fminsearch - issue with quadratic function
Show older comments
Hello everybody.
I have a series of experimental data (tabella_raw.txt, column #4) for which I want to find the best interpolation function. If you have a look at the experimental data named 'qse' you can see that the best option is a piece-wise interpolation: three functions, in particular, the first part quadratic (from 0 to 1 h), as well as the second (from 1 to 2), and the third is hyperbolic (from 2 to end). The function must be continuous. I tried to find at first some suitable expressions for the three parts and then, by adopting fminsearch that minimizes the error between the two curves, and I got some kind of interpolation curve (the red one). In blue you can see the experimental data.
However, there is something wrong or better to say, something I don't like. At 1 and 2 (yellow dots) I want to have the maximum and the minimum values of the function. Is there any possibile way to set up some paramters contraints to obtain something like the second picture?
I attach the matlab code, as well.
For any doubts, please write me.
Thanks in advance.
Maja


10 Comments
Mathieu NOE
on 9 Jan 2024
just for my own fun, I wanted to see if we could put a first order model (so exponential functions) to fit your data (you say "interpolation" but you meant model fitting probably)
so this is it , and obviously it coud be improved (usind an optimizer) , especially on the 3rd segement

code FYI
clc
clear all
close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% INTERPOLAZIONE CURVE DINAMICO %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
data=readmatrix('tabella_raw.txt');
tsi=data(:,1); tse=data(:,2); qsi=data(:,3); qse=data(:,4);
ti=data(:,5); to=data(:,6);
%__________________________________________________________________________
% INTERPOLAZIONE CURVE
%__________________________________________________________________________
% usare la scala x ogni ora per fitting corretto
n = 500;
ind = (1:n);
x=(ind/60)';
dT = 10; % delta T impulso (10°)
qse = qse(ind);
%% flusso termico esterno qse
b1 = -2; % exponant term
% first segment
[m1,i1] = max(qse);
y1 = m1*(1-exp(b1*x));
y1(i1:end) = NaN;
% second segment
[m2,i2] = min(qse);
[m3,i3] = max(y1);
b2 = -2; % exponant term
y2 = m3 - (m1-m2)*(1-exp(b2*(x-x(i1))));
y2(1:i1) = NaN;
y2(i2:end) = NaN;
% third segment
b3 = -3; % exponant term
y3 = m2*exp(b3*(x-x(i2)));
y3(1:i2) = NaN;
plot(x,qse)
hold on
plot(x,y1)
plot(x,y2)
plot(x,y3)
hold off
Maja
on 9 Jan 2024
Mathieu NOE
on 10 Jan 2024
hello again
still playing with it. Found a better fit function for the 3rd segment

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% INTERPOLAZIONE CURVE DINAMICO %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
data=readmatrix('tabella_raw.txt');
tsi=data(:,1); tse=data(:,2); qsi=data(:,3); qse=data(:,4);
ti=data(:,5); to=data(:,6);
%__________________________________________________________________________
% INTERPOLAZIONE CURVE
%__________________________________________________________________________
% usare la scala x ogni ora per fitting corretto
n = 500;
ind = (1:n);
x=(ind/60)';
dT = 10; % delta T impulso (10°)
qse = qse(ind);
%% flusso termico esterno qse
b1 = -2.1; % exponant term
% first segment
[m1,i1] = max(qse);
y1 = m1*(1-exp(b1*x));
y1(i1:end) = NaN;
% second segment
[m2,i2] = min(qse);
[m3,i3] = max(y1);
b2 = -2.4; % exponant term
xx = x-x(i1);
y2 = m3 - (m1-m2)*(1-exp(b2*xx));
y2(1:i1-1) = NaN;
y2(i2:end) = NaN;
% third segment
b3 = -1; % exponant term
b4 = -1; % exponant term
xx = x-x(i2);
y3 = m2*exp(b3*xx + b4*xx.^0.25);
y3(1:i2-1) = NaN;
plot(x,qse)
hold on
plot(x,y1)
plot(x,y2)
plot(x,y3)
hold off
Maja
on 10 Jan 2024
Maja
on 15 Jan 2024
Maja
on 15 Jan 2024
Maja
on 15 Jan 2024
Mathieu NOE
on 15 Jan 2024
hello
just regarding your comment about having one single continuous fitting function
this is what I could do , simply by using a sigmoid function to apply like a weight window (could be done with some kind of step function)

clc
clear all
close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% INTERPOLAZIONE CURVE DINAMICO %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
data=readmatrix('tabella_raw.txt');
tsi=data(:,1); tse=data(:,2); qsi=data(:,3); qse=data(:,4);
ti=data(:,5); to=data(:,6);
%__________________________________________________________________________
% INTERPOLAZIONE CURVE
%__________________________________________________________________________
% usare la scala x ogni ora per fitting corretto
n = 500;
ind = (1:n);
x=(ind/60)';
dT = 10; % delta T impulso (10°)
qse = qse(ind);
%% flusso termico esterno qse
% sigmoid a parameter
a_sig = -1000; % a large negative value so the sigmoid is like a steped window (sharp transition)
% first segment
[m1,i1] = max(qse);
b1 = -2.1; % exponant term
y1 = m1*(1-exp(b1*x));
x1 = x(i1);
s1 = mysigmoid(x,x1,a_sig);
y1 = y1.*s1;
% second segment
[m2,i2] = min(qse);
[m3,i3] = max(y1);
b2 = -2.4; % exponant term
y2 = m3 - (m1-m2)*(1-exp(b2*(x-x1)));
x2 = x(i2);
s2 = mysigmoid(x,x2,a_sig);
y2 = y2.*(1-s1).*s2;
% third segment
b3 = -1; % exponant term
b4 = -1; % exponant term
y3 = m2*exp(b3*(x-x2) + b4*(x-x2).^0.25);
y3 = y3.*(1-s2);
y = y1+y2+y3;
plot(x,qse)
hold on
plot(x,y)
hold off
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = mysigmoid(x,c,a)
% sigmoid evaluates a simple sigmoid function along x:
%
% ______1________
% y = -a(x-c)
% 1 + e^
%
%% Syntax
%
% y = sigmoid(x)
% y = sigmoid(x,c)
% y = sigmoid(x,c,a)
%
y = 1./(1 + exp(-a.*(x-c)));
end
Maja
on 15 Jan 2024
Mathieu NOE
on 15 Jan 2024
tada !
now the full monty with fminsearch at the rescue
see answer section
Accepted Answer
More Answers (0)
Categories
Find more on Resampling Techniques in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!