我有一组数据,在绘制时,看起来像这样。
我需要使用polyfit
命令来确定大致在1.7
和2.3
之间的时间的最佳拟合指数。我还必须将此指数拟合与简单的线性拟合进行比较。
我得到等式Temp(t) = Temp0 * exp(-(t-t0)/tau)
,其中t0
是与温度Temp0
对应的时间(我可以选择从哪里开始曲线拟合,但必须限制在面积大致介于1.7和2.3之间)。这是我的尝试。
% 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)
我的指数拟合最终看起来像。我的线性拟合看起来像。 (几乎相同)。我做错了什么?两者是否应该如此相似?我被告知circshift
可能会有所帮助,但在阅读帮助文件后我无法理解命令的适用性。
答案 0 :(得分:4)
正如我在评论中提到的,在对数空间中拟合线性模型与拟合非线性模型(两者都在最小二乘意义上)之间存在差异。
统计工具箱中有一个很好的demo来解释这种情况。我正在调整以下代码:
%# 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'})
答案 1 :(得分:4)
事情就像你期待的一样。问题是您尝试拟合的功能不是数据的非常好的近似值。观察曲线,似乎曲线的指数部分渐近渐近于16左右的值;但是你使用的功能最终会趋向于0的温度。因此,适合从22到16的部分会给你一个几乎线性的关系。为了说明这一点,我写了几行与你所拥有的数据点大致匹配的代码 - 它们显示了不同的函数(一个趋于0,另一个趋于16)将给你一个非常不同的曲线形状。第一个(你的原始函数)在T值为22和16之间几乎是线性的 - 所以它看起来像线性拟合。
我建议您考虑适合的功能的“正确”形状 - 什么是使您选择特定形式的基础物理?做到这一点至关重要......
以下是代码:
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')
这导致以下情节:
我从中得出结论,你的情节看起来如此相似的主要原因是你试图拟合的功能在你选择的领域几乎是线性的 - 一个不同的功能选择将是更好的匹配。
答案 2 :(得分:2)
如果我理解正确,你在polyfit中使用的变量time和Temp包含所有值(从1.5到2.5)。因此,您可能希望在计算polyfit之前将时间和Temp的值限制为1.71到2.3(现在它正在计算从1.5到2.5的polyfit,因此为什么线不与数据点对齐)。
p = polyfit(time, log(Temp), 1)
答案 3 :(得分:0)
使用
polyfit(x,y,n)
在Matlab曲线拟合工具箱中的功能。