scipy.stats.kde和scipy.stats.kstest

时间:2013-03-21 20:13:47

标签: python statistics scipy probability-theory

如何以保形的方式使用scipy.stats.kde.gaussian_kdescipy.stats.kstest

例如,代码:

from numpy import inf
import scipy.stat
my_pdf = scipy.stats.kde.gaussian_kde(sample)
scipy.stats.kstest(sample, lambda x: my_pdf.integrate_box_1d(-inf, x))

给出以下答案: (0.5396735893479544, 0.0)

这不正确,因为样本显然属于在此样本上构建的分布。

1 个答案:

答案 0 :(得分:1)

首先,用于测试两个样本可能来自同一分布的正确测试是two-sample KS test,在scipy.stats.ks_2samp中实现,直接比较经验CDF。 KDE是密度估计,它可以平滑CDF,因此从统计学角度来说,这也是一堆不必要的工作,也会使你的估计变得更糟。

但是你看到这个问题的原因是你的CDF参数的签名不太正确。 kstest调用cdf(vals) (source),其中vals是已排序的样本,以获取每个样本的CDF值。在您的代码中,这最终会调用my_pdf.integrate_box_1d(-np.inf, samps),但integrate_box_1d希望这两个参数都是标量。签名是错误的,如果您对大多数阵列都尝试过这种签名,那么它会因ValueError

而崩溃
>>> my_pdf.integrate_box_1d(-np.inf, samp[:10])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-38-81d0253a33bf> in <module>()
----> 1 my_pdf.integrate_box_1d(-np.inf, samp[:10])

/Library/Python/2.7/site-packages/scipy-0.12.0.dev_ddd617d_20120725-py2.7-macosx-10.8-x86_64.egg/scipy/stats/kde.pyc in integrate_box_1d(self, low, high)
    311 
    312         normalized_low = ravel((low - self.dataset) / stdev)
--> 313         normalized_high = ravel((high - self.dataset) / stdev)
    314 
    315         value = np.mean(special.ndtr(normalized_high) - \

ValueError: operands could not be broadcast together with shapes (10) (1,1000) 

但不幸的是,当第二个参数是samp时,它可以播放得很好,因为数组是相同的形状,然后一切都变成了地狱。据推测integrate_box_1d应检查其参数的形状,但这是正确执行此操作的一种方法:

>>> my_cdf = lambda ary: np.array([my_pdf.integrate_box_1d(-np.inf, x) for x in ary])
>>> scipy.stats.kstest(sample, my_cdf)
(0.015597917205996903, 0.96809912578616597)

如果您愿意,也可以使用np.vectorize

(但是,您可能实际上想要使用ks_2samp。)