Aller au contenu

Mesurez la valeur d'une politique avec Bellman

Au chapitre précédent, le robot du lac gelé disposait d’une politique, mais rien ne permettait encore de dire si elle était bonne. Une politique se juge sur ce qu’elle rapporte en moyenne, depuis chaque case du lac. Cette moyenne porte un nom, la fonction de valeur, et elle obéit à une équation d’une grande élégance : l’équation de Bellman.

Ce chapitre est le cœur théorique du cours. Tous les algorithmes qui suivent, de la programmation dynamique au Q-learning, ne sont que des façons différentes de résoudre les équations que vous allez écrire ici.

Placez le robot sur une case du lac et laissez-le suivre sa politique π\pi. Le retour GtG_t qu’il obtient est aléatoire : la politique peut tirer ses actions au hasard, et le lac peut être glissant. On définit donc la valeur de l’état ss sous la politique π\pi comme l’espérance de ce retour :

Vπ(s)=Eπ[ Gt∣st=s ]V^\pi(s) = \mathbb{E}_\pi\big[\, G_t \mid s_t = s \,\big]
  • Vπ(s)V^\pi(s) est la fonction de valeur d’état (state-value function) ;
  • Eπ\mathbb{E}_\pi est l’espérance quand l’agent suit π\pi (et que l’environnement suit PP) ;
  • la condition st=ss_t = s signifie qu’on part de l’état ss.

Au lac, où la seule récompense est le +1+1 de l’objectif, Vπ(s)V^\pi(s) se lit comme une probabilité d’atteindre G, pondérée par la durée du trajet. Une case proche de l’objectif, pour une bonne politique, a une valeur proche de 1 ; une case d’où l’on tombe presque toujours dans un trou a une valeur proche de 0.

Les états terminaux ont une valeur nulle : une fois dans un trou ou sur l’objectif, il n’y a plus de récompense à venir. La récompense de l’objectif est comptée au moment où l’on y entre, donc dans la valeur de la case d’avant.

Pour décider, il est souvent plus utile de connaître la valeur d’une action précise. On définit la fonction de valeur d’action (action-value function), ou fonction Q :

Qπ(s,a)=Eπ[ Gt∣st=s, at=a ]Q^\pi(s, a) = \mathbb{E}_\pi\big[\, G_t \mid s_t = s, \, a_t = a \,\big]

C’est le retour espéré si l’on fait d’abord l’action aa dans l’état ss, puis qu’on suit π\pi ensuite. Les deux fonctions sont liées très simplement : la valeur d’un état est la moyenne des valeurs de ses actions, pondérée par la politique.

Vπ(s)=∑aπ(a∣s) Qπ(s,a)V^\pi(s) = \sum_{a} \pi(a \mid s) \, Q^\pi(s, a)

Pourquoi s’embêter avec deux fonctions ? Parce que VV dit où il fait bon être, alors que QQ dit quoi faire. Nous verrons que, pour améliorer une politique, c’est QQ qu’il faut regarder.

Voici l’idée qui change tout. Le retour se décompose en « ce que je gagne maintenant » plus « ce que je gagnerai ensuite, actualisé » :

Gt=rt+1+γ Gt+1G_t = r_{t+1} + \gamma \, G_{t+1}

En prenant l’espérance, et grâce à la propriété de Markov (la suite ne dépend que de l’état atteint), on obtient une relation entre la valeur d’un état et celle de ses successeurs. C’est l’équation de Bellman d’espérance :

Vπ(s)=∑aπ(a∣s)∑s′P(s′∣s,a)[R(s,a,s′)+γ Vπ(s′)]V^\pi(s) = \sum_{a} \pi(a \mid s) \sum_{s'} P(s' \mid s, a) \Big[ R(s, a, s') + \gamma \, V^\pi(s') \Big]

Lisez-la de l’intérieur vers l’extérieur :

  • R(s,a,s′)+γVπ(s′)R(s, a, s') + \gamma V^\pi(s') est ce que rapporte une transition précise : la récompense immédiate, plus la valeur actualisée de l’état d’arrivée ;
  • la somme sur s′s', pondérée par P(s′∣s,a)P(s' \mid s, a), fait la moyenne sur les issues possibles de l’action (c’est Qπ(s,a)Q^\pi(s, a)) ;
  • la somme sur aa, pondérée par π(a∣s)\pi(a \mid s), fait la moyenne sur les actions que la politique peut choisir.

