Simulation de variables aléatoires, loi des grands nombres

École Polytechnique Florent Benaych-Georges
Année 2 Stefano De Marco
Mathématiques Appliquées Stéphane Gaiffas
TP1 Emmanuel Gobet
MAP441 – Modal SNA Christelle Vergé
Simulation de variables aléatoires, loi des grands nombres, théorème central limite
1. Préambule
Dans le cadre de ce Modal nous utiliserons le langage python. Nous ferons appel intensivement aux librairies
numpy,scipy et matplotlib. Il s’agit de libraries permettant de faire très simplement du calcul matriciel, du
calcul scientifique, de la simulation, et des représentations graphiques. La syntaxe de ces librairies est similaire
à celle de Matlab. Nous les utiliserons pour faire du calcul numérique, en évitant quand cela est possible de faire
des boucles.
En appendice de ce document est donné un exemple de programme Python. Un coup d’oeil à ce programme
permettra un bon départ. Les élèves non encore familiers avec Python pourront (sans y passer trop de temps)
télécharger les programmes et "jouer avec" (les exécuter, puis changer certains paramètres pour voir l’effet
sur l’exécution). Les fichiers de ces programmes sont disponibles (comme le seront, tout au long du cours, les
corrigés des TP), à l’adresse http://www.cmap.polytechnique.fr/~gaiffas/teaching_X.html. Un tutoriel
plus détaillé que ce qui est décrit dans cet énoncé de TP est disponible à l’adresse
http://www.cmap.polytechnique.fr/~gaiffas/intro_python.html
Un fichier de script (ou fichier de module) en python est un fichier texte avec l’extension .py.On s’interdira
l’utilisation de caractères accentués dans un script python. Nous écrirons un script par question dans
les corrections.
1.1. Import de fonction, utilisation de librairies. Il y a un très grand nombre de librairires python, et ces
librairies contiennent beaucoup de fonctions. Pour pouvoir utiliser une fonction ou une classe dans une librairie,
il est nécessaire de l’importer dans chaque script avant de s’en servir, de préférence en début de script, mais
ça n’est pas obligatoire. Il y a plusieurs manières d’importer des fonctions en python. Dans l’exemple qui suit,
nous chargeons et utilisons la fonction randn qui permet de simuler une matrice avec des entrées gaussiennes
i.i.d. Nous le faisons de cinq façons différentes, mais la fonction randn importée est à chaque fois exactement la
même.
# Methode 1
from numpy.random import randn
X = randn(3, 3)
# Methode 2
import numpy
X = numpy.random.randn(3, 3)
# Methode 3 : on cree un alias de numpy.random que l’on appelle npr
import numpy.random as npr
X = npr.randn(3, 3)
# Methode 4 : on importe toute les fonction de numpy.random
from numpy.random import *
X = randn(3, 3)
# Methode 5 : on importe les fonctions les plus utilisees de numpy, scipy, matplotlib
from pylab import *
X = randn(3, 3)
# Pour importer plusieurs fonction d’une meme librairie
from numpy import ones, zeros, empty
La librairie pylab utilisée dans la cinquième méthode permet d’importer de façon concise toutes les fonctions les
plus courantes des librairies numpy,scipy et matplotlib. C’est cette méthode que nous utiliserons dans les TP.
Tous vos scripts devront donc commencer par la commande : from pylab import *
Il y aura quelques cas exceptionnels, où nous aurons besoin, dans un même script, de deux fonctions qui portent
le même nom mais qui sont différentes. Dans l’exemple suivant, nous utilisons deux fonctions s’appelant toutes
1
2
les deux poisson. La première fonction est dans numpy.random et permet de simuler des variables de loi de
Poisson, alors que la deuxième est dans scipy.stats et permet d’obtenir la valeur de la densité de probabilité
de la loi de Poisson.
from pylab import *
import numpy.random as npr
import scipy.stats as sps
mu = 0.5
n = 1000
m = 20
X = npr.poisson(mu, n) # Simulation de variables de loi de Poisson d’intensite mu
x = arange(m+1) # x contient le vecteur d’entiers [0, 1, 2, ..., m]
f = sps.poisson.pmf(x, mu) # Densite de probabilite de la loi de Poisson d’intensite mu aux points x
1.2. Remarques fondamentales sur python.Nous listons ici quelques remarques fondamentales sur python,
qui vont vous éviter de faire les erreurs les plus habituelles, et vous faire gagner du temps.
Par défaut, les objects en python ne sont pas copiés. Considérons l’exemple suivant
x = [4, 2, 10, 9, "toto"]
y=x # y est juste une reference au tableau x, pas de copie effectuee ici
y[2] = "tintin"
print x# Cela affiche [4, 2, "tintin", 9, "toto"]
x = [4, 2, 10, 9, "toto"]
y = x[:] # On demande une copie
y[2] = "tintin"
print x# Cela affiche [4, 2, 10, 9, "toto"]
L’indexation des tableaux commence a zéro : si x = [4, 3, 12] alors x[1] vaut 3.
La division est entière (dans python2). En effet la division 1/2est une division entière, et vaut donc
0, alors que 1. / 2 ou 1 / 2. donne bien 0.5
L’échange de deux variables aet bpeut se faire en une ligne, sans variable intermédiaire : a, b = b, a
L’indentation est fondamentale en python. Voici un exemple.
def fib(n):
"""Fonction qui calcule le n-ieme element de la suite de Fibonacci"""
a, b = 0, 1
for iin range(n):
a,b=b,a+b
return a
print fib(10) # donne 55
Tout le contenu de la fonction fib est indenté d’une tabulation. Tout le contenu de la boucle for
est également indenté d’une tabulation (donc deux en tout). La ligne return an’est pas dans la boucle
for, donc est indenté d’une tabulation en moins. La ligne print fib(10) est en dehors de la définition
de la fonction fib.
L’élevation à la puissance : x ** 2 calcule le carré du nombre x. Encore une fois, attention à la division
entière : 1000 ** (3/2) vaut 1. alors que 1000 ** (3/2.) vaut 464.158883361
La boucle for : si on veut faire varier un indice ientre 0et 10 (compris) on écrit for iin range(11):
Si on veut faire varier un indice ientre 2et 7(compris) on écrit for iin range(2, 8):
On peut itérer sur beaucoup de types d’objets python (on les appelle des iterable), par exemple :
X = [10., [1, 2, 3], "Bonjour", 4]
for xin X:
print x
# affiche successivement 10 puis [1, 2, 3] puis Bonjour puis 4
Déclaration d’une fonction. La déclaration d’une fonction python se fait avec le mot-clé def. On doit
déclarer en premier les paramètres sans valeurs par défaut, puis ceux avec une valeur par défauts. Les
paramètres avec une valeur par défaut sont nommés. On peut alors se servir du nom des paramètres
dans l’appel à la fonction. C’est plus clair sur un exemple :
def f(tata, toto=2, tintin=4):
print tata, toto, tintin
3
f(3) # affiche 3 2 4
f(3, 5, 12) # affiche 3 5 12
f(3, tintin=5, toto=12) # affiche 3 12 5
1.3. Calcul matriciel, la librarie numpy.Donnons un premier exemple de calcul numérique avec numpy.
Imaginons que l’on cherche une valeur approchée de la probabilité que le sinus d’une v.a. gaussienne standard
soit <1/2. On peut procéder comme cela :
from pylab import *
n = 1000
X = randn(n)
p = mean(sin(X) < 0.5)
print "Proba que sin(X) < 0.5 quand X est de loi N(0, 1)=", p
Quelques remarques fondamentales sur numpy:
Le premier élément d’un tableau numpy est indexé par 0. Si x = array([4, 1, 2]) alors x[0] contient
4.
Si xest un tableau numpy, alors y=xne fait pas une copie de xdans y(xet ysont deux noms pour le
même object). Pour avoir une copie, il faut utiliser y = x.copy(). Si on a deux tableaux numpy x et y
de même taille, alors y[:] = x copie le contenu de xdans y(pas de création mémoire).
arange(5) donne le tableau d’entiers [0, 1, 2, 3, 4]
Les valeurs dans un tableau numpy sont typées (int,float,double, etc.) et ont le même type (ce qui
n’est pas le cas d’un tableau python). La plupart des fonctions de numpy ont un argument optionnel
appelé dtype. Par exemple zeros((2, 3), dtype=int) donne une matrice de taille 2×3à valeurs entières,
alors que zeros((2, 3), dtype=double) donne une matrice à valeurs réelles (double précision). Le type
de valeurs dans un tableau numpy peut être très important, comme illustré dans l’exemple suivant.
from pylab import *
n=4
x = arange(n) # x contient [0, 1, 2, 3]
y=x/4 # y contient [0, 0, 0, 0], car c’est une division entiere
y = x / 4. # y contient [ 0. 0.25 0.5 0.75]
x = array(x, dtype=double)
y=x/4 # y contient [ 0. 0.25 0.5 0.75]
Si xest un tableau numpy alors x.shape donne sa dimension
ones((3, 4)) donne une matrice de taille 3×4qui ne contient que des 1 (par defaut réels)
zeros((3, 4)) donne une matrice de taille 3×4qui ne contient que des 0 (par defaut réels)
eye(4) donne la matrice identité de taille 4×4(qui contient par defaut des valeurs réelles)
ones(X.shape) donne une matrice de même taille que Xqui ne contient que des 1.
X.T est la matrice transposee de X
Les opérations +, -, *, /, **, +=, *=, /=, -=, etc. sont programmées de façon à être appliquées terme
à terme aux tableaux numpy. Par exemple, si Aet Bsont des matrices de même taille, alors A*Bcalcule
la matrice qui contient les produits terme à terme des matrices Aet B. Pour calculer le produit matriciel
entre Aet Bon utilise dot(A, B).
La plupart des fonctions mathématiques classiques sont programmées de façon matricielle. Si Xest une
matrice (ou vecteur) numpy, alors exp(X),sin(X), etc. correspondent aux applications des fonctions exp,
sin, etc. à chaque terme de X. De même, pour xun scalaire, X+xcorrespond à l’addition de xterme
à terme dans X.
Pour Xmatrice et aun scalaire, X<aest la matrice de même taille que Xoù les entrées sont remplacées
par des booléens True (=vrai) et des False (=faux) selon qu’elles soient ou non < a. Cela se généralise
à des opérations à valeurs booléennes plus compliquées (encadrements, ...) et permet souvent d’éviter
le recours à des boucles et/ou des tests.
from pylab import *
x = array([4, 2, 1, 5, 1, 10])
logical_and(x >= 3, x <= 9, x != 1) # vaut [ True False False True False False]
Les fonctions logical_and,logical_or,logical_not,logical_xor sont disponibles pour appliquer des
opérations logiques termes à terme des tableaux numpy
4
Il y a de nombreux générateurs de nombres aléatoires dans numpy.random :randn génère des gaussiennes
et rand des lois uniformes sur [0,1]. Toutes les lois classiques sont disponibles, cf http://docs.scipy.
org/doc/numpy/reference/routines.random.html
On peut construire une matrice par blocs, à partir de sous-matrices. Voici un exemple.
from pylab import *
A = array([[2, 1, 1], [4, 3, 0]])
B = array([[1, 2], [12, 0]])
C = array([[1, 2], [12, 0], [-1, 2]])
D = array([[1, 2, -4], [2, 0, 0], [1, 2, 3]])
print bmat([[A, B], [C, D]])
# affiche la matrice
# [[ 2 1 1 1 2]
# [ 4 3 0 12 0]
# [ 1 2 1 2 -4]
# [12 0 2 0 0]
# [-1 2 1 2 3]]
Beaucoup de fonctions de numpy ont un argument nommé axis. Par exemple sum(X, axis=1) calcule la
somme de chaque ligne de X,cumsum(X, axis=0) calcule la somme cumulée des colonnes de X.
1.4. Commandes principales de matplotlib.
plot(x, y) affiche la courbe affine par morceaux reliant les points d’abscisses xet d’ordonnée y
hist trace un histogramme. Il faut spécifier l’option normed=True pour afficher l’histogramme normalisé
(d’aire égale à 1).
bar trace un diagramme en bâton
scatter(x, y) affiche le nuage de points d’abscisses xet d’ordonnée y
stem(x, y) affiche des barres verticales en position xet de hauteur y
show() affiche les fenêtres créées dans le script
figure crée une nouvelle fenêtre graphique
title donne un titre à une figure
legend() affiche la légende d’un graphique
subplot subdivise la fenêtre graphique de façon à y afficher plusieurs graphiques dans la même figure
2. Simulation de variables aléatoires discrètes
2.1. Un exemple simple de loi discrète. On considère la loi Psur l’ensemble {1,2,3}donnée par les
probabilités P({1}) = 0.3,P({2}) = 0.6,P({3}) = 0.1. Simulez un grand nombre de v.a. i.i.d. de loi P, en
faire l’histogramme à l’aide des fonctions bincount et bar et comparer le résultat obtenu avec la représentation
en bâtons, sur le même graphique, de la loi P(que l’on obtient à l’aide de la fonction stem).
2.2. Les lois discrètes classiques.
(1) On considère B(n, p)la loi binomiale de paramètres n, p. Ecrire une procédure dans laquelle on simule
un grand nombre de v.a. de loi B(n, p)(avec la fonction binomial de numpy.random), faire l’histogramme
de l’échantillon obtenu et comparer avec la représentation en bâtons, sur le même graphique, de la loi
B(n, p)(que l’on obtient à l’aide de la fonction binom.pmf de scipy.stats).
(2) Faire de même avec une loi de Poisson (on utilisera la fonction poisson de numpy.random et la fonction
poisson.pmf de scipy.stats).
(3) Un calcul simple montre que lorsque ntend vers l’infini, la loi B(n, λ/n)tend vers la loi de Poisson de
paramètre λ. En pratique, on assimile B(n, p)à la loi de Poisson de paramètre np dès que np2<0.1.
Illustrer cette proximité de lois en affichant, sur le même graphique, leurs histogrammes en bâtons (sans
faire aucune simulation).
3. Simulation de variables aléatoires continues (1)
(1) Simuler un grand nombre de variables aléatoires gaussiennes standard, représenter l’histogramme associé
et comparer à la densité gaussienne. Faire de même avec des variables aléatoires de loi gamma. On
utilisera les fonctions randn, linspace, hist, plot et la fonction norm.pdf de la librairie scipy.stats
(2) Un des programmes donnés dans le tutoriel joint illustre la propriété d’absence de mémoire de la loi
exponentielle : si Xsuit une telle loi, alors pour tout t > 0, la loi de Xtsachant X > t est la loi de
X. Charger ce programme, l’exécuter, et faire la même expérience en remplaçant la loi exponentielle
par des (autres) lois gamma. A-t-on encore absence de mémoire ? On utilisera la fonction gamma de
numpy.random et la fonction gamma.pdf de scipy.stats
5
4. Programmation matricielle
4.1. Motivation. En python, la programmation matricielle proposée dans numpy est plus rapide que celle re-
posant sur des boucles. Le programme suivant compare le calcul d’une valeur approchée du nombre γ
Pn
i=1 1
iln(n)pour n1en programmation matricielle et via une boucle. Le récupérer à l’adresse http:
//www.cmapx.polytechnique.fr/~benaych/MODAL_MAP441/ et le faire tourner. Quel est le facteur de temps
de calcul entre les deux méthodes ?
from pylab import *
from time import time
n = 1000000
# Methode 1. Boucle for
print "-" * 40
print "Methode 1. Boucle for"
print "-" * 40
t1 = time()
x=0
for iin range(1, n):
x += 1. / i
print "gamma=", sum(x) - log(n)
t2 = time()
print "Cela a pris ",t2-t1," secondes"
# Methode 2. Numpy
print "-" * 40
print "Methode 2. Numpy"
t1 = time()
print "gamma=", sum(1. / arange(1, n)) - log(n)
t2 = time()
print "Cela a pris ",t2-t1," secondes"
print "-" * 40
4.2. Chacune des deux questions suivantes est à traiter sans boucle. On essayera de ne pas passer trop de
temps sur ces questions (notamment, les probabilités seront estimées sans intervalle de confiance).
(1) Soit, pour N= 100,X(1) <··· < X(N)le réordonnement croissant d’une famille X1, . . . , XNde v.a.
i.i.d. de loi gaussienne standard. Estimer la probabilité que cos(X(b0.8Nc))<0.6. On pourra simuler
M×Nv.a. gaussiennes, utiliser la fonction sort(., axis=1) puis utiliser le fait que si Vest une matrice,
pour tout j,V[:, j] désigne la jème colonne de V(la première est la colonne numéro 0).
(2) Soit (Xi)i1des v.a. i.i.d. de loi uniforme sur [0,1]. Estimer n0, la plus petite valeur de l’entier ntelle
que
P[X1+··· +Xn<5] 0.2
L’inégalité de Markov nous permet d’affirmer que n020. On pourra donc simuler M×20 v.a., utiliser
les fonctions cumsum(., axis=1) et sum(., axis=0), ainsi que la fonction argwhere.
5. Simulation de variables aléatoires continues (2) : inversion de la fonction de répartition
La loi de Cauchy de paramètre aest la loi de densité fa(x) = 1
π
a
x2+a2sur R. Simuler un grand nombre de
variables aléatoires de loi de Cauchy de paramètre a, représenter l’histogramme associé et le comparer à la
densité. Que se passe-t-il lorsque as’approche de 0?
Rappel : On rappelle que si Uest une v.a. uniforme sur ]0,1[ et Fla fonction de répartition d’une loi µ, alors
F1(U)est distribuée selon µ.
6. Loi des grands nombres
On rappelle que si (Xn)est une suite de variables aléatoires indepéndantes identiquement distribuées et ayant
une espérance m, alors la suite de variables aléatoires
¯
Xn=X1+··· +Xn
n
converge presque sûrement vers mlorsque ntend vers l’infini. Simuler un grand nombre Nde variables aléatoires
de loi uniforme sur [0,1], tracer sur un même graphe la représentation de la suite ¯
Xnpour nvariant de 1àNet
la courbe d’équation y=m, et observer cette convergence. On pourra utiliser la fonction axhline(y) qui trace
une droite horizontale à la hauteur y.
1 / 7 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !