# Activité 8 - Simulation d'échantillons d'une loi de Bernoulli¶

## Présentation de l'activité¶

- Références au programme :
  - Tronc commun de première de la voie technologique : simuler des échantillons de taille n d’une loi de Bernoulli de paramètre $p$ à partir d’un générateur de nombres aléatoires entre 0 et 1.
  - Tronc commun de première de la voie technologique : représenter par un histogramme ou par un nuage de points les fréquences de $1$ dans $N$ échantillons de taille n d’une loi de Bernoulli.
  - Tronc commun de première de la voie technologique : compter le nombre de valeurs situées dans un intervalle de la forme $[p-ks;p+ks]$ pour $k\in\{ 1,2,3\}$.
- Description : cette activité permet dans un premier temps de simuler un jeu à deux issues (gagner ou perdre). Dans un deuxième temps, on propose de calculer mathématiquement la probabilité de gagner $p$. Puis on simule $N$ échantillons de $n$ parties de ce jeu. On écrit alors un programme qui calcule la moyenne $m$ et l'écart-type $s$ de la série statistique constituée des fréquences de gagner observées sur chaque échantillon de $n$ parties. On observe la fluctuation de ces fréquences autour de $p$ et on compte la proportion des cas où ces fréquences sont situées dans un intervalle de la forme $[p-ks;p+ks]$ pour $k\in\{ 1,2,3\}$.

## Un jeu¶

On considère un jeu dans lequel on dispose d'un dé à six faces numérotées de $1$ à $6$ et d'une pièce ayant un côté Pile et un côté Face. Le dé est bien équilibré, en revanche la pièce a deux fois plus de chance de tomber sur Pile que sur Face. Dans ce jeu, on lance tout d'abord le dé et on lit le chiffre apparaissant sur la face supérieure.

- Si le $6$ apparaît, alors le joueur a gagné.
- Si un nombre impair apparaît, alors le joueur a perdu.
- Si le nombre $2$ ou $4$ apparaît, alors on lance la pièce. Si on obtient Pile, alors le joueur a gagné sinon, il a perdu.

## Simulation du dé¶

Pour simuler le dé, on utilise la fonction `randint` de la bibliothèque `random`. Cette fonction permet de générer aléatoirement, de manière équiprobable, un nombre entier compris entre deux bornes. Ce nombre correspond au numéro de la face du dé obtenu après un lancer.

L'instruction suivante permet l'importation de la fonction `randint` de la bibliothèque `random`.

In [1]:

    from random import randint

La fonction `simulDe` renvoie un nombre entier aléatoire compris entre $1$ et $6$.

In [2]:

    def simulDe():
    	return randint(1,6)

    simulDe()

Out[2]:

    2

## Simulation de la pièce¶

La simulation du lancer de la pièce utilise la fonction `random` de la bibliothèque `random`. Cette fonction renvoie un nombre de type flottant compris entre $0$ et $1$.

Importation de la fonction `random` de la bibliothèque `random`

In [3]:

    from random import random

La fonction `simulPiece` renvoie $1$ avec la probabilité $\frac{2}{3}$ et $0$ avec la probabilité $\frac{1}{3}$. Le $1$ correspond à l'obtention de Pile et le $0$ à l'obtention de Face.

In [4]:

    def simulPiece():
        X = random()
        if X < 2/3:
            return 1
        else:
            return 0

    simulPiece()

Out[4]:

    0

Suggestions pédagogiques

- Compléter un programme

  Le programme précédent étant fourni en remplaçant les lignes 3 et 6 par `if X...` et `return ...`, demander aux élèves de compléter les lignes 3 et 6.

- Tester plusieurs fois la fonction `simulPiece` et vérifier la cohérence des résultats.

- Mathématiques débranchées

  Montrer que la probabilité $p$ de gagner à ce jeu est égale à $\frac{7}{18}$.

## Simulation du jeu¶

Les fonctions précédentes permettent de simuler le jeu.

La fonction `jeu` simule une partie et renvoie 0 si le joueur a perdu et 1 s'il a gagné.

In [5]:

    def jeu():
    	X = simulDe()
    	if X == 6:
    		return 1
    	elif X==1 or X==3 or X==5:
    		return 0
    	else:
    		Y=simulPiece()
    		if Y==1:
    			return 1
    		else:
    			return 0

    jeu()

