2010-10-24 5 views
2

J'essaye d'écrire un test de bonté de l'ajustement de bêta pour la distribution bêta à partir de rien, sans utiliser de fonctions externes. Le code ci-dessous signale '1' pour un ajustement, même si kstest de scipy.stats renvoie un zéro. Les données sont distribuées normalement, donc ma fonction devrait aussi retourner zéro.Test du Chi carré en utilisant les fréquences, les bins, le CDF, le 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 

Dans le code, je crée des bacs, des fréquences de mesure sur la base des bacs, calculer la fréquence attendue en utilisant la distribution Beta CDF et résumer pour résultat la statistique de test X^2.

L'appel kstest est

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

Qu'est-ce que je fais mal ici?

Merci,

+0

Quelle est la sortie actuelle? – Wok

+0

La sortie est '1' pour ma fonction et (0,97653486524680988, 0,0) pour l'appel kstest. – user423805

Répondre

0

problème a été la définition: ddl

dof = len (preds) -2

est le bon choix. De plus, j'ai dû réduire la taille de la boîte à 15 pour obtenir un résultat '0' constant. On sait que les tests de Chi^2 sont sensibles à la taille de la poubelle.

3

Je ne pense pas que votre réponse à votre propre question soit correcte, et il y a une série de problèmes dans vos codes.

Tout d'abord, selon votre implémentation, le dof calculé en utilisant len(counts)-2 est la même chose que len(preds)-2. Donc changer cela ne fait aucune différence. Deuxièmement, pour faire un test Chi^2 sur l'ajustement des paramètres, vous devez construire un certain nombre de classes qui sont MECE, ce qui signifie qu'il n'y a pas de chevauchement entre les classes et qu'elles couvrent toutes les valeurs possibles de X. Toutefois, en configurant vos bacs à l'aide du bins = np.linspace(0,10,bin_size), vous avez forcé le bac le plus à droite à s'arrêter à 10. Alors que la distribution gaussienne s'étend à inf. Il y a donc un risque que les nombres aléatoires que vous avez générés dépassent 10.

Mais cela pourrait être moins un problème par rapport à celui-ci: le nombre de comptes pour chaque bin est conventionnellement requis pour être au moins de 5. Cependant, en utilisant votre méthode pour compter les nombres tombant dans les bacs (ici vous avez fixé à 30 bacs) pourrait et a presque toujours des nombres inférieurs à 5, et même 0. 0 compte dans n'importe quel bac conduit à l'infini dans le calcul sum suivant, et cela pourrait donner un rejet, peu importe l'ajustement est bon ou mauvais. Et je pense que c'est pourquoi vous obtenez un 0 après avoir changé le dof pour être len(preds)-2, il vous arrive d'avoir au moins un 0 dans le compte de la poubelle.

Un autre problème est le calcul de Chi^2. Je pense que vous n'utilisez pas les fréquences, mais compte réel dans chaque bac:

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 

donc à la fois p et freq sont le nombre de comptes dans chaque catégorie, plutôt que les fréquences relatives. Mais je ne suis pas entièrement sûr de cela.

Enfin, la définition de dof est le nombre de cases - nombre de paramètres ajustés (ici 2) -1. Donc, si vous avez 10 bacs, dof = 10 - 2 - 1 = 7. Dans votre code c'est `200 - 2 = 198 '. Une distribution de chi^2 avec un tel dof est extrêmement aplatie, ce qui signifie que vous avez besoin d'une valeur de chi^2 extrêmement grande pour rejeter l'ajustement. C'est la raison pour laquelle vous obtenez 1 en utilisant votre code.

Questions connexes