import numpy as np
=4) np.random.uniform(size
array([0.70682855, 0.19816833, 0.50696264, 0.83819303])
numpy
, savoir afficher un histogramme, une densité, etc.numpy
.Avec numpy
, la fonction numpy.random.uniform
permet la génération de réalisations pseudo-aléatoires de la loi uniforme sur [0,1].
On peut modifier la taille de l’échantillon généré en modifiant l’argument de la fonction. Pour obtenir n=4 réalisations i.i.d. de loi uniforme, essayez par exemple
array([0.70682855, 0.19816833, 0.50696264, 0.83819303])
Pour rappel, l’algorithme de génération de v.a. est récursif et s’appuie sur une graine. La graine peut être modifiée avec la création d’un générateur, et il suffit d’entrer un nombre en argument pour fixer cette graine.
rng = np.random.default_rng(seed=34)
print(rng.uniform())
rng = np.random.default_rng(34)
print(rng.uniform())
0.004028243493043537
0.004028243493043537
Changer les valeurs de seed
et vérifier que les tirages ont bien changé.
Créez un vecteur de taille 1000 composé de réalisations i.i.d. de v.a.uniformes sur [-1,1]. Dans la suite on supposera que l’on a chargé matplotlib
pour l’affichage graphique avec la commande:
À l’aide de la fonction plt.hist
, représentez l’histogramme de cet échantillon.
fig, ax = plt.subplots()
vect = rng.uniform(-1, 1, 1000)
ax.hist(vect, label="Histogramme", bins=30, density=True)
plt.title("Histogramme: tirage uniforme sur [-1, -1]")
plt.legend()
ax.set_xlim((-1.5,1.5))
ax.set_xlabel('Abscisse')
ax.set_ylabel('Ordonnée')
plt.show()
On utilisera l’aide de hist de matplotlib
s pour préciser les options graphiques suivantes:
bins
en entrant l’option bins=30
et bins=10
.density=True
, de sorte que l’aire soit de 1 (on représente donc une densité qui est constante par morceaux)plt.title
(avec une chaîne de caractères entre guillemets). On peut également ajouter un nom aux axes avec l’option plt.xlabel
et plt.ylabel
.ax.set_xlim
et ax.set_ylim
permettent de préciser l’échelle de axes: il faut préciser un tuple (a,b)
où a<b sont les deux bornes choisies pour votre axe.fill
et histtype
de hist
pour obtenir le résultat suivant, en affichant sur un même graphique trois tirages, de tailles 1000, 5000 et 10000.pdf
du module scipy.stats
. Créer un vecteur équiréparti sur [-2, 2] de longueur 300 évaluer la fonction sur la même figure: on souhaite superposer cette densité à l’histogramme. On utilisera la fonction plot
pour tracer la densité, et on pourra utiliser l’option alpha
pour rendre la densité plus transparente.Un exemple de figure de qualité acceptable est par exemple celle qui suit:
cmap = plt.cm.coolwarm
vect100 = rng.uniform(-1, 1, 1000)
vect1000 = rng.uniform(-1, 1, 5000)
vect10000 = rng.uniform(-1, 1, 10000)
x = np.linspace(-2, 2, num=300)
fig, ax = plt.subplots()
colors=[cmap(0.99), cmap(0.7), cmap(0.5)]
ax.plot(x, stats.uniform.pdf(x, loc=-1,scale=2),'--', color='k', label="Loi théorique", alpha=0.5)
ax.hist(vect10000, histtype='step', density=True, bins=30, label="Histogramme 10000", fill=False, color=colors[0])
ax.hist(vect1000, histtype='step', density=True, bins=30, label="Histogramme 5000", fill=False, color=colors[1])
ax.hist(vect100, histtype='step', density=True, bins=30, label="Histogramme 1000", fill=False, color=colors[2])
plt.title('Histogramme: tirage uniforme sur [-1, -1]')
plt.xlabel('Abscisse')
plt.ylabel('Ordonnée')
ax.set_xlim((-2,2))
from matplotlib.lines import Line2D
custom_lines = [Line2D([0], [0], color=colors[0], lw=2),
Line2D([0], [0], color=colors[1], lw=2),
Line2D([0], [0], color=colors[2], lw=2)]
ax.legend(custom_lines, ['10000 tirages', '1000 tirages', '100 tirages'], loc='upper right')
plt.show()
Attention quand vous tracez des histogrammes pour des réalisation de la v.a. non bornées: pour la gaussienne, les histogrammes sont bons
vectGauss = np.random.randn(1000)
fig, ax = plt.subplots()
xx = np.linspace(vectGauss.min() - 1, vectGauss.max() + 1, 100)
ax.plot(xx, stats.norm.pdf(xx, loc=0, scale=1),'--', color='k', label="Loi théorique", alpha=0.5)
ax.hist(vectGauss, histtype='step', density=True, bins=30, label="Histogramme 10000", fill=False, color=colors[0])
# plot density
plt.title('Histogramme: tirage Gaussien')
plt.show()
Pour la Cauchy, les histogrammes se comportent mal
vectCauchy = np.random.standard_cauchy(10000)
fig, ax = plt.subplots()
xx = np.linspace(vectCauchy.min() - 1, vectCauchy.max() + 1, 100)
ax.plot(xx, stats.cauchy.pdf(xx, loc=0, scale=1),'--', color='k', label="Loi théorique", alpha=0.5)
ax.hist(vectCauchy, histtype='step', density=True, bins=30, label="Histogramme 10000", fill=False, color=colors[0])
plt.title('Histogramme naïf: tirage Cauchy...')
plt.show()
Il faut tronquer (ci-dessous entre -11 et 11) pour retrouver une représentation fidèle:
xmax = 11
fig, ax = plt.subplots()
xx = np.linspace(-xmax - 1, xmax + 1, 100)
ax.plot(xx, stats.cauchy.pdf(xx, loc=0, scale=1),'--', color='k', label="Loi théorique", alpha=0.5)
ax.hist(vectCauchy[np.abs(vectCauchy) < xmax], histtype='step', density=True, bins=30, label="Histogramme 10000", fill=False, color=colors[0])
ax.set_xlim((-xmax - 1, xmax + 1))
plt.title('Histogramme : tirage Cauchy tronquée...')
plt.show()
La fonction de répartition de la loi uniforme est obtenue via la commande cdf
du module scipy.stats.uniform
. À l’aide de la commande plt.plot
tracez en bleu la fonction de répartition de la loi uniforme sur [-1,1], [-0.7, 0.7] et [-0.5,0.5] et donnez un titre à votre graphique.
lw
(linewidth) l’épaisseur du trait.matplotlib
. Une liste exhaustive est donnée ici: matplotlib.pyplot.plot.htmlcolor=nom_couleur
dans la fonction plot
.Manipulez les différentes options pour vous familiariser avec les graphes
Tenter de reproduire la figure suivante
fig, ax = plt.subplots()
lines = np.linspace(0, 1, 9)
for i, vali in enumerate(lines):
ax.plot(x, stats.uniform.cdf(x, loc=-vali,scale=2*vali), color=cmap(0.2+0.8*i/len(lines)), label=f"[-{-vali},{-vali+2*vali}]", lw=2)
ax.set_xlim([-1.5,1.5])
plt.legend()
plt.title("Fonctions de répartition de diverses loi uniformes")
plt.show()
Créez un vecteur de taille 100 composé de réalisations i.i.d. de variables uniformes sur [0,1]. Calculez dans un vecteur la moyenne cumulée des valeurs générées. Représenter graphiquement l’évolution de ces moyennes. Vers quoi semble converger la moyenne quand la taille de l’échantillon augmente ?
Pour ajouter une droite à un graphe, on utilise la commande ax.axhline
. Ajoutez en rouge la droite d’équation y=1/2 sur le graphe précédent. Refaites cet exercice avec un échantillon de taille n=1000 pour observer plus finement la convergence.
vect = rng.uniform(0, 1, 1000)
fig, ax = plt.subplots()
ax.plot(np.cumsum(vect) / np.arange(1, len(vect)+1), label="Moyenne empirique")
ax.axhline(0.5, linestyle="--", color='red', lw=2, label="Espérance de la loi")
ax.set_title("Convergence de la moyenne empirique")
plt.legend()
dzexpo
qui prend en argument une taille d’échantillon n et un paramètre \lambda > 0 et qui donne en sortie un échantillon de taille n de loi \mathcal{E}(\lambda). On utilisera la méthode d’inversion vue en cours et seulement des tirages uniformes sur [0,1]. Attention, le mot clef lambda
est un mot réservé en Python.cumulative
de hist
) d’un tel échantillon pour n=10^2, n=10^3, puis n=10^4, et pour \lambda = 1, puis \lambda = 4. Superposez à chaque fois le graphe de la densité de \mathcal{E}(\lambda).fig, ax = plt.subplots()
x = np.linspace(0, 8, num=300)
ax.plot(x, stats.expon.cdf(x, scale=1), color='k', label="Fonction de répartition", lw=2)
def dzexpo(n, lbd):
U = rng.uniform(size=n)
return - np.log(U) / lbd
ax.hist(dzexpo(100, 1), density=True, cumulative=True, histtype='step',bins=30, label="Estimation de la fonction de répartition", color=colors[0])
ax.hist(dzexpo(1000, 1), density=True, cumulative=True, histtype='step',bins=30, label="Estimation de la fonction de répartition", color=colors[1])
ax.hist(dzexpo(10000, 1), density=True, cumulative=True, histtype='step',bins=30, label="Estimation de la fonction de répartition", color=colors[2])
ax.set_title("Loi exponentielle")
custom_lines = [Line2D([0], [0], color='k', lw=2),
Line2D([0], [0], color=colors[0], lw=2),
Line2D([0], [0], color=colors[1], lw=2),
Line2D([0], [0], color=colors[2], lw=2),
]
ax.legend(custom_lines,
['Fonction de répartition (théorique)',
'Fonction de répartition (estimée, n=100)',
'Fonction de répartition (estimée, n=1000)',
'Fonction de répartition (estimée, n=10000)',
], loc='lower right')
On reprend le tout avec la loi de Cauchy:
vect = dzcauchy(1000, 1)
fig, ax = plt.subplots()
ax.plot(np.cumsum(vect) / np.arange(1, len(vect)+1), label="Moyenne empirique")
ax.axhline(1, linestyle="--", color='red', lw=2, label="Médiane de la loi")
ax.set_title("Convergence de la moyenne empirique pour une loi de Cauchy?")
plt.legend()
Le phénomène qui apparaît avec la loi de Cauchy est les suivant: les queues de la loi de Cauchy sont tellement épaisses que la moyenne empirique que l’écart entre \min_i(X_i) et le \max_i(X_i) (les X_i étant les tirages effectués) est du même ordre de grandeur que le nombre de tirages, n. Comme la fonction hist
discrétise l’intervalle [\min(X_i), \max(X_i)] en le nombre de boîtes (bins
) on observe peu de points dans chaque boîte ce qui rend l’estimation de la densité trop petite.
Ce point n’est pas un problème pour les lois gaussiennes, car la largeur de l’intervalle [\min(X_i), \max(X_i)] est de l’ordre de \sqrt{\log(n)}, et comme on a n points à placer dans cet intervalle, il y a assez de points dans chaque boîte pour obtenir une bonne estimation.
Notons que les méthodes à noyaux (KDE) ne souffrent pas de ce défaut, car les “boîtes” sont en fait fixé autour des données et non sur une grille discrétisée comme c’est le cas pour l’histogramme. Voir par exemple l’aide de scikit learn ou encore wikipedia, méthode à noyau.
import plotly.graph_objects as go
from sklearn.neighbors import KernelDensity
n_sample = 1000
x = np.linspace(-2, 10, num=10000)
X=dzcauchy(n_sample, 1)
kde = KernelDensity(kernel="tophat", bandwidth=0.1).fit(X.reshape(-1, 1))
log_dens = kde.score_samples(x.reshape(-1, 1))
fig=go.Figure()
fig.add_trace(go.Scatter(x=x, y=np.exp(log_dens), mode='lines', line=dict(color='blue', width=2), name="Estimation de la densité"))
fig.add_trace(go.Scatter(x=x, y=stats.cauchy.pdf(x, scale=1, loc=0), mode='lines', opacity=0.6, line=dict(color='black', width=2), name="Densité de Cauchy"))
fig.update_layout(
template="simple_white",
showlegend=True,
)
print(f"Taille de l'échantillon: {n_sample}")
print(f"Étendue: {np.max(X)-np.min(X)}")
Taille de l'échantillon: 1000
Étendue: 1488.6440039526083
Notons qu’un phénomène similaire apparaît aussi avec la loi de Pareto, qui est une loi à queue lourde quand son paramètre \alpha est plus petit que 1.
Taille de l'échantillon: 1000
Étendue: 8254.628995163406
Taille de l'échantillon: 1000
Étendue: 152.94757156399794