我想在gnuplot中拟合我的数据,其拟合关系具有第二类修改后的贝塞尔函数。所以,让我们说它看起来像这样:
f(x)= A*x + b*besselk(1,b)
(我用matlab或octave和系数写的,我想找到的是A和b,所以其中一个就是bessel)。但问题是gnuplot没有修改第二类bessel功能。
任何人都知道我该怎么做?
答案 0 :(得分:2)
最佳拟合策略通常是将非线性或非多项式问题减少为线性或多项式问题。特别是,线性问题总是只有一个解决方案。因此,我们理想情况下f(x) = A*x + B
适用于B = b * besy1(b)
- 这适用于第二类贝塞尔函数,请参阅下面的第二类已修改贝塞尔函数的编辑,这些函数不可用在Gnuplot。你这样做:
fit A*x + B "datafile" via A, B
获得B
后,您可以在b
找到与y = x * besy1(x)
与B
的交叉点对应的x = b
。由于besy1(x)
是振荡的,因此可能会有多个结果,但根据您提供数据的范围,您可以选择正确的结果。假设您从拟合得到B = 1.2
,那么[0:10]
区间的交叉点如下:
plot [0:10] x*besy1(x), 1.2
如果您感兴趣的区域在x = 4.65
附近,其中有一个交叉点的大致位置,那么请查找完全相交。 x * besy1(x)
和B
之间的距离在此区域将接近零,因此距离平方可以用具有明确定义的最小值的抛物线近似:
plot [4.6:4.7] (x*besy1(x)-1.2)**2
您的最佳x = b
是此最低要求的位置。您可以将其导出为数据并适合抛物线f(x) = a2*x**2 + b2*x + c2
,其最小值为f'(x) = 0
,即x = -b2 / (2.*a2)
:
set table "data_minimum"
plot [4.6:4.7] (x*besy1(x)-1.2)**2
unset table
fit [4.6:4.7] a2*x**2 + b2*x + c2 "data_minimum" via a2,b2,c2
print -b2/2./a2
这会为x = 4.65447163370989
提供最小的位置,与b
中的最佳B = b*besy1(b)
相对应。
这种精确度取决于二次拟合的优点,而二次拟合又取决于x值范围的最小值。在这种情况下,范围[4.6:4.7]
导致二次拟合非常好但不完美(您可以进一步缩小范围):
plot [4.6:4.7] "data_minimum" t "data", a*x**2+b*x+c t "quadratic fit"
修改强>
对于第二种改进的贝塞尔函数,或者Gnuplot中没有的其他复杂函数,可以使用外部解析器。例如,请参阅我的答案,了解如何使用外部python代码来解析函数:Passing Python functions to Gnuplot。
您可以使用scipy
访问您的函数,从我的其他答案(文件名test.py
)修改Python脚本:
import sys
from scipy.special import kn as kn
n=float(sys.argv[1])
x=float(sys.argv[2])
print kn(n,x)
在Gnuplot内使用此作为
kn(n,x) = real(system(sprintf("python test.py %g %g", n, x)))
然后,上述所有程序只能将besy1(x)
替换为kn(1,x)
。