为什么curve_fit不会收敛β函数拟合?

时间:2018-06-04 12:12:54

标签: python curve-fitting data-fitting model-fitting function-fitting

当我尝试将beta函数调整到几个点时,我的Python代码有一个小问题。问题是解决方案不会收敛(并且结果系数为nans),或者它什么都不做(结果与我的初始猜测保持一致),或者它显然适合,但是适合的是与数据点完全不相似。 我一直在阅读关于beta函数和curve_fit的类似帖子,因为这两个问题都在stackoverflow文献中讨论过,但是我无法找到解决我所遇到的具体问题的方法,所以我想知道你是否可以给我一些想法。

我有一套要点:

x = np.array([0.1, 0.3, 0.5, 0.7, 0.9, 1.1])
y = np.array([0.45112234, 0.56934313, 0.3996803 , 0.28982859, 0.19682153,
   0.]

然后我尝试使用gamma使用curve_fit函数使其符合如下:

from scipy.optimize import curve_fit
from scipy.special import gamma as gamma
def betafunc(x,a,b,cst):
    return cst*gamma(a+b) * (x**(a-1)) * ((1-x)**(b-1))  / ( gamma(a)*gamma(b) )
popt2,pcov2 = curve_fit(betafunc,x,y,p0=(0.5,1.5,0.5))

我的问题就出现了,因为根据我的初步猜测,我得到popt2=[nan,nan,nan]popt2=p0,或者几次得到的值,在绘制时,不会模仿数据所有

我也知道beta函数适用于0< x< 1,所以我尝试重新缩放点,或者只删除数据的最后一点,但这也不好。向曲线拟合添加误差,或者如上所述,更改初始参数也没有帮助。 另外我认为可能只是因为我有3个自由参数和4或5个点,但是,如图所示...... enter image description here

...我已经安装了另一个配置文件(也使用了三个免费参数),并且它没有问题,所以我不明白为什么这个其他beta配置文件不起作用。任何指导都非常感谢!

1 个答案:

答案 0 :(得分:1)

您的实现是针对β分布的概率密度函数(而不是beta函数)。它是在0< = x< = 1的区间内定义的。因此,您的独立数据(x坐标)必须完全在此区间内。您如何确保这取决于您尝试做的事情的更大背景。可能的方法包括修剪或映射到间隔的某些部分。

按照您的示例,以下(修剪)运行时没有错误:

import numpy as np
from scipy.optimize import curve_fit
from scipy.special import gamma as gamma
def betafunc(x,a,b,cst):
    return cst*gamma(a+b) * (x**(a-1)) * ((1-x)**(b-1))  / ( gamma(a)*gamma(b) )

x = np.array( [0.1, 0.3, 0.5, 0.7, 0.9, 1.1])
y = np.array( [0.45112234, 0.56934313, 0.3996803 , 0.28982859, 0.19682153, 0.] )


popt2,pcov2 = curve_fit(betafunc,x[:-1],y[:-1],p0=(0.5,1.5,0.5))

print popt2
print pcov2

并生成结果:

[ 1.22624727  1.74192827  0.37084996]
[[ 0.03758865  0.04888083 -0.00132468]
 [ 0.04888083  0.09142608 -0.00309165]
 [-0.00132468 -0.00309165  0.00094766]]

这也是(重新缩放x),运行没有错误:

import numpy as np
from scipy.optimize import curve_fit
from scipy.special import gamma as gamma
def betafunc(x,a,b,cst,scale):
    x = x / scale
    return cst*gamma(a+b) * (x**(a-1)) * ((1-x)**(b-1))  / ( gamma(a)*gamma(b) )

x = np.array( [0.1, 0.3, 0.5, 0.7, 0.9, 1.1])
y = np.array( [0.45112234, 0.56934313, 0.3996803 , 0.28982859, 0.19682153, 0.] )

popt2,pcov2 = curve_fit(betafunc,x,y,p0=(0.5,1.5,0.5,1.1))

print popt2
print pcov2

并生成结果:

[ 1.37100253  2.36832069  0.32337175  1.16052822]
[[ 0.04972377  0.15943756 -0.00792804  0.02550767]
 [ 0.15943756  0.71001918 -0.04180131  0.14426687]
 [-0.00792804 -0.04180131  0.00312037 -0.00983075]
 [ 0.02550767  0.14426687 -0.00983075  0.0373759 ]]

请注意,在第二个示例中,x范围缩放也是拟合变量之一。但它也可以由你的问题决定。这一切都取决于你的背景。

同样,哪种方法适合您使用,取决于数据来源的详细信息。您选择的方法应该在您尝试适合的数据的上下文中以及您希望实现的目标中具有物理意义。