我的一个朋友在gnuplot中发现了一些关于简单多项式拟合的奇怪行为Can sombody可以解释一下吗?
这是文件:
#!/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
Run Code Online (Sandbox Code Playgroud)
数据是:
# 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
Run Code Online (Sandbox Code Playgroud)
得到的图是绿线.蓝线显示使用基本相同形式的另一个功能更好的拟合.对于绿线A,用常数值代替(A = 0.2123,约为B*300 ^ 4)

所以绿线显然不是最合适的,因为f(x) = B*(x**4) - 0.2123产量更好,结果也是B*x 4 + A的形式.在绿色拟合中,参数**A被gnuplot忽略,并且通过拟合算法保持不变.为A和B设置不同的初始值似乎没有多大帮助 - A的值永远不会因其初始值而改变.我的朋友和我正在使用Ubuntu附带的标准Gnuplot版本:gnuplot 4.4 patchlevel 3.
这是一个非常好(和涉及)的问题,我没有完整的答案,但以下将有希望照亮.
Fit使用最小二乘拟合程序(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
Run Code Online (Sandbox Code Playgroud)
另请注意,如果您发现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
Run Code Online (Sandbox Code Playgroud)
只需尝试下面的代码.诀窍是确保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)
Run Code Online (Sandbox Code Playgroud)
