使用scipy.stats.fit拟合stats.nbinom时非整数n参数的报错问题
解决scipy.stats.fit拟合负二项分布时非整数n的报错问题
问题背景
使用scipy.stats.fit拟合stats.nbinom分布,要求参数n取非整数值时触发报错:
ValueError: There are no integer values for
non the interval defined by the user-provided bounds and the domain of the distribution.
已验证stats.nbinom本身支持非整数n,但不清楚报错原因。
复现代码
from scipy import stats from scipy.optimize import differential_evolution import numpy as np rng = np.random.default_rng() def optimizer(fun, bounds, *, integrality): return differential_evolution(fun, bounds, strategy='best2bin', rng=rng, integrality=[False, False, False]) data = [0,0,0,1,2,4,11] bounds = [(1.5, 1.55), (0, 1)] res4 = stats.fit(stats.nbinom, data, bounds, optimizer=optimizer) print(res4.params)
验证非整数n可行的代码
from scipy import stats import matplotlib.pyplot as plt n = 0.4 p = 0.1 x = np.arange(stats.nbinom.ppf(0.01, n, p), stats.nbinom.ppf(0.99, n, p)) plt.bar(x, stats.nbinom.pmf(x, n, p)) plt.show()
报错原因
scipy.stats.fit默认参考负二项分布的传统定义,将参数n视为整数类型,因此会预先检查你设置的bounds区间内是否存在整数。即使自定义优化器中设置了integrality,fit函数在调用优化器前的参数约束检查环节仍会强制要求n为整数,导致区间(1.5, 1.55)因无整数触发报错。
解决方案
在调用stats.fit时,通过integrality参数显式指定所有参数无需整数约束,同时优化器函数需正确接收该参数(而非硬编码):
from scipy import stats from scipy.optimize import differential_evolution import numpy as np rng = np.random.default_rng() def optimizer(fun, bounds, *, integrality): # 接收fit传入的integrality参数,而非硬编码 return differential_evolution(fun, bounds, strategy='best2bin', rng=rng, integrality=integrality) data = [0,0,0,1,2,4,11] bounds = [(1.5, 1.55), (0, 1)] # 显式指定两个参数都不需要整数约束 res4 = stats.fit(stats.nbinom, data, bounds, optimizer=optimizer, integrality=[False, False]) print(res4.params)
说明
stats.nbinom的概率计算方法(如pmf)确实支持广义负二项分布的非整数n,但stats.fit的默认约束未适配这一点,因此必须手动通过integrality参数覆盖默认设置,才能让拟合过程允许n取非整数值。
内容的提问来源于stack exchange,提问作者JasTonAChair
相关产品推荐
相关产品推荐

