2010-10-24 1 views
2

Я пытаюсь написать тест доброкачественности чи-квадрата для бета-распространения с нуля, без каких-либо внешних функций. Код ниже сообщает «1» для подгонки, хотя kstest из scipy.stats возвращает ноль. Данные распределяются нормально, поэтому моя функция также должна возвращать ноль.Тест Квай-Квадрата с использованием частот, бинов, 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 

В коде, я создаю бункеры, частоты мера, основанная на бункерах, рассчитать ожидаемую частоту с помощью бета-распределения CDF и подвести его в результате X^2 тестовой статистики.

Вызов kstest является

print kstest(preds, 'beta', [mean, var]) 

Что я здесь делаю неправильно?

Спасибо,

+0

Каков текущий выход? – Wok

+0

Вывод «1» для моей функции и (0.97653486524680988, 0.0) для вызова kstest. – user423805

ответ

0

проблема была с DOF определения:

ФО = LEN (Preds) -2

является правильным выбором. Кроме того, мне пришлось сократить размер бункера до 15, чтобы получить согласованный результат «0». Известно, что тесты Chi^2 чувствительны к размеру бункера.

3

Я не думаю, что ваш ответ на ваш вопрос правильный, и в ваших кодах есть ряд проблем.

Во-первых, согласно вашей реализации, DOF, рассчитанная с использованием len(counts)-2, - это то же самое, что и len(preds)-2. Так что изменение этого не имеет никакого значения.

Во-вторых, чтобы выполнить тест Chi^2 по параметру fit, вам нужно построить несколько ячеек, которые являются MECE, что означает отсутствие перекрытия между ячейками, и они совместно охватывают все возможные значения X. Однако, установив свои бункеры с помощью bins = np.linspace(0,10,bin_size), вы заставили крайний правый бит остановиться на 10. В то время как распределение Гаусса распространяется на inf. Таким образом, есть вероятность, что случайные числа, которые вы создали, снимают за 10.

Но это может быть меньше проблемы по сравнению с этим: количество отсчетов для каждого бункера обычно должно быть как минимум 5. Однако, используя ваш метод для подсчета чисел, попадающих в бункеры (здесь вы устанавливаете 30 бункеров), может и фактически почти всегда иметь числа ниже 5, и даже 0. 0 отсчетов в любом бине приводит к бесконечности в последующем вычислении sum и что может дать отказ, независимо от того, подходит ли это хорошо или плохо. И я думаю, именно поэтому вы получаете 0 после изменения dof, чтобы быть len(preds)-2, у вас просто есть как минимум один 0 в подсчетах bin.

Другой проблемой является расчет 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 являются число отсчетов в каждой категории, а не относительных частот. Но я не совсем уверен в этом.

И, наконец, определение dof - количество ячеек - количество параметров, соответствующих (здесь 2) -1. Итак, если у вас есть 10 бункеров, dof = 10 - 2 - 1 = 7. В вашем коде это `200 - 2 = 198 '. Распределение chi^2 с такой большой степенью тяжести очень сплющено, что означает, что вам нужно очень большое значение chi^2, чтобы отклонить соответствие. Вот почему вы получаете 1, используя свой код.

Смежные вопросы