首先,用于测试两个样本是否来自同一分布的正确测试是在 中实现的双样本 KS 测试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
.)