在python scipy中实现Kolmogorov Smirnov测试

Hoo*_*voo 24 python statistics scipy

我有N个数据的数据集,我想测试其正常性.我知道scipy.stats有一个kstest函数, 但是没有关于如何使用它以及如何解释结果的例子.有人在这里熟悉它可以给我一些建议吗?

根据文档,使用kstest返回两个数字,KS检验统计量D和p值.如果p值大于显着性水平(比如说5%),那么我们就不能拒绝数据来自给定分布的假设.

当我通过从正态分布中绘制10000个样本并测试高斯度来进行测试运行时:

import numpy as np
from scipy.stats import kstest

mu,sigma = 0.07, 0.89
kstest(np.random.normal(mu,sigma,10000),'norm')
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

(0.04957880905196102,8.9249710700788814e-22)

p值小于5%,这意味着我们可以拒绝数据正态分布的假设.但样品来自正态分布!

有人能理解并向我解释这里的差异吗?

(正常性测试是假设μ= 0且sigma = 1?如果是这样,我如何测试我的数据是高斯分布但具有不同的mu和sigma?)

unu*_*tbu 23

您的数据生成时mu = 0.07,sigma = 0.89.您正在针对正态分布测试此数据,平均值为0,标准差为1.

零假设(H0)是您的数据是样本的分布等于标准正态分布,均值为0,标准偏差为1.

小的p值表示与概率p值一起预期与D一样大的检验统计量.

换句话说,(p值~8.9e-22)很可能H0是真的.

这是合理的,因为平均值和标准偏差不匹配.

将您的结果与:

In [22]: import numpy as np
In [23]: import scipy.stats as stats
In [24]: stats.kstest(np.random.normal(0,1,10000),'norm')
Out[24]: (0.007038739782416259, 0.70477679457831155)
Run Code Online (Sandbox Code Playgroud)

要测试您的数据是高斯数据,您可以移动并重新调整它以使其正常,均值为0且标准偏差为1:

data=np.random.normal(mu,sigma,10000)
normed_data=(data-mu)/sigma
print(stats.kstest(normed_data,'norm'))
# (0.0085805670733036798, 0.45316245879609179)
Run Code Online (Sandbox Code Playgroud)

警告:(非常感谢user333700(又名SciPy的开发商约瑟夫Perktold))如果你不知道musigma,估计参数使得p值无效:

import numpy as np
import scipy.stats as stats

mu = 0.3
sigma = 5

num_tests = 10**5
num_rejects = 0
alpha = 0.05
for i in xrange(num_tests):
    data = np.random.normal(mu, sigma, 10000)
    # normed_data = (data - mu) / sigma    # this is okay
    # 4915/100000 = 0.05 rejects at rejection level 0.05 (as expected)
    normed_data = (data - data.mean()) / data.std()    # this is NOT okay
    # 20/100000 = 0.00 rejects at rejection level 0.05 (not expected)
    D, pval = stats.kstest(normed_data, 'norm')
    if pval < alpha:
        num_rejects += 1
ratio = float(num_rejects) / num_tests
print('{}/{} = {:.2f} rejects at rejection level {}'.format(
    num_rejects, num_tests, ratio, alpha))     
Run Code Online (Sandbox Code Playgroud)

版画

20/100000 = 0.00 rejects at rejection level 0.05 (not expected)
Run Code Online (Sandbox Code Playgroud)

这表明,stats.kstest如果使用样本的均值和标准差对样本进行标准化,则可能不会拒绝预期的无效假设数

normed_data = (data - data.mean()) / data.std()    # this is NOT okay
Run Code Online (Sandbox Code Playgroud)

  • Kolmogorov-Smirnov检验假设不估计参数.如果规范化或使用估计参数,则kstest的p值不正确.如果你只是想测试数据是否正常分布,无论mu和sigma是什么,那么我会推荐其他测试. (7认同)

Jos*_*sef 12

unutbu答案的最新消息:

对于仅依赖于位置和比例但没有形状参数的分布,几个拟合优度检验统计量的分布与位置和比例值无关.分发是非标准的,但是,它可以制表并与基础分布的任何位置和比例一起使用.

具有估计位置和尺度的正态分布的Kolmogorov-Smirnov检验也称为Lilliefors检验.

它现在在statsmodels中可用,具有相关决策范围的近似p值.

>>> import numpy as np
>>> mu,sigma = 0.07, 0.89
>>> x = np.random.normal(mu, sigma, 10000)
>>> import statsmodels.api as sm
>>> sm.stats.lilliefors(x)
(0.0055267411213540951, 0.66190841161592895)
Run Code Online (Sandbox Code Playgroud)

大多数蒙特卡罗研究表明,Anderson-Darling测试比Kolmogorov-Smirnov测试更强大.它在具有临界值的scipy.stats中可用,在具有近似p值的statsmodel中可用:

>>> sm.stats.normal_ad(x)
(0.23016468240712129, 0.80657628536145665)
Run Code Online (Sandbox Code Playgroud)

两个测试都没有拒绝Null假设,即样本是正态分布的.虽然问题中的最新部分拒绝了Null假设,即样本是标准的正态分布.