Trouvez la loi stationnaire
Au chapitre 1, vous avez calculé la météo dans trois jours. Mais quelle est la proportion de jours de pluie sur une année entière ? Et cette proportion dépend-elle du temps qu’il faisait le 1er janvier ? L’intuition dit que non : au bout d’un moment, la chaîne « oublie » son point de départ.
Ce chapitre donne un sens précis à cette intuition. Vous allez calculer la loi stationnaire d’une chaîne, apprendre dans quels cas la chaîne converge vers elle, et à quelle vitesse. Nous reprenons la météo rennaise du chapitre 1, et nous finirons par l’algorithme qui a fait la fortune de Google.
La chaîne oublie son point de départ
Section intitulée « La chaîne oublie son point de départ »Rappelons la matrice de la météo (soleil, nuages, pluie) :
Calculons pour deux points de départ opposés : un jour de soleil et un jour de pluie.
| Départ au soleil | Départ sous la pluie | |
|---|---|---|
| 1 | (0,600 ; 0,300 ; 0,100) | (0,100 ; 0,400 ; 0,500) |
| 5 | (0,357 ; 0,363 ; 0,280) | (0,335 ; 0,368 ; 0,297) |
| 10 | (0,346 ; 0,365 ; 0,288) | (0,346 ; 0,365 ; 0,289) |
| 20 | (0,346 ; 0,365 ; 0,288) | (0,346 ; 0,365 ; 0,288) |
Au bout d’une dizaine de jours, les deux colonnes sont identiques à trois décimales : la loi de ne dépend plus de . Elle s’est stabilisée sur un vecteur, qu’on appelle la loi stationnaire. Pourquoi « stationnaire » ? Parce que si ne bouge plus, alors .
Définir et calculer la loi stationnaire
Section intitulée « Définir et calculer la loi stationnaire »Une loi stationnaire (ou invariante) est un vecteur ligne qui vérifie
La première équation dit que si la chaîne suit la loi à un instant, elle la suit encore à l’instant suivant, et donc pour toujours. La deuxième en fait une loi de probabilité. En langage d’algèbre linéaire, est un vecteur propre à gauche de pour la valeur propre 1, normalisé pour sommer à 1.
Le système contient une équation redondante (les lignes de sommant à 1, l’une se déduit des autres). On en supprime donc une, et on la remplace par la normalisation.
Pour une chaîne à deux états, le calcul se fait de tête. Reprenons la machine du chapitre 2, qui tombe en panne avec probabilité et est réparée avec probabilité :
En effet, la première équation donne : le « flux » de la marche vers la panne égale le flux de la panne vers la marche. Avec et , la machine fonctionne 80 % du temps.
Quand la loi stationnaire est-elle la limite ?
Section intitulée « Quand la loi stationnaire est-elle la limite ? »Une loi stationnaire existe-t-elle toujours ? Est-elle unique ? Et surtout, converge-t-elle vers elle ? Le résultat central du chapitre répond à tout.
Chaque hypothèse compte. Voyons ce qui se passe quand l’une manque.
Sans apériodicité. Le robot du chapitre 2 fait la navette entre deux entrepôts : . La loi est bien stationnaire et unique. Mais partant de l’entrepôt 0, vaut aux instants pairs et aux instants impairs : elle oscille et ne converge pas. En revanche, garde un sens : c’est la proportion du temps passée dans chaque état sur une longue période (le robot est la moitié du temps dans chaque entrepôt).
Sans irréductibilité. Dans la chaîne du site du chapitre 2, deux classes sont fermées. La loi qui met toute la masse sur Départ est stationnaire, celle qui se répartit sur Abonné et Vidéo en proportions aussi, et tout mélange des deux également. Il y a une infinité de lois stationnaires, et la limite dépend du point de départ. C’est l’objet du chapitre 4.
Sans récurrence positive (espace infini seulement). Dans une file d’attente où les clients arrivent plus vite qu’ils ne sont servis, la file grandit sans fin : aucune loi stationnaire n’existe. Nous le verrons au chapitre 8.
Vitesse de convergence et temps de retour
Section intitulée « Vitesse de convergence et temps de retour »À quelle vitesse la chaîne oublie-t-elle son départ ? Pour la machine, on peut calculer exactement. Partant de l’état « marche » :
Le premier terme est ; le second est l’écart à la limite, qui décroît géométriquement avec la raison . Avec et , on a : l’écart est divisé par deux chaque heure (1 ; 0,9 ; 0,85 ; 0,825…).
Ce nombre n’est pas un hasard : c’est la seconde valeur propre de (la première vaut toujours 1). En général, la vitesse de convergence est gouvernée par la plus grande valeur propre de en module après 1. Pour la météo, elle vaut environ 0,456 : l’écart à la loi stationnaire est divisé par un peu plus de 2 chaque jour, ce qui explique la stabilisation en une dizaine de jours. Une valeur proche de 1 signale une chaîne qui « se mélange » lentement.
La loi stationnaire a une autre interprétation, très parlante. Pour une chaîne irréductible et récurrente positive, la probabilité stationnaire d’un état est l’inverse de son temps moyen de retour :
où est le nombre moyen de pas pour revenir en en partant de . Plus on revient vite, plus on passe de temps dans l’état. Pour la machine, heure (calculé au chapitre 2), et on retrouve bien . Pour la météo, le temps moyen entre deux jours de pluie vaut jours.
PageRank : la loi stationnaire d’un surfeur aléatoire
Section intitulée « PageRank : la loi stationnaire d’un surfeur aléatoire »Comment classer des pages web par importance ? L’idée de PageRank est de lâcher un surfeur aléatoire sur le web : sur chaque page, il clique au hasard sur l’un des liens sortants. Une page importante est une page où il passe souvent, c’est-à-dire une page de forte probabilité stationnaire.
Problème : le graphe du web n’est ni irréductible (des pages sans lien entrant, des culs-de-sac) ni forcément apériodique. On corrige avec la téléportation : à chaque pas, avec probabilité , le surfeur saute sur une page tirée uniformément. La matrice devient
où est la matrice de la marche sur les liens, le nombre de pages, la matrice remplie de 1, et le facteur d’amortissement, classiquement 0,85. Tous les coefficients de sont strictement positifs : la chaîne est irréductible et apériodique, et le théorème ergodique s’applique.
Pour calculer sur des milliards de pages, on ne résout pas de système linéaire : on itère simplement à partir d’une loi quelconque. C’est la méthode de la puissance, qui converge d’autant plus vite que la seconde valeur propre est petite (pour PageRank, elle est au plus ).
import numpy as np
P = np.array([[0.6, 0.3, 0.1], [0.3, 0.4, 0.3], [0.1, 0.4, 0.5]])n = len(P)
# 1) Système linéaire : (P^T - I) Pi^T = 0, une équation remplacée par sum(Pi) = 1A = P.T - np.eye(n)A[-1, :] = 1b = np.zeros(n); b[-1] = 1pi = np.linalg.solve(A, b)print(pi) # [0.3462 0.3654 0.2885]
# 2) Méthode de la puissancepi_it = np.ones(n) / nfor _ in range(100): pi_it = pi_it @ Pprint(np.allclose(pi, pi_it)) # True
# 3) Valeurs propres : 1, puis la seconde qui fixe la vitesse de convergenceprint(np.sort(np.abs(np.linalg.eigvals(P)))[::-1]) # [1. 0.456 0.044]
# 4) Proportion du temps sur une longue trajectoire simuléerng = np.random.default_rng(1)x, compte = 0, np.zeros(n)for _ in range(100_000): x = rng.choice(n, p=P[x]) compte[x] += 1print(compte / compte.sum()) # proche de piLe quatrième calcul illustre une autre face du théorème ergodique : la proportion du temps passée dans chaque état le long d’une seule trajectoire converge elle aussi vers . C’est ce résultat qui fonde les méthodes MCMC en statistique bayésienne : on construit une chaîne dont la loi stationnaire est la loi qu’on veut échantillonner, on la laisse tourner un moment (la « chauffe », qui correspond au régime transitoire), puis on utilise ses états comme des tirages.
En résumé
Section intitulée « En résumé »- Une loi stationnaire vérifie , : c’est un vecteur propre à gauche de pour la valeur propre 1.
- On la calcule en remplaçant une équation de par la normalisation, ou par la méthode de la puissance.
- Théorème ergodique : irréductible + récurrente positive (automatique si finie) + apériodique implique une unique et quelle que soit la loi initiale.
- Périodique : existe mais oscille ; reste la proportion du temps passée dans chaque état. Non irréductible : plusieurs lois stationnaires possibles.
- La convergence est géométrique, à la vitesse de la seconde plus grande valeur propre en module.
- : probabilité stationnaire et temps moyen de retour sont inverses. PageRank est la loi stationnaire d’une marche aléatoire avec téléportation.
Exercices
Section intitulée « Exercices »Exercice · Disponibilité d'une machine
facileUne imprimante 3D tombe en panne en cours d’heure avec probabilité 0,2 et, quand elle est en panne, est réparée dans l’heure avec probabilité 0,3. Quelle proportion du temps fonctionne-t-elle à long terme ? En moyenne, combien d’heures s’écoulent entre deux heures de panne ?
Voir la solution
Avec et , la chaîne est irréductible, finie et apériodique (boucles), donc ergodique. La loi stationnaire vaut
L’imprimante fonctionne 60 % du temps. Le temps moyen de retour dans l’état « panne » vaut heures.
En code
import numpy as np
a, b = 0.2, 0.3 # panne, réparation (par heure)P = np.array([[1 - a, a], [b, 1 - b]])
# Pi P = Pi : une équation remplacée par la normalisationA = P.T - np.eye(2)A[-1, :] = 1pi = np.linalg.solve(A, [0, 1])print(pi) # [0.6 0.4] : en marche 60 % du tempsprint(1 / pi[1]) # 2.5 heures entre deux heures de pannea <- 0.2; b <- 0.3 # panne, réparation (par heure)P <- matrix(c(1 - a, a, b, 1 - b), nrow = 2, byrow = TRUE)
# Pi P = Pi : une équation remplacée par la normalisationA <- t(P) - diag(2)A[2, ] <- 1pi_ <- solve(A, c(0, 1))pi_ # 0.6 0.4 : en marche 60 % du temps1 / pi_[2] # 2.5 heures entre deux heures de panneExercice · Une chaîne à trois états
moyenUn livreur travaille dans trois quartiers alignés A, B, C. Depuis A, il reste en A ou passe en B avec probabilité 1/2 chacun ; depuis B, il va en A ou en C avec probabilité 1/4 chacun et reste en B avec probabilité 1/2 ; depuis C, il reste en C ou passe en B avec probabilité 1/2 chacun.
- Justifiez que la chaîne converge vers une loi stationnaire unique.
- Calculez-la, puis le temps moyen entre deux passages en A.
Voir la solution
- Tous les quartiers communiquent (A ⇄ B ⇄ C) : la chaîne est irréductible. Elle est finie, donc récurrente positive, et chaque état a une boucle, donc elle est apériodique. Le théorème ergodique s’applique.
- L’équation de la colonne A donne , soit . Par symétrie entre A et C, . La normalisation donne , donc
Le temps moyen de retour en A vaut pas.
En code
import numpy as np
P = np.array([[1/2, 1/2, 0], # quartiers A, B, C [1/4, 1/2, 1/4], [0, 1/2, 1/2]])
# Vecteur propre à gauche pour la valeur propre 1, normalisévaleurs, vecteurs = np.linalg.eig(P.T)pi = np.real(vecteurs[:, np.argmin(abs(valeurs - 1))])pi = pi / pi.sum()print(pi) # [0.25 0.5 0.25]print(1 / pi[0]) # 4.0 pas entre deux passages en Aprint(np.linalg.matrix_power(P, 50)[2]) # [0.25 0.5 0.25] : partant de C, on convergeP <- matrix(c(1/2, 1/2, 0, # quartiers A, B, C 1/4, 1/2, 1/4, 0, 1/2, 1/2), nrow = 3, byrow = TRUE)
# Vecteur propre à gauche pour la valeur propre 1, normalisée <- eigen(t(P))pi_ <- Re(e$vectors[, which.min(abs(e$values - 1))])pi_ <- pi_ / sum(pi_)pi_ # 0.25 0.50 0.251 / pi_[1] # 4 pas entre deux passages en AExercice · Stationnaire mais pas limite
difficileUne balle rebondit entre trois positions alignées : depuis une extrémité (0 ou 2), elle va toujours au centre (1) ; depuis le centre, elle va à chaque extrémité avec probabilité 1/2.
- Quelle est la période de la chaîne ? Calculez sa loi stationnaire.
- La balle part de la position 0. Calculez , , . La suite converge-t-elle ?
- Montrez que la moyenne de sur deux pas consécutifs est égale à la loi stationnaire. Interprétez.
Voir la solution
- Tout chemin alterne entre le centre et une extrémité, donc un retour n’est possible qu’en un nombre pair de pas : la période vaut 2. La colonne 0 de donne , de même , et la normalisation conduit à .
- , , , , puis la suite alterne entre et . Elle ne converge pas : la chaîne est irréductible et récurrente positive, mais périodique.
- . La loi stationnaire ne décrit pas la position à un instant donné, mais la proportion du temps passée à chaque position : la balle est au centre un pas sur deux, et à chaque extrémité un pas sur quatre.
En code
import numpy as np
P = np.array([[0, 1, 0], # extrémité 0 -> centre [0.5, 0, 0.5], # centre -> une extrémité [0, 1, 0]])p = np.array([1.0, 0, 0]) # départ en 0lois = [p]for n in range(5): p = p @ P lois.append(p)for n, loi in enumerate(lois): print(n, loi)# 0 [1. 0. 0.]# 1 [0. 1. 0.]# 2 [0.5 0. 0.5]# 3 [0. 1. 0.] et ainsi de suite : la suite oscilleprint((lois[4] + lois[5]) / 2) # [0.25 0.5 0.25] = PiP <- matrix(c(0, 1, 0, # extrémité 0 -> centre 0.5, 0, 0.5, # centre -> une extrémité 0, 1, 0), nrow = 3, byrow = TRUE)p <- c(1, 0, 0) # départ en 0lois <- list(p)for (n in 1:5) { p <- as.vector(p %*% P) lois[[n + 1]] <- p}do.call(rbind, lois) # lignes : n = 0, ..., 5## 1.0 0 0.0 / 0 1 0 / 0.5 0 0.5 / 0 1 0 / 0.5 0 0.5 / 0 1 0 : la suite oscille(lois[[5]] + lois[[6]]) / 2 # 0.25 0.50 0.25 = Pi