2010-10-24 26 views
2

我想從零開始編寫卡方擬合優度測試Beta版,而不使用任何外部函數。下面的代碼報告「1」表示適合,即使scstey中的kstest返回0也是如此。數據正常分配,所以我的函數也應該返回零。卡方測試使用頻率,箱,CDF,Python

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

我在做什麼錯在這裏?

謝謝,

+0

什麼是當前輸出? – Wok 2010-10-24 20:19:14

+0

對於我的功能,輸出爲'1',對於kstest調用,輸出爲(0.97653486524680988,0.0)。 – user423805 2010-10-24 20:42:20

回答

0

問題是與所述DOF的定義:

自由度= LEN(preds)-2

是正確的選擇。另外,爲了得到一致的'0'結果,我必須將bin大小減小到15。據瞭解,Chi^2測試對垃圾桶尺寸很敏感。

3

我不認爲你對自己問題的回答是正確的,並且你的代碼有一系列問題。

首先,根據您的實施情況,使用len(counts)-2計算得到的自由度與len(preds)-2是相同的。所以改變這並沒有什麼區別。其次,要對參數擬合進行Chi^2檢驗,需要構建MECE的多個分箱,這意味着分箱之間不存在重疊,它們共同涵蓋了所有可能的值X。但是,通過使用bins = np.linspace(0,10,bin_size)設置垃圾箱,您強制最右邊的垃圾箱在10處停止。高斯分佈跨越-inf到inf。所以有可能你生成的隨機數字超過10

但是,與此相比,這可能不是一個問題:每個箱的計數數量通常要求至少爲5。但是,使用您的方法來計算落入箱的數量(此處設置爲30個箱)並且實際上幾乎總是可以有小於5的數,並且甚至在任何箱中都有0個計數會導致在隨後的sum計算中無窮大,並且無論適合是好還是不好,這都會導致拒絕。而我認爲這就是爲什麼你在將自由度改爲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 

因此,無論pfreq是計數的每個類別的數量,而不是相對的頻率。但我對此並不完全確定。

最後,dof的定義是bin的個數 - 參數個數fit(這裏是2)-1。 所以,如果你有10個垃圾箱,dof = 10 - 2 - 1 = 7。在你的代碼中這是`200 - 2 = 198'。具有如此大的自由度的chi^2分佈非常平坦,這意味着需要非常大的chi^2值來拒絕擬合。這就是你使用你的代碼獲得1的原因。