I. Introduction▲
Une loi binomiale peut être utilisée pour modéliser des situations simples de succès ou échec, un jeu de pile ou face par exemple. Le calcul de sa fonction de masse devient rapidement fastidieux lorsque le nombre d'épreuves n est grand, il est alors possible d'utiliser des approximations par d'autres lois de probabilité telle que la loi normale et d'utiliser des tables de valeurs.
Après avoir défini ces lois de probabilité, on va ensuite montrer comment les représenter graphiquement en Python à l'aide de la librairie matplotlib.
Enfin, on va créer une interface paramétrable Tkinter intégrant un graphique afin de montrer la convergence de loi binomiale vers la loi normale conformément au théorème de Moivre-Laplace.
II. Lois de probabilité▲
II-A. Loi binomiale▲
D'après Wikipédia, la loi binomiale est une loi de probabilité discrète décrite par deux paramètres : n le nombre d'expériences réalisées, et p la probabilité de succès. Pour chaque expérience appelée épreuve de Bernoulli, on utilise une variable aléatoire qui prend la valeur 1 lors d'un succès et la valeur 0 sinon. La variable aléatoire, somme de toutes ces variables aléatoires, compte le nombre de succès et suit une loi binomiale. Il est alors possible d'obtenir la probabilité de k succès dans une répétition de n expériences :
kitxmlcodelatexdvpP\left( X=k \right) = \binom{n}{k} p^{k} \left( 1-p \right)^{n-k}finkitxmlcodelatexdvpII-B. Loi normale▲
La loi normale est une loi de probabilité continue qui dépend de deux paramètres : son espérance, un nombre réel noté μ, et son écart-type, un nombre réel positif noté σ. La densité de probabilité de la loi normale d'espérance μ et d'écart-type σ est donnée par :
kitxmlcodelatexdvpf(x) = \frac{1}{\sigma\sqrt{2\pi}} \ e^{\textstyle -\frac{1}{2} {\left(\frac{x - \mu}{\sigma}\right)}^2}finkitxmlcodelatexdvpParmi les lois de probabilité, les lois normales prennent une place particulière grâce au théorème central limite. En effet, elles correspondent au comportement, sous certaines conditions, d'une suite d'expériences aléatoires similaires et indépendantes lorsque le nombre d'expériences est très élevé. Grâce à cette propriété, une loi normale permet d'approcher d'autres lois comme la loi binomiale et ainsi de modéliser de nombreuses études scientifiques comme des mesures d'erreurs ou des tests statistiques, en utilisant par exemple les tables de la loi normale centrée réduite.
III. Théorème de Moivre-Laplace▲
D'après Wikipédia, en théorie des probabilités, selon le théorème de Moivre-Laplace, si la variable Xn suit une loi binomiale d'ordre n et de paramètre p ϵ [0, 1], alors la variable :
kitxmlcodelatexdvpZ_n = \frac{X_n - np}{\sqrt{np\left( 1-p \right)}}finkitxmlcodelatexdvpconverge en loi vers une loi normale centrée et réduite N(0, 1). Cette approximation est bonne en général pour np(1 − p) ≥ 10.
IV. Implémentation en Python▲
IV-A. Fonctions de probabilité▲
Les fonctions et les objets décrits par la suite sont issus du module scipy.stats.
IV-A-1. Fonction de masse de la loi binomiale▲
L'objet binom représente une variable aléatoire discrète suivant une loi binomiale qui est en fait une instance de la classe rv_discrete avec ses différentes méthodes.
La fonction de masse de la loi binomiale binom.ppf(x, n, p) peut être appelée comme ceci :
x =
10
; n =
100
; p =
0.5
val =
binom.ppf
(
x, n, p)
Traçons maintenant l'histogramme de la fonction avec la librairie matplotlib :
from
scipy.stats import
binom
import
matplotlib.pyplot as
plt
from
math import
sqrt
# nombre d'épreuves de Bernoulli
n =
80
# probabilité de succès
p =
0.5
# moyenne μ et écart-type σ de la loi binomiale
μ =
n*
p
σ =
sqrt
(
n*
p*(
1
-
p))
# génère la séquence des x : 0 -> n-1
x =
range(
n)
# nom et dimension de la figure contenant le graphique
plt.figure
(
num=
"Figure : Loi binomiale"
, figsize=(
8
, 5
), dpi=
80
)
# trace l'histogramme correspondant à la série de valeurs
plt.bar
(
x, binom.pmf
(
x,n,p), color=
"blue"
)
# limites sur l'axe des x : [μ - 4σ, μ + 4σ]
plt.xlim
(
μ -
4
*
σ, μ +
4
*
σ)
# limite inférieure sur l'axe des y
plt.ylim
(
0
)
plt.title
(
"Histogramme de la loi binomiale B({0}, {1})"
.format
(
n,p))
# affiche le graphique
plt.show
(
)
Le code affiche :
IV-A-2. Fonction de densité de la loi normale▲
L'objet norm représente une variable aléatoire continue suivant une loi normale qui est en fait une instance de la classe rv_continuous avec ses différentes méthodes.
La fonction de densité de la loi normale norm.pdf(x, loc=μ, scale=σ) d'espérance μ et d'écart-type σ peut être invoquée comme ceci :
x =
10
; μ =
50
; σ =
5
val =
norm.pdf
(
x, loc=
μ, scale=
σ)
Traçons maintenant la courbe représentative de la fonction :
from
scipy.stats import
norm
import
matplotlib.pyplot as
plt
from
math import
sqrt
# nombre d'épreuves de Bernoulli
n =
80
# probabilité de succès
p =
0.5
# moyenne μ et écart-type σ de la loi normale
μ =
n*
p
σ =
sqrt
(
n*
p*(
1
-
p))
# génère la séquence des x : 0 -> n-1
x =
range(
n)
# nom et dimension de la figure contenant le graphique
plt.figure
(
num=
"Figure : Loi normale"
, figsize=(
8
, 5
), dpi=
80
)
# trace la courbe correspondant à la série de valeurs
plt.plot
(
x, norm.pdf
(
x,μ,σ), color=
"red"
)
# limites sur l'axe des x : [μ - 4σ, μ + 4σ]
plt.xlim
(
μ -
4
*
σ, μ +
4
*
σ)
# limite inférieure sur l'axe des y
plt.ylim
(
0
)
plt.title
(
"Courbe représentative de la loi normale N({0}, {1})"
.format
(
round(
μ,2
),round(
σ**
2
,2
)))
# affiche le graphique
plt.show
(
)
Le code affiche :
IV-B. Représentation graphique : intégration du graphique dans une interface Tkinter▲
Nous allons maintenant créer une interface paramétrable avec Tkinter sur laquelle nous allons pouvoir choisir le nombre d'expériences n et la probabilité de succès p de la loi binomiale, puis tracer le graphique des deux fonctions.
La classe tkinter.Tk permet de construire un widget Tk de niveau supérieur, qui est généralement la fenêtre principale d'une application, et initialise un interpréteur Tcl pour ce widget. Chaque instance a son propre interpréteur Tcl associé.
Notre interface est ainsi construite à l'aide d'une classe fille InterfaceGraphique qui hérite de la classe mère tkinter.Tk. On peut alors utiliser les attributs et méthodes de cette classe mère :
Au moment de créer l'interface Tkinter, c'est-à-dire quand la classe InterfaceGraphique(Tk) est instanciée, on met à jour les zones de texte, puis on trace les graphiques des deux fonctions :
from
tkinter import
*
from
matplotlib.figure import
Figure
from
matplotlib.backends.backend_tkagg import
FigureCanvasTkAgg
from
math import
sqrt
class
InterfaceGraphique
(
Tk):
def
__init__
(
self, n, p, pmf, pdf):
# instantiation de la classe parente
Tk.__init__
(
self)
# conteneur vertical occupant tout le formulaire et destiné à contenir le widget à canvas
verticalPane =
PanedWindow
(
self, orient=
VERTICAL )
# conteneur horizontal placé en haut du formulaire pour les différents contrôles du formulaire
horizontalPane =
PanedWindow
(
verticalPane, orient=
HORIZONTAL )
# création des labels et des zones de texte
lblNbreEpreuves =
Label
(
horizontalPane, text =
"Nombre d'épreuves (n) :"
)
self.txtNbreEpreuves=
Text
(
horizontalPane, height =
1
, width =
8
)
lblProbaSucces =
Label
(
horizontalPane, text =
"Proba de succès (p) :"
)
self.txtProbaSucces=
Text
(
horizontalPane, height =
1
, width =
8
)
lblMoyenne =
Label
(
horizontalPane, text =
"Moyenne (μ) :"
)
self.txtMoyenne=
Text
(
horizontalPane, height =
1
, width =
8
, bg=
"lightgray"
)
lblEcartType =
Label
(
horizontalPane, text =
"Ecart-type (σ) :"
)
self.txtEcartType =
Text
(
horizontalPane, height =
1
, width =
8
, bg=
"lightgray"
)
# création du bouton de commande pour générer le graphique sur l'interface Tkinter
btnTracer=
Button
(
horizontalPane, text=
"Tracer"
, command=
self.btnTracerClicked, width =
10
)
# ajout des contrôles au conteneur horizontal
horizontalPane.add
(
lblNbreEpreuves )
horizontalPane.add
(
self.txtNbreEpreuves )
horizontalPane.add
(
lblProbaSucces )
horizontalPane.add
(
self.txtProbaSucces )
horizontalPane.add
(
lblMoyenne )
horizontalPane.add
(
self.txtMoyenne )
horizontalPane.add
(
lblEcartType )
horizontalPane.add
(
self.txtEcartType )
horizontalPane.add
(
btnTracer )
# ajout du conteneur horizontal
verticalPane.add
(
horizontalPane )
verticalPane.pack
(
expand=
True
, fill=
'both'
)
# ajout de l'objet au conteneur vertical
verticalPane.pack
(
expand=
True
, fill=
'both'
)
# saisie des valeurs par défaut dans les zones de texte
self.txtNbreEpreuves.insert
(
END,n)
self.txtProbaSucces.insert
(
END,p)
# moyenne μ et écart-type σ de la loi binomiale et de la normale
μ =
n*
p
σ =
math.sqrt
(
n*
p*(
1
-
p))
# mise à jour des zones de texte correspondantes
self.txtMoyenne.insert
(
END,round(
μ,2
))
self.txtEcartType.insert
(
END,round(
σ,2
))
self.pmf =
pmf
self.pdf =
pdf
# trace le graphique
self.tracer
(
n, p, μ, σ)
def
tracer
(
self, n, p, μ, σ, new_graph=
False
):
# méthode permettant de tracer les graphiques sur l'interface
# génère la séquence des x : 0 -> n-1
x =
range(
n)
# on crée la figure du graphique pour les 2 séries de valeurs
fig =
Figure
(
figsize=(
8
, 5
), dpi=
96
)
plt =
fig.add_subplot
(
111
)
# trace l'histogramme et la courbe correspondant aux 2 séries de valeurs
plt.bar
(
x, self.pmf
(
x,n,p), color=
"blue"
, label =
"B({0}, {1})"
.format
(
n,p))
plt.plot
(
x, self.pdf
(
x,μ,σ), color=
"red"
, label =
"N({0}, {1})"
.format
(
round(
μ,2
),round(
σ**
2
,2
)))
# limites sur l'axe des x : [μ - 4σ, μ + 4σ]
plt.set_xlim
(
μ -
4
*
σ, μ +
4
*
σ)
# limite inférieure sur l'axe des y
plt.set_ylim
(
0
)
plt.set_title
(
"Représentation graphique de la loi binomiale et de la loi normale"
)
plt.legend
(
)
if
new_graph:
self.graph.get_tk_widget
(
).pack_forget
(
)
self.graph =
FigureCanvasTkAgg
(
fig, master=
self)
self.graph.get_tk_widget
(
).pack
(
)
Un bouton de commande btnTracerClicked permet ensuite de tracer le graphique en fonction des choix de paramètres n et p :
class
InterfaceGraphique
(
Tk):
...
def
btnTracerClicked
(
self):
# méthode qui s'exécute quand on clique sur le bouton de commande btnTracer
# copie du contenu des zones de texte dans des variables
n =
int(
self.txtNbreEpreuves.get
(
"1.0"
,'end-1c'
))
p =
float(
self.txtProbaSucces.get
(
"1.0"
,'end-1c'
))
# moyenne μ et écart-type σ de la loi binomiale et de la normale
μ =
n*
p
σ =
math.sqrt
(
n*
p*(
1
-
p))
# mise à jour des zones de texte correspondantes
self.txtMoyenne.delete
(
"1.0"
,'end-1c'
)
self.txtMoyenne.insert
(
END,round(
μ,2
))
self.txtEcartType.delete
(
"1.0"
,'end-1c'
)
self.txtEcartType.insert
(
END,round(
σ,2
))
# trace le graphique
self.tracer
(
n,p,μ,σ,True
)
Testons maintenant notre interface graphique :
from
scipy.stats import
binom, norm
from
interface_graphique import
InterfaceGraphique
# nombre d'épreuves de Bernoulli
n =
80
# probabilité de succès
p =
0.5
# création de l'objet InterfaceGraphique avec les paramètres : n, p, binom.pmf, norm.pdf
InterfaceGraphique =
InterfaceGraphique
(
n, p, binom.pmf, norm.pdf)
# ajout d'un titre à la fenêtre Tkinter
interface_graphique.title
(
"Interface graphique avec Tkinter"
)
# centre la fenêtre
InterfaceGraphique.eval(
'tk::PlaceWindow . center'
)
InterfaceGraphique.mainloop
(
)
Le code affiche :
Le graphique montre bien que la valeur en x de la fonction de densité de la loi normale représente une bonne approximation de la valeur en x de la fonction de masse de la loi binomiale pour n=80 et p=0.5.
IV-C. Module Python▲
On donne pour finir le code complet du module présent dans le fichier joint dossier_test.zipdossier de test :
V. Conclusion▲
Après avoir défini la loi binomiale et la loi normale, on a donc présenté le théorème de Moivre-Laplace comme un cas particulier du théorème central limite.
On a pu ensuite montrer comment représenter graphiquement ces lois à l'aide de la librairie matplotlib, et comment tracer leur graphique dans une interface Tkinter afin de vérifier que la loi binomiale converge bien vers la loi normale quand n augmente.
VI. Téléchargement▲
Le dossier de testdossier de test :
- interface_graphique.py : module contenant la classe InterfaceGraphique ;
- representation_graphique.py : module principal.
VII. Remerciements▲
Je tiens à remercier Malick pour le suivi de cet article, ainsi que f-leb pour sa relecture.
Sources
- https://fr.wikipedia.org/wiki/Loi_binomiale
- https://fr.wikipedia.org/wiki/Loi_normale
- https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_de_Moivre-Laplace
- https://fr.wikipedia.org/wiki/H%C3%A9ritage_(informatique)
- https://docs.scipy.org/doc/scipy/reference/stats.html
- https://matplotlib.org/
- https://docs.python.org/fr/3/library/tkinter.html