10

我的一个朋友在 gnuplot 中发现了一些关于简单多项式拟合的奇怪行为 有人可以解释一下吗?

这是文件:

#!/usr/bin/gnuplot -p

f(x) = B*(x**4) + A
fit f(x) "data.txt" using ($1+273.14):2 via A, B

plot    "data.txt" using ($1+273.14):2 notitle,\
        f(x) notitle

数据是:

# content of data.txt
350 3.856
330 3.242
290 2.391
250 1.713
210 1.181
170 0.763
130 0.437

结果图是绿线。蓝线显示使用基本相同形式的另一个函数的拟合效果要好得多。对于绿线,A 被一个常数值代替(A = 0.2123,大约是 B*300^4)

奇怪的拟合行为 gnuplot

所以绿线显然不是这里的最佳拟合,因为f(x) = B*(x**4) - 0.2123产生的结果要好得多,并且也是 B*x 4 + A 的形式。在绿色拟合中,参数 **A 被 gnuplot 简单地忽略,并且拟合算法保持不变。为 A 和 B 设置不同的初始值似乎没有多大帮助 - A 的值永远不会改变它的初始值。我和我的朋友正在使用 Ubuntu 附带的标准 Gnuplot 版本:gnuplot 4.4 patchlevel 3。

4

2 回答 2

9

这是一个非常好的(和涉及的)问题,我没有完整的答案,但以下内容有望有所启发。

拟合使用最小二乘拟合例程 ( Levenberg–Marquardt )。它迭代地收敛于一个“好”的解决方案。需要多好的解决方案是由FIT_LIMIT变量决定的。默认情况下,FIT_LIMIT 设置为(保守的)1.e-5。显然,与更改 A 相比,通过更改迭代路由中 B 的值,您的数据收敛速度要快得多。事实上,正如您所注意到的,您甚至可以在不触及变量 A 的情况下低于错误阈值。但是,如果您加快速度您的期望(您希望获得更好的拟合,因此您设置FIT_LIMIT为较低的值 - 我将其设置为1.e-14),你会得到更好的结果。您在这里付出的代价是拟合可能需要更长的时间才能收敛(或者甚至可能发散——我不是拟合专家)。这里的一个要点是,功能拟合与其说是一门科学,不如说是一门艺术——没有最好的拟合,只有足够好的拟合

另请注意,该算法搜索残差平方的局部最小化(满足您给出的容差)。它不保证它找到一个全局最小值。

#!/usr/bin/gnuplot -p

FIT_LIMIT=1.e-14
f(x) =A +  B*(x**4)
fit f(x) "data.txt" using ($1+273.14):2 via A, B

plot     "data.txt" using ($1+273.14):2 notitle,\
         f(x) notitle

另请注意,如果您发现 gnuplot 收敛到错误的最小值,您可以通过执行以下操作“播种”拟合例程:

FIT_LIMIT=1.e-14
f(x) =A +  B*(x**4)
A=1.3  #initial guess for A
fit f(x) "data.txt" using ($1+273.14):2 via A, B

plot     "data.txt" using ($1+273.14):2 notitle,\
         f(x) notitle
于 2012-06-17T22:27:44.377 回答
6

只需尝试下面的代码。诀窍是确保 x 和 y 变量的范围具有相同的数量级。

reset;
plot 'data.txt' u ($1+273.14):2 w p;
f(x, a, b) = a*(1e-2*x)**4 + b; # note the 1e-2 multiplicative factor
a = 1; b = 1; # initial parmeters
fit f(x,a,b) 'data.txt' u (($1+273.14)):2 via a, b
#plot 'data.txt' u (($1+273.14)):2 w p, f(x, a, b) w l
plot 'data.txt' u (($1+273.14)):2 w p, (a*(1e-2)**4)*x**4+b w l
print sprintf("Fit parameters for the fit function a*x^4 + b are :\n\ta = %e, \n\tb = %f", a*(1e-2)**4, b)

图表的图像

于 2014-11-11T20:10:02.713 回答