Si vous avez suivi le cours de modèles stochastiques, ce raisonnement vous est familier : c’est exactement le conditionnement sur le premier pas qui sert à calculer les probabilités et les temps d’absorption d’une chaîne de Markov. Une politique fixée transforme le MDP en chaîne de Markov, et VπV^\pi se calcule comme une quantité d’absorption.

Le lac a 64 états, c’est trop pour un calcul à la main. Prenons un couloir de trois cases, A, B et G (l’objectif, terminal). Deux actions : gauche et droite, sans glissade. Depuis A, gauche fait buter contre le mur (on reste en A) et droite mène en B. Depuis B, gauche ramène en A et droite atteint G, avec une récompense de +1+1. On prend γ=0,9\gamma = 0{,}9 et la politique aléatoire uniforme (1/21/2 pour chaque action).

ABGdroite : 1/2droite : 1/2gauche : 1/2gauche : 1/2(reste en A)+1V(A) ≈ 0,647V(B) ≈ 0,791V(G) = 0politiquealéatoire
Le couloir sous la politique aléatoire. Chaque flèche est suivie une fois sur deux ; les valeurs 0,647 et 0,791 sont la solution des deux équations de Bellman.

L’exemple le montre : pour une politique fixée, l’équation de Bellman est linéaire en les valeurs. En notation matricielle, avec PπP^\pi la matrice de transition de la chaîne obtenue en suivant π\pi et RπR^\pi le vecteur des récompenses immédiates espérées, elle s’écrit :

Vπ=Rπ+γ Pπ Vπ⟺Vπ=(I−γPπ)−1RπV^\pi = R^\pi + \gamma \, P^\pi \, V^\pi \quad \Longleftrightarrow \quad V^\pi = (I - \gamma P^\pi)^{-1} R^\pi
  • VπV^\pi est le vecteur des valeurs, une composante par état ;
  • Pπ(s,s′)=∑aπ(a∣s)P(s′∣s,a)P^\pi(s, s') = \sum_a \pi(a \mid s) P(s' \mid s, a) est la probabilité de passer de ss à s′s' en suivant π\pi ;
  • Rπ(s)R^\pi(s) est la récompense espérée au prochain pas depuis ss ;
  • II est la matrice identité. Pour γ<1\gamma < 1, la matrice I−γPπI - \gamma P^\pi est toujours inversible.
import numpy as np
gamma = 0.9
# États non terminaux : 0 = A, 1 = B (G est terminal, de valeur 0)
# Transitions de la politique aléatoire, restreintes aux états non terminaux
P_pi = np.array([[0.5, 0.5], # depuis A : reste en A ou va en B
[0.5, 0.0]]) # depuis B : va en A (l'autre moitié sort vers G)
R_pi = np.array([0.0, 0.5]) # depuis B, une chance sur deux de gagner 1
V = np.linalg.solve(np.eye(2) - gamma * P_pi, R_pi)
print(V.round(3)) # [0.647 0.791]

Pour un petit problème, cette résolution directe est parfaite. Mais inverser une matrice coûte de l’ordre de ∣S∣3\lvert S \rvert^3 opérations : pour un million d’états, c’est hors de portée. On préfère alors itérer l’équation, et c’est tout l’objet du chapitre suivant.

Les valeurs optimales et l’équation de Bellman d’optimalité

Section intitulée « Les valeurs optimales et l’équation de Bellman d’optimalité »

Parmi toutes les politiques, certaines sont meilleures que d’autres. On définit la valeur optimale d’un état comme la meilleure valeur atteignable :

V∗(s)=max⁡πVπ(s)Q∗(s,a)=max⁡πQπ(s,a)V^*(s) = \max_\pi V^\pi(s) \qquad Q^*(s, a) = \max_\pi Q^\pi(s, a)

Ces fonctions vérifient elles aussi une équation de Bellman, où la moyenne sur les actions est remplacée par un maximum : un agent optimal choisit toujours la meilleure action. C’est l’équation de Bellman d’optimalité :