Out[5]:

    0

Suggestions pédagogiques

- Compléter un programme

  Le programme précédent étant fourni en remplaçant les lignes 3, 5, 9 et 12 par `if X...`, `elif ...`, `if Y==...` et `return ...`, demander aux élèves de compléter les lignes 3, 5, 9 et 12.

- Écrire un programme

  Écrire une fonction `simulPiece` simulant une partie.

## Simulation de $n$ parties¶

La fonction `frequence` prend en paramètre un entier naturel $n$ correspondant au nombre de parties jouées et renvoie la fréquence de succès au cours de ces parties.

In [6]:

    def frequence(n):
        nbSucces = 0
        for i in range(n):
           nbSucces = nbSucces+jeu()
        return nbSucces/n

    print(frequence(50))

    0.34

Suggestions pédagogiques

- Compléter un programme

  Le programme précédent étant fourni en remplaçant les lignes 2, 3, 4, 5, 6 et 7 par `nbSucces = ...`, `for i in range(...)`, `X = ...`, `if X==...`, `nbSucces = ...` et `return ...`, demander aux élèves de compléter les lignes 2, 3, 4, 5, 6 et 7.

- Écrire un programme

  Écrire une fonction `frequence` donnant la fréquence des parties gagnées sur $n$ parties simulées.

## Calcul des fréquences de succès sur $N$ échantillons de taille $n$¶

Il est maintenant possible de générer $N$ échantillons de taille $n$ et de calculer pour chacun d'eux la fréquence de succès.

La fonction `echantillonFrequence` prend en paramètres deux entiers $N$ et $n$. L'entier $N$ correspond au nombre d'échantillons et l'entier $n$ à la taille commune à tous ces échantillons. Elle renvoie une liste contenant les $N$ fréquences de succès calculées sur chacun des échantillons.

In [7]:

    def echantillonFrequence(N,n):
    	echantillon = []
    	for i in range(N):
    		echantillon.append(frequence(n))
    	return echantillon

Suggestions pédagogiques

- Compléter un programme

  Le programme précédent étant fourni en remplaçant la ligne 4 par `echantillon.append(...)`, demander aux élèves de compléter la ligne 4.

- Écrire un programme

  Écrire une fonction `echantillonFrequence` donnant une liste contenant les $N$ fréquences des $N$ parties de $n$ jeux.

Les instructions suivantes permettent l'importation des librairies graphiques.

In [8]:

    %matplotlib inline
    import matplotlib.pyplot as plt

Représentation du nuage de points et de l'histogramme des fréquences de 1 dans N échantillons simulant chacun $n$ parties du jeu.

In [9]:

    fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(15, 6))

    N=100
    n=50

    echantillon = echantillonFrequence(N,n)

    ax1.plot(echantillon,'bo')
    ax2.hist(echantillon,color = '#1e7fcb',edgecolor = 'red')
    plt.show()

Suggestions pédagogiques

- Tester le programme précédent en faisant varier $N$ et $n$. Comment semblent être réparties les valeurs ?

## Fluctuation d'échantillonnage¶

L'objectif est de montrer que, si les fréquences de succès correspondant aux différents échantillons fluctuent, cette fluctuation se fait autour de la probabilité $p$ et est contrôlée par l'écart-type de la distribution de ces fréquences.

### Calculs de moyenne et d'écart-type¶

La fonction `moyenne` a pour paramètre une liste de nombres et renvoie la moyenne de cette liste.

In [10]:

    def moyenne(L):
        n = len(L)
        s = 0
        for x in L:
            s = s + x
        return s/n

Suggestions pédagogiques

- Compléter un programme

  Le programme précédent étant fourni en remplaçant les lignes 2, 3 et 5 par `n = len(...)`, `s = ...`, et `s = ...`, demander aux élèves de compléter les lignes 2, 3 et 5.

- Écrire un programme :

  Écrire une fonction `moyenne` prenant une liste de nombres en paramètre et renvoyant la moyenne de la liste.

Les fonctions `variance` et `ecartType` prennent une liste de nombres en paramètre et renvoient respectivement la variance et l'écart-type de cette liste.

In [11]:

    def variance(L):
        n = len(L)
        s = 0
        for x in L:
            s = s + x**2
        return 1/n*s-moyenne(L)**2

    def ecartType(L):
        return variance(L)**(1/2)

