如何在参数范围限制的情况下用 scipy 拟合曲线

问题描述 投票:0回答:1

我正在尝试使用

scipy.genextreme.fit
将 GEV 拟合到某些数据,例如

from scipy.stats import genextreme as gev
import numpy as np

# Generate some random data
data = np.random.normal(size=1000)

# Fit the data to a GEV distribution
params = gev.fit(data)

print(params)

如果我想拟合 GEV 并保持比例参数的值固定(例如 0.5),我只需要做:

params = gev.fit(data,f0=0.5)

我真正想要的是拟合 GEV 并将比例参数的值保持在一个范围内(例如 -0.5 和 0.5 之间)。我试过:

params = gev.fit(data,f0=[-0.5,0.5]) #Does not work

可以用 scipy 指定拟合参数的范围吗?

python scipy curve-fitting data-fitting probability-distribution
1个回答
0
投票

我找到了一些关于如何使用答案的元素

scipy.optimize.minimize

我从 GEV 生成随机数据,我正在使用“scipy.stats.genextreme.fit”拟合它们,并比较我从

scipy.optimize.minimize
获得的 4 个不同边界的结果:

  • Bounds = 未指定(应该等同于 None)
  • Bounds = None(明确完成)
  • Bounds 设置为 -inf 到 inf(实际上应该是无界的)
  • Bounds 设置为我想要的实际值 (shape:[-0.5,0.5], loc:[-inf,inf], scale[0,inf]
import warnings
import numpy                                 as np
from   scipy.stats    import genextreme      as gev
from   scipy.optimize import minimize,Bounds
warnings.filterwarnings("ignore")

# Function to be minimized
def fun(x):
    return -np.sum(gev.logpdf(data, x[0], loc=x[1], scale=x[2]))

# Generate a random sample from a GEV distribution
c     = 0.25
loc   = 1
scale = 2
data = gev.rvs(c, loc=loc, scale=scale, size=10000)


################################
# Fitting the curve using "fit"#
################################
C,LOC,SCALE = gev.fit(data, method='mle')
print('%12s'%'Using fit:','[%.8f,%.8f,%.8f]'%(C,LOC,SCALE))


############################################################
# Fitting the curve using "minimize" (and different bounds)#
############################################################
# Define the initial guess for the parameters
x0 = np.array([-0, np.mean(data), 1 ])

# No specifying the  bounds (default should be None if I understood correctly)
res = minimize(fun,x0)
print('%12s'%'Unspecified:',res.x)

# Explicitely using None
bounds=None
res = minimize(fun, x0, bounds=bounds)
print('%12s'%'None:',res.x)

# Setting -infinity and +infinity (~ no bounds?)
bounds = Bounds([-np.inf,-np.inf,-np.inf],[np.inf,np.inf,np.inf],True)
res = minimize(fun, x0, bounds=bounds)
print('%12s'%'-inf to inf:',res.x)

# Setting bound on the shape parameter c:[0.5,0.5])
bounds = Bounds([-0.5,-np.inf,0],[0.5,np.inf,np.inf],True)
res = minimize(fun, x0, bounds=bounds)
print('%12s'%'My choice:',res.x)

输出如下所示:

  Using fit: [0.24802565,0.99147038,1.99752719]
Unspecified: [0.24803505 0.99151589 1.99750206]
       None: [0.24803505 0.99151589 1.99750206]
-inf to inf: [0.         1.74141644 1.        ]
  My choice: [0.15475374 1.42297545 1.97813723]

所以当 Bounds 未指定或设置为 None 时,我们得到的结果非常接近预期值(从 fit 获得),但在其他情况下它会失败(参数在指定范围内,但它们没有预期价值)。为什么?

最后一点,如果我使用负值的形状参数,例如c=-0.25,“我的选择”现在产生与 Unspecified 和 None 相同的值:

  Using fit: [-0.24485102  1.01219881  2.01972737]
Unspecified: [-0.24486353  1.01221328  2.01976429]
       None: [-0.24486353  1.01221328  2.01976429]
-inf to inf: [0.           2.81041857  1.        ]
  My choice: [-0.24486356  1.01221433  2.01976554]
© www.soinside.com 2019 - 2024. All rights reserved.