scipy中Anderson-Darling检验k个样本的数学溢出错误

5
我想用 Kolmogorov-Smirnov (KS) 和 Anderson-Darling (AD) 测试来比较一对样本。对于此,我分别使用了 scipy. stats.ks_2sampscipy.stats.anderson_ksamp 。我期望类似的样本会得到一个低的统计值(相同样本为0),而更不同的样本则会得到一个更高的统计值。
在相同的样本和非常不同的样本(没有重叠)的情况下,ks_2samp 提供了预期结果,而 anderson_ksamp 对于相同的样本提供了负值,并且最重要的是,在非常不同的样本中而出现错误(可能是由于样本大小:200 在下面的例子中)。
以下是说明这些发现的代码:
import scipy.stats as stats
import numpy as np
normal1 = np.random.normal(loc=0.0, scale=1.0, size=200)
normal2 = np.random.normal(loc=100, scale=1.0, size=200)

在相同的样本上使用KS和AD:

sstats.ks_2samp(normal1, normal1)
sstats.anderson_ksamp([normal1, normal1])

分别返回:
# Expected
Ks_2sampResult(statistic=0.0, pvalue=1.0) 
# Not expected
Anderson_ksampResult(statistic=-1.3196852620954158, critical_values=array([ 0.325,  1.226,  1.961,  2.718,  3.752]), significance_level=1.4357209285296726)

在不同的样本中:

sstats.ks_2samp(normal1, normal2)
sstats.anderson_ksamp([normal1, normal2])

分别返回:
# Expected
Ks_2sampResult(statistic=1.0, pvalue=1.4175052453413253e-89)
# Not expected
---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-757-e3914aaf909c> in <module>()
----> 1 stats.anderson_ksamp([normal1, normal2])

/usr/lib/python3.5/site-packages/scipy/stats/morestats.py in anderson_ksamp(samples, midrank)
   1694         warnings.warn("approximate p-value will be computed by extrapolation")
   1695 
-> 1696     p = math.exp(np.polyval(pf, A2))
   1697     return Anderson_ksampResult(A2, critical, p)
   1698 

OverflowError: math range error
1个回答

3
我认为这两件事实际上是有意义的。Anderson-Darling测试中的显著性水平或p值是基于测试统计量落在关键值范围内的位置进行外推。测试统计量越靠右,你就越能拒绝它们来自同一分布的零假设。
请注意,在使用你的示例分布参数进行80-90个样本的测试时,你会看到测试统计量(对于normal1和normal2)开始比最大关键值要大得多,这意味着显著性的外推可以自由增长(非常大,因为指数函数是凸向上二次函数从polyfit中计算得出),直至无穷大。因此,对于大样本量,你将计算某些巨大数字的指数并得到溢出。换句话说,你的数据明显不是来自同一分布,因此显著性外推会导致溢出。在这种情况下,你可以从实际数据中引导一个较小的数据集,以避免溢出(或引导多次并平均统计量)。
在另一端,当排序后的数据集相同时,似乎某些步骤公式允许负值的可能性。本质上,这意味着统计量远偏左于临界值,表示完全匹配。

再次,显著性是通过外推计算的,但这次是从测试统计量向最小临界值外推,而不是像不匹配情况那样从最大临界值向测试统计量外推。由于统计量在左侧的相对大小刚好较小(我看到使用相同样本的统计量约为-1.3),相对于最小临界值(约为0.3),“仅仅”得到了约140%的外推结果,而不是指数级别的大数……但仍然看到1.4的显著性值表明数据只是超出了测试相关范围。

很可能是因为上面链接的那一行中从计算的检验统计量中减去“自由度”(degrees of freedom)的k-1。在双样本情况下,这意味着要减去1。因此,如果我们将1加回到您看到的检验统计量中,它会把您放在0.31范围内,这几乎等于最低临界值 (这是您期望的完全相同数据,这意味着您甚至不能在最弱的显著性水平下拒绝原假设)。所以很可能是自由度调整使它处于负极端,然后通过hacky基于二次方的p值外推来放大。

这是一个很棒的回答@ely!您有什么建议可以解决这个问题的最有效/优雅的方式吗?您提出了一种引导分析方法,但为了使其更加健壮,我认为我需要使用多个引导分析,这可能会相当麻烦。负值怎么办?如果为负数,则将其设置为0?也许最好创建一个Github问题? - michael
对于负值,您可以将 k-1 添加回该值(k 将是传递给测试的单独样本数),并自行执行关于临界值的外推。 您需要使用几个较小样本大小的引导程序,但这是一个相对廉价的计算,因此我认为即使在较小的数据上进行50或100次重复计算也是可以的。 确保您还跨引导聚合了临界值本身(平均值 可能 是可以的,但如果您需要某种顺序统计量,则应进行检查)。 - ely
1
我不知道 OP 使用的是哪个版本的 scipy,但在版本 1.1.0 中,AD 测试不会崩溃,而是返回:Anderson_ksampResult(statistic=202.74793118968645, critical_values=array([0.325, 1.226, 1.961, 2.718, 3.752]), significance_level=inf)。在 1.2.0 版本中,这似乎已经被修改了,最大 p 值为 1。 - Gabriel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接