Suggestions pédagogiques

- Compléter un programme :

  Le programme précédent étant fourni en remplaçant les lignes 3 et 5 par `s = ...` et `s = ...`, demander aux élèves de compléter les lignes 3 et 5.

- Écrire un programme :

  Écrire deux fonctions `variance` et `ecartType` prenant une liste de nombres en paramètre et renvoyant respectivement la variance et l'écart-type de la liste.

### Calcul des bornes¶

On cherche maintenant à écrire une fonction qui, à partir l'une liste, donne un intervalle centré sur sa moyenne et d'amplitude proportionnelle à son écart-type.

La fonction `bornes` prend en paramètres une liste `L` et un entier `k` et renvoie la liste des deux nombres $p-k \times s$ et $p+k \times s$, où $p$ est la probabilité de gagner, $s$ l'écart-type des valeurs de la liste `L` et $k$ un nombre entier (qui sera restreint à $1$, $2$ ou $3$).

In [12]:

    def bornes(L,k):
        p = 7/18
        s = ecartType(L)
        return [p-k*s,p+k*s]

Suggestions pédagogiques

- Compléter un programme :

  Le programme précédent étant fourni en remplaçant les lignes 2, 3 et 4 par `p = ...`, `s = ...` et `return ...`, demander aux élèves de compléter les lignes 2, 3 et 4.

- Écrire un programme

  Écrire la fonction `bornes`.

### Proportion d'éléments de la liste compris dans les différents intervalles¶

Nous allons maintenant calculer la proportion d'éléments de la liste appartenant à l'intervalle précédemment créé.

La fonction `propPoints` prend en paramètres une liste `L` et un entier `k` et renvoie la proportion des points de la liste compris entre $p-k \times s$ et $p+k \times s$, où $p$ est la probabilité de gagner, $s$ l'écart-type des valeurs de la liste `L` et $k$ un nombre entier.

In [13]:

    def propPoints(L,k):
        b,B = bornes(L,k)
        filtre = [x for x in L if x<=B and x>=b]
        return len(filtre)/len(L)

Suggestions pédagogiques

- Compléter un programme

  Le programme précédent étant fourni en remplaçant les lignes 2, 3 et 4 par `b,B = ...`, `filtre = [x for x in L if ... and ...]` et `return ...`, demander aux élèves de compléter les lignes 2, 3 et 4. .

- Écrire un programme

  Écrire la fonction `propPoints`.

- Tester la fonction `propPoints` pour des échantillons de différentes tailles. Que peut-on observer ?

## Étude de la fluctuation des fréquences¶

Cette partie est destinée à l'enseignant afin qu'il puisse montrer aux élèves comment fluctuent les différentes fréquences.

In [14]:

    fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(20, 6))

    N=100
    n=50

    echantillon = echantillonFrequence(N,n)

    i1,s1 =  bornes(echantillon,1)
    i2,s2 =  bornes(echantillon,2)
    i3,s3 =  bornes(echantillon,3)

    for i in range(3):
        print("La proportion de points entre [p-{0}*s,p+{0}*s] est ".format(i+1),propPoints(echantillon,i+1))

    ax1.plot(echantillon,'bo')
    ax1.plot([0,N],[i1,i1],'r--',label='k=1')
    ax1.plot([0,N],[s1,s1],'r--')
    ax1.plot([0,N],[i2,i2],'m-.',label='k=2')
    ax1.plot([0,N],[s2,s2],'m-.')
    ax1.plot([0,N],[i3,i3],'y:',label='k=3')
    ax1.plot([0,N],[s3,s3],'y:')
    ax1.legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0.)
    ax2.hist(echantillon,color = '#1e7fcb',edgecolor = 'red')
    plt.show()

    La proportion de points entre [p-1*s,p+1*s] est  0.63
    La proportion de points entre [p-2*s,p+2*s] est  0.96
    La proportion de points entre [p-3*s,p+3*s] est  1.0

## Convergence¶

Cette partie est destinée à l'enseignant. Elle illustre la convergence vers $p$, lorsque $n$ tend vers l'infini, des fréquences de succès calculées sur des échantillons simulés de taille $n$ d'une loi de Bernoulli de paramètre $p$.