V∗(s)=max⁡a∑s′P(s′∣s,a)[R(s,a,s′)+γ V∗(s′)]V^*(s) = \max_{a} \sum_{s'} P(s' \mid s, a) \Big[ R(s, a, s') + \gamma \, V^*(s') \Big] Q∗(s,a)=∑s′P(s′∣s,a)[R(s,a,s′)+γmax⁡a′Q∗(s′,a′)]Q^*(s, a) = \sum_{s'} P(s' \mid s, a) \Big[ R(s, a, s') + \gamma \max_{a'} Q^*(s', a') \Big]

Le symbole max⁡a\max_a prend la plus grande valeur sur toutes les actions possibles ; a′a' désigne l’action choisie dans l’état suivant s′s'.

sas′moyennepondérée par π(a | s)moyenne pondéréepar P(s′ | s, a)r + γ V(s′) sur chaque feuilleBellman d’espérance (politique π)sas′maxon garde lameilleure actionmoyenne pondéréepar P(s′ | s, a)r + γ V(s′) sur chaque feuilleBellman d’optimalité (valeur V*)
Les deux équations regardent un pas en avant, puis remontent les valeurs r + γV(s′) des feuilles. Seul le traitement des actions change : moyenne pondérée par π pour l'espérance, maximum pour l'optimalité.

Deux différences importantes avec l’équation d’espérance :

  1. À cause du max⁡\max, l’équation est non linéaire : impossible de la résoudre par une simple inversion de matrice. On la résoudra par itérations (value iteration, chapitre 4).
  2. Une fois Q∗Q^* connue, la politique optimale s’en déduit immédiatement : dans chaque état, on prend l’action de plus grande valeur.
π∗(s)=arg⁡max⁡aQ∗(s,a)\pi^*(s) = \arg\max_{a} Q^*(s, a)

Le symbole arg⁡max⁡a\arg\max_a désigne l’action qui réalise le maximum (et non la valeur de ce maximum). Un résultat fondamental garantit que, dans un MDP fini, il existe toujours une politique optimale déterministe, meilleure ou égale à toutes les autres dans tous les états à la fois.

ABGQ*(A, droite) = 0,90Q*(B, droite) = 1,00Q*(B, gauche) = 0,81Q*(A, gauche) = 0,81(reste en A)+1V*(A) = 0,9V*(B) = 1V(G) = 0politiqueoptimale
Dans chaque état, la flèche verte (droite) a la plus grande valeur Q* : c'est l'action choisie par l'argmax, et V* reprend sa valeur.

Au lac gelé, le même raisonnement donne V∗(S)=0,913≈0,254V^*(S) = 0{,}9^{13} \approx 0{,}254 pour γ=0,9\gamma = 0{,}9 : la valeur optimale du départ est le retour du plus court chemin. À titre de comparaison, si vous évaluez la politique aléatoire uniforme sur le même lac, vous obtenez une valeur de départ d’environ 3×10−53 \times 10^{-5} : en marchant au hasard, le robot tombe presque toujours dans un trou avant d’arriver.

HHHHHHHHHHG3·10⁻⁵0,360,12politique aléatoireHHHHHHHHHHG0,25410,9politique optimalevaleur de chaque case, γ = 0,9 (plus c’est foncé, plus la case vaut)
Même échelle de couleurs pour les deux politiques. Au hasard, seules les cases voisines de G ont une valeur visible ; la politique optimale donne 0,254 dès le départ.
  • Vπ(s)V^\pi(s) est le retour espéré en partant de ss et en suivant π\pi ; Qπ(s,a)Q^\pi(s, a) est le retour espéré en faisant d’abord aa, puis en suivant π\pi.
  • Vπ(s)=∑aπ(a∣s) Qπ(s,a)V^\pi(s) = \sum_a \pi(a \mid s) \, Q^\pi(s, a) : la valeur d’un état est la moyenne des valeurs de ses actions.
  • L’équation de Bellman d’espérance relie la valeur d’un état à celle de ses successeurs ; pour une politique fixée, c’est un système linéaire, Vπ=(I−γPπ)−1RπV^\pi = (I - \gamma P^\pi)^{-1} R^\pi.
  • L’équation de Bellman d’optimalité remplace la moyenne sur les actions par un maximum ; elle est non linéaire et caractérise V∗V^* et Q∗Q^*.
  • La politique optimale se lit sur Q∗Q^* : π∗(s)=arg⁡max⁡aQ∗(s,a)\pi^*(s) = \arg\max_a Q^*(s, a), et il en existe toujours une déterministe dans un MDP fini.
  • Au lac gelé avec γ=0,9\gamma = 0{,}9, V∗(S)≈0,254V^*(S) \approx 0{,}254, contre environ 3×10−53 \times 10^{-5} pour la politique aléatoire.

