使用频率、BIN、CDF和Python的卡方检验

使用频率、BIN、CDF和Python的卡方检验,python,statistics,Python,Statistics,我试图从头开始为Beta分布编写一个卡方拟合优度测试,而不使用任何外部函数。下面的代码报告适合的“1”,即使scipy.stats中的kstest返回零。数据是正态分布的,所以我的函数也应该返回零 import numpy as np from scipy.stats import chi2 from scipy.stats import beta from scipy.stats import kstest from scipy.stats import norm preds = norm.

我试图从头开始为Beta分布编写一个卡方拟合优度测试,而不使用任何外部函数。下面的代码报告适合的“1”,即使scipy.stats中的kstest返回零。数据是正态分布的,所以我的函数也应该返回零

import numpy as np
from scipy.stats import chi2
from scipy.stats import beta
from scipy.stats import kstest
from scipy.stats import norm

preds = norm.rvs(5,2,size=200)
preds.sort()

bin_size = 30
bins = np.linspace(0,10,bin_size)
counts = np.digitize(preds, bins)
mean = 5
var = 2

sum = 0
for i in range(len(bins)-1):
    p = beta.cdf(bins[i+1], mean, var) - beta.cdf(bins[i], mean, var)  
    freq = len(counts[counts==i]) / float(len(counts))    
    sum = sum + ((freq - p)**2)/p

dof = len(counts)-2
pval = 1 - chi2.cdf(sum, dof)
print pval
在代码中,我创建了容器,根据容器测量频率,使用Beta分布CDF计算预期频率,并将其相加,得到X^2测试统计数据

kstest调用是

print kstest(preds, 'beta', [mean, var])
我做错了什么


谢谢,

问题在于DOF定义:

dof=长度(preds)-2


这是正确的选择。此外,为了得到一致的“0”结果,我必须将垃圾箱大小减少到15。众所周知,Chi^2测试对料仓尺寸非常敏感

我认为您对自己问题的回答不正确,而且您的代码中存在一系列问题

首先,根据您的实现,使用
len(counts)-2
计算的dof与
len(preds)-2
相同。所以改变这一点没有任何区别

其次,要对参数拟合进行Chi^2测试,您需要构造多个MECE的箱子,这意味着箱子之间没有重叠,它们共同跨越
X
的所有可能值。但是,通过使用
bins=np.linspace(0,10,bin_size)
设置您的箱子,您强制最右边的箱子停在
10
。而高斯分布的范围是-inf到inf。因此,您生成的随机数有可能超过
10

但与此相比,这可能不是什么问题:按照惯例,每个箱子的计数数至少必须为5。然而,使用您的方法来计算落入垃圾箱中的数字(这里您设置为30个垃圾箱)可能并且实际上几乎总是数字低于5,甚至0。任何箱子中的0个计数都会导致后续的
求和
计算结果为无穷大,这可能会导致拒绝,无论拟合是好是坏。我认为这就是为什么在将dof更改为
len(preds)-2
后,会得到一个0,只是碰巧在箱子计数中至少有一个0

另一个问题是Chi^2的计算。我认为您不使用频率,而是使用每个箱子中的实际计数:

p = beta.cdf(bins[i+1], mean, var) - beta.cdf(bins[i], mean, var)  
p = p*200
freq = len(counts[counts==i])    
sum = sum + ((freq - p)**2)/p
因此
p
freq
都是每个类别中的计数数,而不是相对频率。但我对此并不完全确定

最后,自由度的定义是箱数-参数拟合数(此处为2)-1。
所以如果你有10个箱子,
dof=10-2-1=7
。在您的代码中,这是'200-2=198'。具有如此大自由度的chi^2分布非常平坦,这意味着您需要非常大的chi^2值来拒绝拟合。这就是使用代码得到1的原因。

我的函数的输出为“1”,kstest调用的输出为(0.97653486524680988,0.0)。