In [15]:

    def cumul(n):
        X = []
        F = []
        for i in range(n):
            X.append(jeu())
            F.append(sum(X)/(i+1))
        return F
    n=200
    F = cumul(n)
    p = 7/18
    plt.plot([0,n],[p,p],'r')
    plt.plot(F)
    plt.show()

## Animation susceptible d'être présentée aux élèves¶

Cette partie est destinée à l'enseignant pour illustrer son cours.

In [19]:

    import matplotlib.pyplot as plt
    import matplotlib.animation
    from IPython.display import HTML

    #cte
    n=200
    p = 7/18

    #paramètres figure
    fig, ax1 = plt.subplots(1, 1,figsize=(10, 4))

    #probabilité théorique
    F = cumul(n)
    lim = max(F)
    points, = ax1.plot([],[])
    ax1.plot([0,n],[p,p],'r')
    ax1.set_ylim((0, lim+.1))

    def init():
        return (points,)

    def animate(i):
        global F
        points.set_data(list(range(i+1)), F[:i+1])
        return (points,)

    plt.close ()
    ani = matplotlib.animation.FuncAnimation(fig, animate, frames=n,init_func=init,blit=True,interval=75)
    # l'un ou l'autre
    HTML(ani.to_jshtml())
    #HTML(ani.to_html5_video())

Out[19]:
Once Loop Reflect

## Animation susceptible d'être présentée aux élèves¶

Cette partie est destinée à l'enseignant pour illustrer son cours.

In [21]:

    import matplotlib.pyplot as plt
    import matplotlib.animation
    from IPython.display import HTML

    #cte
    N=50
    n=40
    p = 7/18
    pause = 30

    echantillon = echantillonFrequence(N,n)
    i1,s1 =  bornes(echantillon,1)
    i2,s2 =  bornes(echantillon,2)
    i3,s3 =  bornes(echantillon,3)

    #paramètres figure
    fig, ax1 = plt.subplots(1,figsize=(10, 6))

    #ax1.plot(echantillon,'bo')
    ax1.plot([0,N],[p,p],'r',label='p')
    bi1, = ax1.plot([],[],'g--',label='k=1')
    si1, = ax1.plot([],[],'g--')
    bi2, = ax1.plot([],[],'m-.',label='k=2')
    si2, = ax1.plot([],[],'m-.')
    bi3, = ax1.plot([],[],'y:',label='k=3')
    si3, = ax1.plot([],[],'y:')
    ax1.set_xlim((0, N))
    ax1.set_ylim((.1,.7))

    points, = ax1.plot([],[],'bo')

    def init():
        points.set_data([], [])
        return (points,)

    def animate(i):
        global echantillon
        if i>=N:
            bi1.set_data([0,N],[i1,i1])
            si1.set_data([0,N],[s1,s1])
            bi2.set_data([0,N],[i2,i2])
            si2.set_data([0,N],[s2,s2])
            bi3.set_data([0,N],[i3,i3])
            si3.set_data([0,N],[s3,s3])
            return (points,)
        points.set_data([range(i+1),echantillon[:i+1]])
        return (points,)
    ax1.legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0.)
    plt.close ()
    ani = matplotlib.animation.FuncAnimation(fig, animate, frames=N+pause,init_func=init,blit=True)
    # l'un ou l'autre
    HTML(ani.to_jshtml())
    #HTML(ani.to_html5_video())

Out[21]:
Once Loop Reflect
Remarques

Le programme de première technologique comporte deux commentaires sur l'écart-type des échantillons :

- On constate que la série des fréquences observées des $1$ dans $N$ échantillons de taille $n$ d’une loi de Bernoulli a un écart-type de l’ordre de $\frac{1}{\sqrt{n}}$
- Pour plusieurs valeurs de $n$ on représente $\frac{1}{\sqrt{n}}$ en abscisse et, en ordonnée, l’écart-type $s$ des fréquences observées des $1$ dans $N$ échantillons (plusieurs centaines) de taille $n$ . On peut commenter ce résultat en observant que pour diviser la dispersion par $k$ il faut multiplier la taille de l’échantillon par $k^2$.

À partir de cette activité, il serait également possible d'inclure ces parties du programme en générant les écarts-types de chaque échantillon en fonction de leur taille.