I have an array of data which, when plotted, looks like this.
I need to use the polyfit
command to determine the best fitting exponential for the time roughly between 1.7
and 2.3
. I must also compare this exponential fit to a simple linear fit.
I'm given the equation Temp(t) = Temp0 * exp(-(t-t0)/tau)
, where t0
is the time corresponding to temperature Temp0
(I can select where to begin my curve-fitting, but it must be confined to the area roughly between 1.7 and 2.3). Here is my attempt.
% Arbitrarily defined starting point
t0 = 1.71;
%Exponential fit
p = polyfit(time, log(Temp), 1)
tau = -1./p(1)
Temp0 = exp(p(2))
tm = 1.8:0.01:2.3;
Temp_t = Temp0*exp(-(tm)/tau);
plot(time, Temp, tm, Temp_t)
figure(2)
%Linear fit
p2 = polyfit(time, Temp, 1);
Temp_p = p2(1)*tm + p2(2);
plot(time, Temp, tm, Temp_p)
My exponential fit ends up looking like . My linear fit looks like . (virtually identical). What am I doing incorrectly? Should the two fits be so similar? I am told that circshift
may help, but I couldn't grasp the applicability of the command after reading the help file.
Things are behaving just as you are expecting. The problem is that the function you are trying to fit is not a very good approximation of the data. Eyeballing the curve, it seems that the exponential part of the curve tends asymptotically to a value around 16; but the function you are using will eventually tend to a temperature of 0. Thus, fitting to a part that's going from 22 to 16 will give you an almost linear relationship. To illustrate this I wrote a few lines of code that approximately match the data points you have - and that show how different functions (one that tends to 0, and another that tends to 16) will give you a very different shape of the curve. The first (your original function) is almost linear between T values of 22 and 16 - so it will look like the linear fit.
I suggest that you think about the "right" shape of the function to fit - what is the underlying physics that makes you choose a particular form? Getting that right is essential...
Here is the code:
time = linspace(1.5, 2.5, 200);
t0 = 1.7;
t1 = 2.3;
tau = 2.0;
% define three sections of the function:
s1 = find(time < t0);
s2 = find(time >= t0 & time < t1);
s3 = find(time > 2.3);
% compute a shape for the function in each section:
tData(s1) = 28 - 50*(time(s1)-1.5).^2;
tData(s2) = 22*exp(-(time(s2)-t0)/tau);
tData(s3) = tData(s2(end)) + (s3 - s3(1))*12 / numel(s3);
figure
plot(time, tData)
% modify the equation slightly: assume equilibrium temperature is 16
% with a bit of effort one could fit for this as a second parameter
Teq = 16;
tData2 = tData;
tau2 = tau / 8; % decay more strongly to get down to approx the same value by t1
tData2(s2) = (22 - Teq) * exp( - (time(s2) - t0) / tau2) + Teq;
tData2(s3) = tData2(s2(end)) + (s3 - s3(1))*12 / numel(s3);
hold on;
plot(time, tData2, 'r')
This results in the following plot:
I conclude from this that the main reason your plots look so similar is that the function you are trying to fit is almost linear over the domain you are choosing - a different choice of function will be a better match.
As I mentioned in the comments, there is a difference between fitting a linear model in log-space vs. fitting a non-linear model (both in the least-squares sense).
There a nice demo in the Statistics toolbox that explains the situation. I'm adapting the code below:
%# sample data
x = [5.72 4.22 5.72 3.59 5.04 2.66 5.02 3.11 0.13 2.26 ...
5.39 2.57 1.20 1.82 3.23 5.46 3.15 1.84 0.21 4.29 ...
4.61 0.36 3.76 1.59 1.87 3.14 2.45 5.36 3.44 3.41]';
y = [2.66 2.91 0.94 4.28 1.76 4.08 1.11 4.33 8.94 5.25 ...
0.02 3.88 6.43 4.08 4.90 1.33 3.63 5.49 7.23 0.88 ...
3.08 8.12 1.22 4.24 6.21 5.48 4.89 2.30 4.13 2.17]';
xx = linspace(min(x), max(x), 100);
%# linear regression in log-space
%# y = p2 * exp(p1*x)
%# => log(y) = log(p2) + p1*x
p_exp = polyfit(x, log(y), 1);
yy1 = exp(p_exp(2)) .* exp(xx .* p_exp(1));
%# linear regression
p_lin = polyfit(x, y, 1);
yy2 = polyval(p_lin, xx);
%# non-linear regression (using previous result as initial coeff)
f = @(p,x) p(2)*exp(p(1)*x);
p_nonlin = nlinfit(x, y, f, [p_exp(1) exp(p_exp(2))]);
yy3 = f(p_nonlin, xx);
plot(x,y,'o', xx,yy1,'-', xx,yy2,'-', xx,yy3,'-')
legend({'data points','linear in log-space','linear','non-linear'})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With