我使用chi2分布作为一个模拟系统的理论问题。
对于给定的间隔,我需要将此分布估计为PMF,该PMF定义为该间隔内PDF的积分。该值应接近间隔中心处的PDF的值,但可以略有不同,具体取决于PDF的形状。
下面是我要做的:
import numpy
from scipy.stats import chi2
dist = chi2(10)
nbins = 120
F = dist.cdf(numpy.arange(nbins+1))
pmf = F[1:] - F[:-1] # surface inside the interval
pmf /= pmf.sum() # Normalisation问题是,chi2.cdf(100, 10)和更高版本给出的恰好是1.0。所以我能得到的最小值大约是1.11e-16。但是chi2.pdf(100, 10)并不完全是0(大约是2.5e-17)。
我的问题是:如何获得更高精度的pmf估计(可能高达1e-25)?为什么cdf函数比pdf函数精度低?
发布于 2011-06-10 11:49:52
cdf在浮点精度等于1的范围内,但sf接近于零,因此1e-20的微小差异不会被大1所掩盖。(请参阅JABS参考)
>>> probs_from_cdf = np.diff(stats.chi2.cdf(np.arange(nbins+1), 10))
>>> probs_from_sf = np.diff(stats.chi2.sf(np.arange(nbins+1)[::-1], 10))[::-1]
>>> probs_from_sf[:4]
array([ 0.00017212, 0.00348773, 0.01491609, 0.03407708])
>>> probs_from_cdf[:4]
array([ 0.00017212, 0.00348773, 0.01491609, 0.03407708])
>>> probs_from_cdf[-5:]
array([ 0., 0., 0., 0., 0.])
>>> probs_from_sf[-5:]
array([ 1.94252577e-20, 1.21955220e-20, 7.65430774e-21,
4.80270079e-21, 3.01259913e-21])我不知道sf的精确范围,即scipy.special.chdtrc(df,x)走了多远
发布于 2011-06-10 12:39:21
通常,每当我遇到精度问题时,我使用的第一个工具就是mpmath。90%的时间它只是工作(Tm),足够快。在这种情况下,我们可以这样写:
import mpmath
mpmath.mp.dps = 50 # decimal digits of precision
def pdf(x,k):
x,k = mpmath.mpf(x), mpmath.mpf(k)
if x < 0: return 0
return 1/(2**(k/2) * mpmath.gamma(k/2)) * (x**(k/2-1)) * mpmath.exp(-x/2)
def cdf(x,k):
x,k = mpmath.mpf(x), mpmath.mpf(k)
return mpmath.gammainc(k/2, 0, x/2, regularized=True)
def cdf_via_quad(s,k):
return mpmath.quad(lambda x: pdf(x,k), [0, s])给予(使用你的F):
>>> pdf(2,10)
mpf('0.0076641550244050483665734118783637680717877318964951605')
>>> cdf(2,10)
mpf('0.003659846827343712345456455812710150667594853455628779')
>>> cdf_via_quad(2,10)
mpf('0.003659846827343712345456455812710150667594853455628779')
>>> F[2]
0.0036598468273437131
>>> pdf(100,10)
mpf('2.5113930312030179466371651256862142900427508479560716e-17')
>>> cdf(100,10)
mpf('0.99999999999999994550298017079470664906667698474760744')
>>> cdf_via_quad(100,10)
mpf('0.99999999999999994550298017079470664906667698474760744')
>>> F[100]
1.0使用quad来获得所需的任何规范化应该很简单。
https://stackoverflow.com/questions/6298105
复制相似问题