Exercice · Passer de Q à V

facile

Dans un état ss, une politique choisit gauche avec probabilité 0,5, bas avec probabilité 0,3 et droite avec probabilité 0,2 (jamais haut). On connaît Qπ(s,gauche)=0,2Q^\pi(s, \text{gauche}) = 0{,}2, Qπ(s,bas)=0,6Q^\pi(s, \text{bas}) = 0{,}6, Qπ(s,droite)=0,5Q^\pi(s, \text{droite}) = 0{,}5 et Qπ(s,haut)=0,9Q^\pi(s, \text{haut}) = 0{,}9.

  1. Calculez Vπ(s)V^\pi(s).
  2. Quelle action une politique « gloutonne » par rapport à QπQ^\pi choisirait-elle ici ?
Voir la solution
  1. Vπ(s)=0,5×0,2+0,3×0,6+0,2×0,5+0×0,9=0,1+0,18+0,1=0,38V^\pi(s) = 0{,}5 \times 0{,}2 + 0{,}3 \times 0{,}6 + 0{,}2 \times 0{,}5 + 0 \times 0{,}9 = 0{,}1 + 0{,}18 + 0{,}1 = 0{,}38.
  2. L’action de plus grande valeur est « haut » (0,90{,}9), que la politique actuelle ne choisit jamais. Une politique gloutonne choisirait « haut » dans cet état. Nous verrons au chapitre 3 que ce changement ne peut qu’améliorer la politique.

En code

import numpy as np
actions = ["gauche", "bas", "droite", "haut"]
pi = np.array([0.5, 0.3, 0.2, 0.0]) # pi(a | s)
Q = np.array([0.2, 0.6, 0.5, 0.9]) # Q^pi(s, a)
print(round(pi @ Q, 3)) # V^pi(s) = somme pi * Q : 0.38
print(actions[np.argmax(Q)]) # action gloutonne : haut

Exercice · Le couloir avec une autre politique

moyen

Dans le couloir A, B, G du chapitre (γ=0,9\gamma = 0{,}9), on considère la politique déterministe suivante : en A aller à droite, en B aller à gauche.

  1. Écrivez les équations de Bellman de cette politique et résolvez-les. Qu’observez-vous ?
  2. Calculez Qπ(B,droite)Q^\pi(B, \text{droite}) pour cette politique. Qu’en concluez-vous ?
Voir la solution
  1. Les équations sont V(A)=0+0,9 V(B)V(A) = 0 + 0{,}9 \, V(B) et V(B)=0+0,9 V(A)V(B) = 0 + 0{,}9 \, V(A). En substituant, V(A)=0,81 V(A)V(A) = 0{,}81 \, V(A), donc V(A)=0V(A) = 0 et V(B)=0V(B) = 0. Le robot fait des allers-retours entre A et B sans jamais atteindre G : il ne reçoit aucune récompense.
  2. Qπ(B,droite)=1+0,9 V(G)=1Q^\pi(B, \text{droite}) = 1 + 0{,}9 \, V(G) = 1, puisque G est terminal. Faire une seule fois « droite » en B rapporte 1, contre Vπ(B)=0V^\pi(B) = 0 en suivant la politique. Il suffit donc de changer l’action en B pour améliorer nettement la politique. C’est exactement le principe de l’amélioration de politique.

En code

import numpy as np
gamma = 0.9
# Politique : A -> droite (va en B), B -> gauche (va en A). G n'est jamais atteint.
P_pi = np.array([[0.0, 1.0], # depuis A : B
[1.0, 0.0]]) # depuis B : A
R_pi = np.array([0.0, 0.0]) # aucune récompense sur ces transitions
V = np.linalg.solve(np.eye(2) - gamma * P_pi, R_pi)
print(V) # [0. 0.]
# Q(B, droite) : on atteint G (terminal, valeur 0) avec la récompense 1
print(1 + gamma * 0) # 1.0 > V(B) = 0 : changer l'action en B améliore

