29

正規性をテストしたいN個の数値のデータセットがあります。scipy.stats にkstest 関数があることは知っています が、その使用方法と結果の解釈方法に関する例はありません。ここに詳しい人で、アドバイスをくれる人はいますか?

ドキュメントによると、kstest を使用すると、KS 検定統計量 D と p 値の 2 つの数値が返されます。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')

次の出力が得られます。

(0.04957880905196102、8.9249710700788814e-22)

p 値は 5% 未満です。これは、データが正規分布しているという仮説を棄却できることを意味します。しかし、サンプルは正規分布から抽出されました!

誰かがここでの不一致を理解して説明できますか?

(正規性のテストでは、mu = 0 および sigma = 1 を想定していますか? もしそうなら、データがガウス分布であるが、異なる mu と sigma を使用していることをどのようにテストできますか?)

4

4 に答える 4

26

あなたのデータは、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)

データがガウスであることをテストするには、シフトして再スケーリングして、平均 0 と標準偏差 1 で正常になるようにします。

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

警告: ( user333700 (別名 scipy 開発者Josef Perktoldmu ) に感謝します)およびがわからない場合sigma、パラメーターを推定すると 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))     

版画

20/100000 = 0.00 rejects at rejection level 0.05 (not expected)

stats.kstestこれは、サンプルの平均と標準偏差を使用してサンプルが正規化されている場合、帰無仮説の予想数を棄却できない可能性があることを示しています

normed_data = (data - data.mean()) / data.std()    # this is NOT okay
于 2011-10-26T15:04:11.913 に答える
13

unutbu の回答の更新:

位置と縮尺のみに依存し、形状パラメーターを持たない分布の場合、いくつかの適合度検定統計量の分布は、位置と縮尺の値に依存しません。分布は標準的ではありませんが、基になる分布の任意の場所と規模で表にして使用することができます。

位置と縮尺が推定された正規分布の Kolmogorov-Smirnov 検定は、Lilliefors 検定とも呼ばれます。

関連する決定範囲のおおよその p 値とともに、statsmodels で利用できるようになりました。

>>> 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)

ほとんどのモンテカルロ研究では、Anderson-Darling 検定が Kolmogorov-Smirnov 検定よりも強力であることが示されています。これは、重要な値を持つ scipy.stats と、おおよその p 値を持つ statsmodels で利用できます。

>>> sm.stats.normal_ad(x)
(0.23016468240712129, 0.80657628536145665)

どちらの検定も、標本が正規分布しているという帰無仮説を棄却しません。問題の kstest は、サンプルが標準正規分布であるという帰無仮説を棄却します。

于 2014-03-03T00:59:44.817 に答える
1

@unutbu による回答の補足として、kstest でテスト分布の分布パラメーターを提供することもできます。変数からいくつかのサンプルがあり (そしてそれらに datax という名前を付けました)、それらのサンプルが対数正規、一様、または正規から得られない可能性があるかどうかを確認したいとします。scipy stats では、分布ごとに入力パラメーターが取得される方法が少し異なることに注意してください。kstest の "args" (タプルまたはシーケンス) のおかげで、テスト対象の scipy.stats ディストリビューションに引数を提供できます。

:) どちらの方法でもやりたい場合に備えて、2 サンプル テストを使用するオプションも追加しました。

import numpy as np
from math import sqrt
from scipy.stats import kstest, ks_2samp, lognorm
import scipy.stats

def KSSeveralDists(data,dists_and_args,samplesFromDists=100,twosampleKS=True):
    returnable={}
    for dist in dists_and_args:
        try:
            if twosampleKS:
                try:
                    loc=dists_and_args[dist][0]
                    scale=dists_and_args[dist][1]
                    expression='scipy.stats.'+dist+'.rvs(loc=loc,scale=scale,size=samplesFromDists)'
                    sampledDist=eval(expression)
                except:
                    sc=dists_and_args[dist][0]
                    loc=dists_and_args[dist][1]
                    scale=dists_and_args[dist][2]
                    expression='scipy.stats.'+dist+'.rvs(sc,loc=loc,scale=scale,size=samplesFromDists)'
                    sampledDist=eval(expression)
                D,p=ks_2samp(data,sampledDist)
            else:
                D,p=kstest(data,dist,N=samplesFromDists,args=dists_and_args[dist])
        except:
            continue
        returnable[dist]={'KS':D,'p-value':p}
    return returnable

a=lambda m,std: m-std*sqrt(12.)/2.
b=lambda m,std: m+std*sqrt(12.)/2.
sz=2000

sc=0.5 #shape 
datax=lognorm.rvs(sc,loc=0.,scale=1.,size=sz)
normalargs=(datax.mean(),datax.std())

#suppose these are the parameters you wanted to pass for each distribution
dists_and_args={'norm':normalargs,
               'uniform':(a(*normalargs),b(*normalargs)),
               'lognorm':[0.5,0.,1.]
              }
print "two sample KS:"
print KSSeveralDists(datax,dists_and_args,samplesFromDists=sz,twosampleKS=True)
print "one sample KS:"
print KSSeveralDists(datax,dists_and_args,samplesFromDists=sz,twosampleKS=False)

次のような出力が得られます。

2 つのサンプル KS: {'lognorm': {'KS': 0.0234999999999999965, 'p-value': 0.63384188886455217}, 'norm': {'KS': {'KS': 0.1060000000000004, 'p-value': 2.91876form666672310},'uni-15e ': {'KS': 0.15300000000000002, 'p 値': 6.443660021191129e-21}}

1 つのサンプル KS: {'lognorm': {'KS': 0.01763415915126032, 'p-value': 0.56275820961065193}, 'norm': {'KS': 0.10792612430093562, 'p-value': 0.0}, 'uniform': { 「KS」: 0.14910036159697559、「p 値」: 0.0}}

注: scipy.stats の一様分布の場合、a と b は a=loc および b=loc + スケールと見なされます (ドキュメントを参照)。

于 2016-10-26T09:05:02.600 に答える