Data science : Les tests de Kolmogorov-Smirnov et Lilliefors
Les tests de Kolmogrov-Smirnov(KS) et Lilliefors(LF) sont certainement les tests les plus populaires lorsqu’il s’agit de tester la normalité d’un échantillon. Comme nous l’avons vu dans le premier article Data science : Droite de Henry, ces tests ne sont pas seulement réservés à la loi normale, la normalité n’étant qu’un cas particulier. Pour être plus précis, ils permettent de tester si un échantillon provient d’une distribution continue. Le test de Lilliefors, en particulier, ne s’applique qu’à trois distributions continues : Normale, Exponentielle et Uniforme.
La différence principale entre ces deux tests est qu’on utilise le test de KS lorsque les paramètres de la distribution sont connus, et le test de LF lorsqu’ils ne sont pas connus mais estimés grâce à l’échantillon.
Ces tests sont implémentés sous scipy (kstest) et openturns(Fittingtests.Kolmogrov, Fittingtests.Lilliefors) ou encore statsmodels(statsmodels.stats.diagnostic.lilliefors).
Un peu de théorie
Supposons que nous ayons une série de n mesures telle que :
Test de KS
On a recourt au test de KS lorsqu’on veut vérifier si la série de mesure proviendrait d’une certaine distribution continue, entièrement déterminée. Sa fonction de répartition est appelée fonction hypothèse. En particulier, il peut s’agir d’une loi normale, qui est entièrement déterminée par ses deux paramètres : sa moyenne et son écart-type . C’est ce qui nous intéresse.
Soient la fonction de répartition d’une loi normale (la fonction hypothèse) et la fonction de répartition empirique de nos données , . La statistique de test est définie par :
.
Les hypothèses du test sont :
- H0 : pour tout (Nos données suivent une loi normale)
- H1 : pour au moins un donné (nos données ne suivent pas une loi normale)
Test de LF
Ce test est une modification du KS test. Ici on suppose que les moments de la distribution sont inconnus. Il faut donc les estimer à partir des données.
Soient la fonction de répartition des données et celle d’une variable suivant une loi normale avec comme moyenne (moyenne empirique estimée sur les données) et comme écart-type (écart-type corrigé estimé sur les données). La statistique de test du LF test est définie par :
.
Les hypothèses du test sont exactement les mêmes que pour le test KS.
En pratique
Exemple 1
Considérons un échantillon de taille provenant d’une loi normale.
En utilisant scipy et kstest, on a :
from scipy import stats stats.kstest(stats.norm.rvs, 'norm', N=100)
KstestResult(statistic=0.07438290129902819, pvalue=0.6107078771344361)
Sans surprise la p-value est d’environ et est bien plus élevée que le seuil de fixé par défaut dans scipy. On ne peut pas rejeter H0 au risque de .
Essayons maintenant avec statsmodels et lilliefors :
from statsmodels.stats.diagnostic import lilliefors import scipy.stats as stats n = 1000 mu = 2 sigma = 1.2 data = stats.norm.rvs(loc=mu, scale=sigma, size=n) statistic, p_value = lilliefors(data, 'norm') print("statistic =", statistic, '\n', "p_value =", p_value)
statistic = 0.015392333058231733 p_value = 0.8747119829450105
La p_value est d’environ donc logiquement plus grande que le seuil fixé par défaut . On ne rejette pas H0 avec un risque de .
Exemple 2
Considérons un échantillon provenant d’une loi normale standard. Nous utiliserons les options Fittingtests.Kolmogrov et Fittingtests.Lilliefors de openturns.
Avec Fittingtests.Kolmogrov :
import openturns as ot n = 1000 distribution = ot.Normal() data = distribution.getSample(n) threshold = 0.05 test = ot.FittingTest.Kolmogorov(data, distribution, threshold) print('Conclusion =', test.getBinaryQualityMeasure(), '\n', 'P-value =', test.getPValue())
Conclusion = True P-value = 0.5758608108872229
La méthode getBinaryQualityMeasure() compare automatiquement la p-value au seuil fixé et nous permet de conclure directement sur la normalité de l’échantillon. Bien entendu, le résultat du test nous indique que l’échantillon provient d’une distribution normale.
Avec Fittingtests.Lilliefors :
import openturns as ot n = 1000 distributionFactory = ot.NormalFactory() data = distribution.getSample(n) threshold = 0.05 dist, test = ot.FittingTest.Lilliefors(data, distributionFactory, threshold) print('Conclusion=', test.getBinaryQualityMeasure(), '\n', 'P-value=', test.getPValue(), '\n', 'dist_and_param =', dist)
Conclusion= True P-value= 0.8523809523809524 dist_and_param = Normal(mu = -0.0315476, sigma = 0.998111)
Comme précédemment, la méthode getBinaryQualityMeasure() nous permet de conclure directement sur la normalité de l’échantillon. Mais ici on peut aussi récupérer la distribution avec les paramètres estimés sur les données, qu’on affiche avec la variable dist_and_param.
C’est la fin de cet article dans lequel nous avons parcouru les tests de Kolgomorov-Smirnov et de Lilliefors. Nous verrons dans un prochain article le test de Shapiro-Wilk.
Laisser un commentaire