Exercice · Vérifier l'optimalité sur le lac

difficile

Au lac gelé non glissant avec γ=0,9\gamma = 0{,}9, on admet que V∗V^* vaut 1 sur la case 62 (juste à gauche de G) et 0,9 sur la case 61 (deux cases à gauche de G). La case 54, au-dessus de 62, est un trou.

  1. À l’aide de l’équation de Bellman d’optimalité, calculez Q∗(62,a)Q^*(62, a) pour les quatre actions (la case 62 est sur la dernière ligne ; son voisin de gauche est 61, celui de droite est 63).
  2. Supposons maintenant le lac glissant : chaque action réussit avec probabilité 1/31/3 et dérape vers chacune des deux directions perpendiculaires avec probabilité 1/31/3. On garde, pour simplifier, les valeurs V(61)=0,9V(61) = 0{,}9 et V(62)=1V(62) = 1. Calculez Q(62,droite)Q(62, \text{droite}) et Q(62,bas)Q(62, \text{bas}). Laquelle de ces deux actions paraît préférable ?
Voir la solution
  1. En déterministe, Q∗(62,a)=R+0,9 V∗(s′)Q^*(62, a) = R + 0{,}9 \, V^*(s') :

    • gauche : arrivée en 61, Q∗=0+0,9×0,9=0,81Q^* = 0 + 0{,}9 \times 0{,}9 = 0{,}81 ;
    • bas : on bute contre le bord et on reste en 62, Q∗=0+0,9×1=0,9Q^* = 0 + 0{,}9 \times 1 = 0{,}9 ;
    • droite : arrivée en G, Q∗=1+0,9×0=1Q^* = 1 + 0{,}9 \times 0 = 1 ;
    • haut : chute dans le trou 54, Q∗=0+0,9×0=0Q^* = 0 + 0{,}9 \times 0 = 0.

    Le maximum vaut 1, pour « droite », ce qui est cohérent avec V∗(62)=1V^*(62) = 1.

  2. En glissant :

    • droite : réussite vers G (1), dérapage vers le haut dans le trou (0), dérapage vers le bas qui laisse en 62 (0,9×10{,}9 \times 1). Q=13(1+0+0,9)≈0,633Q = \tfrac{1}{3}(1 + 0 + 0{,}9) \approx 0{,}633.
    • bas : réussite qui laisse en 62 (0,90{,}9), dérapage à gauche vers 61 (0,9×0,9=0,810{,}9 \times 0{,}9 = 0{,}81), dérapage à droite vers G (1). Q=13(0,9+0,81+1)≈0,903Q = \tfrac{1}{3}(0{,}9 + 0{,}81 + 1) \approx 0{,}903.

    « Bas » devient préférable : il ne peut jamais faire tomber dans le trou, et il atteint G une fois sur trois par dérapage. Ces valeurs ne sont qu’un calcul d’une étape (les vraies valeurs du lac glissant sont différentes), mais elles montrent que la meilleure action dépend des probabilités de transition, et pas seulement de la case visée.

En code

gamma = 0.9
V = {61: 0.9, 62: 1.0, 63: 0.0, 54: 0.0} # 63 = G et 54 = trou : terminaux
issue = {"gauche": (61, 0), "bas": (62, 0), # (état d'arrivée, récompense) depuis 62
"droite": (63, 1), "haut": (54, 0)}
def q(action):
s_suiv, r = issue[action]
return r + gamma * V[s_suiv]
# 1. Lac déterministe
print({a: round(q(a), 3) for a in issue})
# {'gauche': 0.81, 'bas': 0.9, 'droite': 1.0, 'haut': 0.0}
# 2. Lac glissant : l'action visée et ses deux perpendiculaires, 1/3 chacune
glisse = {"droite": ["droite", "haut", "bas"], "bas": ["bas", "gauche", "droite"]}
for a, issues in glisse.items():
print(a, round(sum(q(b) for b in issues) / 3, 3))
# droite 0.633
# bas 0.903