Machine Learning · PoliMI

Programmazione Dinamica

Capitolo 10
≈ 49 min di lettura · 10721 parole
Importanza per l'esame: 3/5

★★★☆☆ Compare quasi solo negli snippet di codice (policy/value iteration) e in vero/falso su convergenza e numero di iterazioni.

Il capitolo precedente ha costruito il linguaggio dei Processi Decisionali di Markov e lo ha portato fino alle equazioni di Bellman: quelle di aspettativa, che caratterizzano la value function di una policy data e formano un sistema lineare, e quelle di ottimalità, che caratterizzano la value function ottima ma, a causa dell’operatore di massimo, non ammettono soluzione in forma chiusa. Questo capitolo affronta la domanda naturale che ne segue: assumendo di conoscere completamente il modello dell’MDP, cioè la dinamica one-step p(ss,a)p(s' \mid s, a) e la funzione di reward r(s,a)r(s, a), come si calcolano concretamente VπV^{\pi}, VV^{*} e π\pi^{*}? La risposta è la famiglia degli algoritmi di programmazione dinamica (Dynamic Programming, DP): iterative policy evaluation per il problema di valutazione, policy improvement e policy iteration per il problema di controllo, la cornice unificante della generalized policy iteration (GPI) e la sua istanza più celebre, value iteration, fino alle varianti asincrone. Il capitolo si chiude con l’analisi dei costi computazionali e con i due limiti strutturali della DP, la maledizione della dimensionalità e la necessità del modello, che motivano il passaggio ai metodi model-free dei capitoli successivi. Un esempio numerico svolto passo-passo, sia su un gridworld sia su un piccolo MDP a due stati, accompagna ogni algoritmo.

Riferimenti sul testo: Sutton e Barto, Reinforcement Learning: An Introduction, capitolo 4. Materiale complementare consigliato: il corso online Fundamentals of Reinforcement Learning (Coursera).

1. Se conosco il modello, posso pianificare#

1.1 I due problemi: prediction e control#

Tutto il capitolo si svolge sotto un’ipotesi forte: l’MDP è noto per intero. Sono dati gli insiemi S\mathcal{S} e A\mathcal{A}, la dinamica di transizione p(ss,a)p(s' \mid s, a), il reward atteso r(s,a)r(s, a) e il discount factor γ\gamma. In queste condizioni non c’è nulla da “imparare” dall’esperienza: si tratta di pianificare, cioè di estrarre dal modello, con puro calcolo, le quantità di interesse. I problemi da risolvere sono due, in ordine crescente di difficoltà.

Problema di prediction

Dato un MDP completamente noto e una policy π\pi, calcolare la state-value function VπV^{\pi}.

  • Input: π\pi, rr, pp, γ\gamma;
  • Output: VπV^{\pi} (ed eventualmente QπQ^{\pi}).
Problema di control

Dato un MDP completamente noto, trovare la value function ottima e una policy ottima.

  • Input: rr, pp, γ\gamma;
  • Output: VV^{*} e π\pi^{*}.
Prediction (valutare una policy data)π, r, p, γDPequazioni di BellmanVπControl (trovare la policy migliore)r, p, γDPequazioni di Bellmanπ*, V*

I due problemi non sono indipendenti: la prediction è il mattone del control. Come si vedrà, gli algoritmi di controllo funzionano alternando una fase in cui si valuta la policy corrente (prediction) e una fase in cui la si migliora sfruttando la valutazione appena ottenuta. Gli strumenti matematici sono sempre le equazioni di Bellman: quelle di aspettativa per VπV^{\pi} e QπQ^{\pi} nel caso della prediction, quelle di ottimalità per VV^{*} e QQ^{*} nel caso del control.

In parole semplici: prediction risponde a “quanto rende questa strategia?”; control risponde a “qual è la strategia migliore?”. La seconda domanda si affronta rispondendo ripetutamente alla prima: valuto la strategia che ho, scopro dove sbaglia, la correggo, e ricomincio.

1.2 Perché la forza bruta non funziona#

Il capitolo precedente ha già fornito, in linea di principio, una soluzione per entrambi i problemi. Per la prediction c’è la forma chiusa Vπ=(IγPπ)1RπV^{\pi} = (I - \gamma P^{\pi})^{-1} R^{\pi}, che costa O(S3)O(|\mathcal{S}|^3). Per il control c’è la ricerca esaustiva: il teorema di esistenza garantisce una policy ottima deterministica, quindi basterebbe enumerare tutte le policy deterministiche, valutare ciascuna e tenere la dominante. Il conteggio però condanna questo approccio: le policy deterministiche sono

AS|\mathcal{A}|^{|\mathcal{S}|}

perché in ogni stato si sceglie indipendentemente una tra A|\mathcal{A}| azioni, e per ciascuna di esse andrebbe risolto un sistema di S|\mathcal{S}| equazioni lineari. Anche un gridworld modesto, 5×55 \times 5 con 4 azioni, produce 42510154^{25} \approx 10^{15} policy candidate: la ricerca brute-force è fuori scala già sui problemi giocattolo. Serve un metodo che sfrutti la struttura del problema invece di enumerarne le soluzioni.

1.3 Che cos’è la programmazione dinamica e perché si applica agli MDP#

Programmazione dinamica

Metodo generale di risoluzione che affronta un problema complesso spezzandolo ricorsivamente in sottoproblemi più semplici: si risolvono i sottoproblemi e si combinano le loro soluzioni nella soluzione del problema originale.

La programmazione dinamica non è nata per gli MDP: è un paradigma algoritmico generale (lo stesso, per esempio, degli algoritmi di cammino minimo). Perché sia applicabile, un problema deve possedere due proprietà strutturali:

Gli MDP soddisfano entrambe le proprietà, ed è esattamente ciò che le equazioni di Bellman esprimono. La sottostruttura ottima è la ricorsione di Bellman: il valore di uno stato si decompone in reward immediato più valore scontato dello stato successivo, quindi “quanto rende partire da ss” si risolve conoscendo “quanto rende partire da ciascun possibile ss'”. I sottoproblemi ricorrenti sono gli stati stessi: il valore di uno stato ss' serve nel calcolo del valore di tutti gli stati che possono transitare in ss', e la value function è precisamente la cache che memorizza le soluzioni dei sottoproblemi per riutilizzarle.

Idea chiave: le equazioni di Bellman sono la ricetta di decomposizione della programmazione dinamica applicata agli MDP: ogni stato è un sottoproblema, la value function è la tabella delle soluzioni parziali, e l’aggiornamento di Bellman è l’operazione che propaga le soluzioni da uno stato ai suoi predecessori.

La strategia che la DP mette in campo per il control è già visibile in filigrana: produrre una successione di policy via via migliori, ciascuna valutata con le equazioni di aspettativa e corretta con quelle di ottimalità, finché la successione non si stabilizza sulla policy dominante.

π1π2π3π*stato svalore V(s)ogni miglioramento alza la curva (o la lascia uguale) in ogni stato

In parole semplici: invece di provare tutte le strategie una per una, si compila una tabella con il valore di ogni situazione, sfruttando il fatto che il valore di una situazione dipende solo dal valore delle situazioni in cui si può finire. Si aggiorna la tabella finché i numeri non tornano coerenti tra loro: a quel punto la tabella contiene la risposta.

2. Valutare una policy: iterative policy evaluation#

2.1 Dall’equazione di Bellman all’aggiornamento iterativo#

Il punto di partenza è l’equazione di aspettativa di Bellman, che VπV^{\pi} soddisfa in ogni stato:

Vπ(s)=aπ(as)[r(s,a)+γsp(ss,a)Vπ(s)]V^{\pi}(s) = \sum_{a} \pi(a \mid s) \left[ r(s, a) + \gamma \sum_{s'} p(s' \mid s, a) \, V^{\pi}(s') \right]

Risolvere direttamente il sistema lineare costa O(S3)O(|\mathcal{S}|^3) ed è impraticabile su spazi di stati grandi. La programmazione dinamica segue un’altra strada: trasforma l’identità in una regola di aggiornamento. Si parte da una stima iniziale arbitraria V0V_0 (per esempio V0(s)=0V_0(s) = 0 per ogni ss, con l’unico vincolo che gli eventuali stati terminali abbiano valore 0) e si genera una successione di approssimazioni applicando a ogni passo il membro destro dell’equazione alla stima corrente:

Vk+1(s)=aπ(as)[r(s,a)+γsp(ss,a)Vk(s)]sSV_{k+1}(s) = \sum_{a} \pi(a \mid s) \left[ r(s, a) + \gamma \sum_{s'} p(s' \mid s, a) \, V_k(s') \right] \qquad \forall s \in \mathcal{S}

Un’applicazione dell’aggiornamento a tutti gli stati si chiama sweep (spazzata) dello spazio degli stati. Ogni singolo aggiornamento è un backup completo (full-width backup): per calcolare il nuovo valore di ss si considerano tutte le azioni possibili in ss e, per ciascuna, tutti i possibili stati successori con le rispettive probabilità; è qui che la conoscenza del modello (rr e pp) viene usata in modo essenziale.

In forma compatta, usando l’operatore di Bellman di aspettativa introdotto nel capitolo precedente, la successione è Vk+1=TπVkV_{k+1} = T^{\pi} V_k. La convergenza è allora immediata dalle proprietà già dimostrate: VπV^{\pi} è l’unico punto fisso di TπT^{\pi} e, per γ<1\gamma < 1, TπT^{\pi} è una γ\gamma-contrazione in norma del massimo. Ne segue che

VkVπγkV0Vπ0\left\lVert V_k - V^{\pi} \right\rVert_{\infty} \leq \gamma^k \left\lVert V_0 - V^{\pi} \right\rVert_{\infty} \longrightarrow 0

quindi VkVπV_k \to V^{\pi} per kk \to \infty, qualunque sia l’inizializzazione V0V_0, con errore che si riduce almeno di un fattore γ\gamma a ogni sweep. Nei task episodici la convergenza è garantita anche con γ=1\gamma = 1, purché ogni policy considerata raggiunga prima o poi uno stato terminale.

Idea chiave: l’equazione di Bellman viene usata non come vincolo da risolvere ma come operazione da ripetere: si “gira la manovella” del backup finché i valori smettono di cambiare. Quando l’aggiornamento non modifica più nulla, la stima soddisfa l’equazione di Bellman, e quindi è VπV^{\pi}.

In parole semplici: si parte con una tabella di valori tutti a zero e la si corregge a ogni giro: il nuovo valore di ogni stato è “premio medio immediato più valore scontato medio di dove si finisce”, calcolato con i valori del giro precedente. Ogni giro avvicina la tabella alla verità di un fattore γ\gamma, quindi dopo abbastanza giri la tabella è (quasi) esatta.

2.2 Pseudocodice e criterio d’arresto#

In pratica l’iterazione si arresta quando i valori si sono stabilizzati: si monitora la variazione massima su tutti gli stati in uno sweep e ci si ferma quando scende sotto una soglia θ>0\theta > 0 scelta piccola.

Iterative Policy Evaluation
Input: policy π da valutare, modello (p, r), discount γ, soglia θ > 0

Inizializza V(s) arbitrariamente per ogni s ∈ S (V = 0 sugli stati terminali)
ripeti
    Δ ← 0
    per ogni s ∈ S:
        v ← V(s)
        V(s) ← Σ_a π(a|s) [ r(s,a) + γ Σ_{s'} p(s'|s,a) V(s') ]
        Δ ← max(Δ, |v − V(s)|)
finché Δ < θ
Output: V ≈ V^π

Il criterio d’arresto ha una lettura precisa: se dopo uno sweep la variazione massima è Δ<θ\Delta < \theta, significa che la stima corrente soddisfa l’equazione di Bellman a meno di θ\theta; grazie alla contrazione si può anche limitare la distanza residua dalla soluzione vera, che è dell’ordine di θγ/(1γ)\theta \gamma / (1 - \gamma) in norma del massimo. Più θ\theta è piccolo, più la valutazione è accurata, al prezzo di più sweep.

2.3 Versione a due array e versione in place#

La formula Vk+1=TπVkV_{k+1} = T^{\pi} V_k descrive un aggiornamento sincrono: tutti i nuovi valori sono calcolati usando esclusivamente i valori del passo precedente, il che richiede due array, uno per VkV_k e uno per Vk+1V_{k+1}. Lo pseudocodice sopra implementa invece la variante in place: un solo array, in cui ogni valore appena aggiornato è immediatamente disponibile per gli aggiornamenti successivi all’interno dello stesso sweep. Le due versioni convergono entrambe a VπV^{\pi}; quella in place di solito converge più in fretta, perché l’informazione nuova si propaga già durante lo sweep invece di aspettare il successivo, ma il risultato intermedio dipende dall’ordine in cui gli stati vengono visitati. Questa osservazione, apparentemente un dettaglio implementativo, è il seme della programmazione dinamica asincrona della sezione 7.

In parole semplici: nella versione “pulita” si calcolano tutti i nuovi valori guardando solo la fotografia del giro precedente; nella versione in place si sovrascrive man mano, così chi viene aggiornato dopo sfrutta già i valori freschi dei vicini aggiornati prima. La seconda risparmia memoria e tipicamente accelera la convergenza.

2.4 Esempio numerico: il piccolo gridworld#

Il piccolo gridworld. Le due celle grigie agli angoli opposti formano un unico stato terminale; le 14 celle numerate sono gli stati non terminali. (Slide del corso.)

L’esempio classico su cui vedere l’algoritmo in azione è un gridworld 4×44 \times 4 con queste regole:

Poiché reward e transizioni sono deterministici data l’azione, l’aggiornamento si semplifica in

Vk+1(s)=14a[1+Vk(succ(s,a))]=1+14aVk(succ(s,a))V_{k+1}(s) = \frac{1}{4} \sum_{a} \left[ -1 + V_k\big(\mathrm{succ}(s, a)\big) \right] = -1 + \frac{1}{4} \sum_{a} V_k\big(\mathrm{succ}(s, a)\big)

dove succ(s,a)\mathrm{succ}(s,a) è la cella in cui l’azione aa conduce da ss. Partendo da V0=0V_0 = 0 ovunque:

Sweep 1. Per ogni cella non terminale, tutti i successori hanno valore V0=0V_0 = 0, quindi V1(s)=1+0=1V_1(s) = -1 + 0 = -1 ovunque (0 sui terminali).

Sweep 2. Ora i valori dei vicini non sono più tutti uguali. Per una cella adiacente a un terminale, per esempio quella in prima riga, seconda colonna: andando a ovest si entra nel terminale (V1=0V_1 = 0), andando a est, a sud o sbattendo verso nord si finisce in celle con V1=1V_1 = -1. Quindi

V2=1+0+(1)+(1)+(1)4=1,751,7V_2 = -1 + \frac{0 + (-1) + (-1) + (-1)}{4} = -1{,}75 \approx -1{,}7

Per una cella interna lontana dai terminali tutti e quattro i successori valgono 1-1, quindi V2=2,0V_2 = -2{,}0.

Sweep 3. Di nuovo per la cella in prima riga, seconda colonna, usando i valori esatti di V2V_2: ovest porta al terminale (00), est e sud portano in celle con V2=2V_2 = -2, nord fa sbattere e restare sul posto (V2=1,75V_2 = -1{,}75):

V3=1+0+(2)+(2)+(1,75)4=15,7542,4V_3 = -1 + \frac{0 + (-2) + (-2) + (-1{,}75)}{4} = -1 - \frac{5{,}75}{4} \approx -2{,}4

La successione dei valori, arrotondati alla prima cifra decimale, sulle sei istantanee più significative (le celle d’angolo in alto a sinistra e in basso a destra sono i terminali, sempre a 0):

V1V_1 (dopo il primo sweep):

0,00{,}0 1,0-1{,}0 1,0-1{,}0 1,0-1{,}0
1,0-1{,}0 1,0-1{,}0 1,0-1{,}0 1,0-1{,}0
1,0-1{,}0 1,0-1{,}0 1,0-1{,}0 1,0-1{,}0
1,0-1{,}0 1,0-1{,}0 1,0-1{,}0 0,00{,}0

V2V_2:

0,00{,}0 1,7-1{,}7 2,0-2{,}0 2,0-2{,}0
1,7-1{,}7 2,0-2{,}0 2,0-2{,}0 2,0-2{,}0
2,0-2{,}0 2,0-2{,}0 2,0-2{,}0 1,7-1{,}7
2,0-2{,}0 2,0-2{,}0 1,7-1{,}7 0,00{,}0

V3V_3:

0,00{,}0 2,4-2{,}4 2,9-2{,}9 3,0-3{,}0
2,4-2{,}4 2,9-2{,}9 3,0-3{,}0 2,9-2{,}9
2,9-2{,}9 3,0-3{,}0 2,9-2{,}9 2,4-2{,}4
3,0-3{,}0 2,9-2{,}9 2,4-2{,}4 0,00{,}0

V10V_{10}:

0,00{,}0 6,1-6{,}1 8,4-8{,}4 9,0-9{,}0
6,1-6{,}1 7,7-7{,}7 8,4-8{,}4 8,4-8{,}4
8,4-8{,}4 8,4-8{,}4 7,7-7{,}7 6,1-6{,}1
9,0-9{,}0 8,4-8{,}4 6,1-6{,}1 0,00{,}0

V=VπV_{\infty} = V^{\pi} (limite della successione):

00 14-14 20-20 22-22
14-14 18-18 20-20 20-20
20-20 20-20 18-18 14-14
22-22 20-20 14-14 00

I valori limite hanno un’interpretazione trasparente: con reward 1-1 a ogni passo e γ=1\gamma = 1, Vπ(s)V^{\pi}(s) è l’opposto del numero atteso di passi che una passeggiata casuale impiega, partendo da ss, per raggiungere un terminale. Dalla cella più sfavorita (l’angolo opposto diagonale rispetto a ciascun terminale) servono in media 22 passi; dalle celle adiacenti a un terminale ne servono in media 14: la policy casuale è molto inefficiente, e la value function lo quantifica esattamente.

In parole semplici: a ogni giro i valori negativi “si propagano” dai terminali verso l’interno, come un’onda: prima si sistemano le celle vicine alle uscite, poi via via quelle più lontane. Al limite ogni cella riporta quanti passi (in media, cambiati di segno) mancano all’uscita muovendosi a caso.

3. Migliorare una policy: policy improvement#

3.1 Agire greedy rispetto a una value function#

Il calcolo di VπV^{\pi} non è fine a se stesso: serve per capire se e dove la policy π\pi può essere migliorata. Dal capitolo precedente è noto che, se si conoscessero le value function ottime, la policy ottima si otterrebbe agendo in modo greedy: π(s)=argmaxaQ(s,a)\pi^{*}(s) = \arg\max_a Q^{*}(s,a). La domanda naturale è: che cosa succede applicando la stessa ricetta a una value function non ottima? Data VπV^{\pi}, si costruisce la policy deterministica

π(s)=argmaxaA(s)Qπ(s,a)=argmaxaA(s)[r(s,a)+γsp(ss,a)Vπ(s)]\pi'(s) = \arg\max_{a \in \mathcal{A}(s)} Q^{\pi}(s, a) = \arg\max_{a \in \mathcal{A}(s)} \left[ r(s, a) + \gamma \sum_{s'} p(s' \mid s, a) \, V^{\pi}(s') \right]

che in ogni stato sceglie l’azione con il miglior compromesso tra reward immediato e valore (secondo π\pi) dello stato d’arrivo. Il calcolo dell’argmax\arg\max richiede di nuovo il modello: per ogni azione si esegue un lookahead a un passo attraverso rr e pp. Due esiti sono possibili:

3.2 Il teorema di policy improvement#

Teorema di policy improvement

Siano π\pi e π\pi' due policy deterministiche tali che, per ogni stato sSs \in \mathcal{S},

Qπ(s,π(s))Vπ(s)Q^{\pi}\big(s, \pi'(s)\big) \geq V^{\pi}(s)

Allora π\pi' è migliore o uguale a π\pi, cioè Vπ(s)Vπ(s)V^{\pi'}(s) \geq V^{\pi}(s) per ogni sSs \in \mathcal{S}. Se inoltre la disuguaglianza dell’ipotesi è stretta in qualche stato sˉ\bar{s}, allora anche Vπ(sˉ)>Vπ(sˉ)V^{\pi'}(\bar{s}) > V^{\pi}(\bar{s}).

L’ipotesi va letta così: deviare da π\pi per un solo passo (eseguendo π(s)\pi'(s) invece di π(s)\pi(s)) e poi tornare a seguire π\pi non peggiora mai le cose. La tesi afferma qualcosa di più forte: allora anche seguire π\pi' per sempre non peggiora mai le cose. La dimostrazione trasforma la deviazione di un passo in una deviazione permanente, espandendo la value function un passo alla volta.

Dimostrazione. Si parte dall’ipotesi nello stato ss e si espande QπQ^{\pi} con la sua definizione a un passo:

Vπ(s)Qπ(s,π(s))=E[Rt+1+γVπ(St+1)St=s,At=π(s)]=Eπ[Rt+1+γVπ(St+1)St=s]V^{\pi}(s) \leq Q^{\pi}\big(s, \pi'(s)\big) = \mathbb{E}\left[ R_{t+1} + \gamma V^{\pi}(S_{t+1}) \mid S_t = s, A_t = \pi'(s) \right] = \mathbb{E}_{\pi'}\left[ R_{t+1} + \gamma V^{\pi}(S_{t+1}) \mid S_t = s \right]

L’ultima uguaglianza vale perché condizionare all’azione At=π(s)A_t = \pi'(s) equivale a dire che il primo passo è compiuto secondo π\pi'. Ora, dentro il valore atteso compare Vπ(St+1)V^{\pi}(S_{t+1}); applicando l’ipotesi del teorema nello stato St+1S_{t+1} si ottiene Vπ(St+1)Qπ(St+1,π(St+1))V^{\pi}(S_{t+1}) \leq Q^{\pi}(S_{t+1}, \pi'(S_{t+1})), e quindi

Vπ(s)Eπ[Rt+1+γQπ(St+1,π(St+1))St=s]=Eπ[Rt+1+γRt+2+γ2Vπ(St+2)St=s]V^{\pi}(s) \leq \mathbb{E}_{\pi'}\left[ R_{t+1} + \gamma \, Q^{\pi}\big(S_{t+1}, \pi'(S_{t+1})\big) \mid S_t = s \right] = \mathbb{E}_{\pi'}\left[ R_{t+1} + \gamma R_{t+2} + \gamma^2 V^{\pi}(S_{t+2}) \mid S_t = s \right]

dove il secondo passaggio espande di nuovo QπQ^{\pi} a un passo: ora anche la seconda azione è scelta da π\pi'. Iterando lo stesso argomento (applicare l’ipotesi in St+2S_{t+2}, espandere, e così via) si sostituisce π\pi con π\pi' un passo alla volta:

Vπ(s)Eπ[Rt+1+γRt+2+γ2Rt+3+γ3Vπ(St+3)St=s]V^{\pi}(s) \leq \mathbb{E}_{\pi'}\left[ R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + \gamma^3 V^{\pi}(S_{t+3}) \mid S_t = s \right] \leq \cdots

Al limite, il termine residuo γkVπ(St+k)\gamma^k V^{\pi}(S_{t+k}) svanisce (perché γk0\gamma^k \to 0 se γ<1\gamma < 1, oppure perché l’episodio termina), e resta l’intero return generato seguendo π\pi':

Vπ(s)Eπ[Rt+1+γRt+2+γ2Rt+3+St=s]=Vπ(s)V^{\pi}(s) \leq \mathbb{E}_{\pi'}\left[ R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + \cdots \mid S_t = s \right] = V^{\pi'}(s)

che è la tesi. Se in qualche stato l’ipotesi vale con disuguaglianza stretta, la stessa catena parte con un << e produce un miglioramento stretto in quello stato. \blacksquare

La policy greedy π\pi' della sezione 3.1 soddisfa automaticamente l’ipotesi del teorema: per ogni ss,

Qπ(s,π(s))=maxaQπ(s,a)aπ(as)Qπ(s,a)=Vπ(s)Q^{\pi}\big(s, \pi'(s)\big) = \max_{a} Q^{\pi}(s, a) \geq \sum_{a} \pi(a \mid s) \, Q^{\pi}(s, a) = V^{\pi}(s)

perché il massimo di un insieme di valori non è mai inferiore a una loro media pesata. Quindi il miglioramento greedy non può mai peggiorare la policy; e se non la cambia, la policy era già ottima.

Idea chiave: il teorema di policy improvement trasforma un vantaggio locale in un vantaggio globale: se in ogni stato la deviazione di un solo passo verso π\pi' non è dannosa, allora adottare π\pi' ovunque e per sempre non è dannoso. È questa amplificazione dal singolo passo all’intera traiettoria che rende il miglioramento greedy uno strumento sicuro.

In parole semplici: se cambiare una sola mossa qua e là non fa mai danno, cambiare tutte le mosse insieme non fa danno: i piccoli vantaggi si accumulano lungo la traiettoria invece di annullarsi. Per questo scegliere sempre l’azione col QQ più alto della vecchia strategia produce una strategia nuova che è almeno altrettanto buona.

3.3 Il gridworld rivisitato: greedy su una value function non ottima#

Si torni al piccolo gridworld e alla value function VπV^{\pi} della policy casuale. Poiché il reward è 1-1 per ogni mossa e le transizioni sono deterministiche con γ=1\gamma = 1, l’azione greedy in una cella è semplicemente quella che porta nel vicino con il valore più alto.

Dal valore alla policy migliorata. A sinistra la value function V^{\pi} della policy casuale uniforme sul piccolo gridworld; a destra la policy greedy \pi' costruita con un lookahead a un passo: in ogni cella le frecce indicano le azioni che massimizzano Q^{\pi} (più frecce dove c’è pareggio). La policy risultante è già quella ottima. (Slide del corso.)

Applicando il miglioramento greedy alle istantanee della sezione 2.4 si osserva un fatto notevole:

Il fronte delle scelte greedy avanza con le valutazioni. Le policy greedy estratte da V_0, V_1, V_2 e V_3: da V_0 tutte le azioni sono in pareggio, da V_1 si determinano le celle adiacenti ai terminali, da V_3 la policy estratta è già \pi^{*}. (Slide del corso.)

Ci sono due lezioni. La prima: agire greedy rispetto alla value function di una policy mediocre (quella casuale) può produrre direttamente una policy eccellente; in questo piccolo esempio, addirittura ottima al primo miglioramento. La seconda, ancora più utile in pratica: la policy greedy si è stabilizzata già a V3V_3, molto prima che la valutazione converga (V3V_3 dista ancora parecchio da VV_{\infty}). Valutare con precisione assoluta una policy destinata a essere subito rimpiazzata è uno spreco: questa osservazione motiverà la generalized policy iteration e value iteration.

In parole semplici: per capire da che parte andare non serve conoscere i valori esatti, basta che l’ordinamento tra i vicini sia giusto. E l’ordinamento giusto emerge dopo pochi giri di valutazione, molto prima dei valori esatti: quindi si può migliorare la strategia in anticipo, senza aspettare la fine dei conti.

4. Alternare valutazione e miglioramento: policy iteration#

4.1 L’algoritmo e la sua convergenza#

I due strumenti costruiti finora si compongono naturalmente in un algoritmo per il problema di control. Si parte da una policy arbitraria π0\pi_0 (per esempio quella casuale) e si alternano i due passi:

La successione generata è

π0EVπ0Iπ1EVπ1Iπ2EIπEV\pi_0 \xrightarrow{E} V^{\pi_0} \xrightarrow{I} \pi_1 \xrightarrow{E} V^{\pi_1} \xrightarrow{I} \pi_2 \xrightarrow{E} \cdots \xrightarrow{I} \pi^{*} \xrightarrow{E} V^{*}

e l’algoritmo termina quando il passo di miglioramento non modifica più la policy. La convergenza è garantita da un argomento in tre mosse:

V = Vππ = greedy(V)V0, π0V*, π*valutazione (E)miglioramento (I)

Lo pseudocodice completo:

Policy Iteration
Input: modello (p, r), discount γ, soglia θ > 0

1. Inizializzazione:
   V(s) arbitraria e π(s) ∈ A(s) arbitraria, per ogni s ∈ S

2. Policy Evaluation:
   ripeti
       Δ ← 0
       per ogni s ∈ S:
           v ← V(s)
           V(s) ← r(s, π(s)) + γ Σ_{s'} p(s'|s, π(s)) V(s')
           Δ ← max(Δ, |v − V(s)|)
   finché Δ < θ

3. Policy Improvement:
   policy_stabile ← vero
   per ogni s ∈ S:
       a_old ← π(s)
       π(s) ← argmax_a [ r(s,a) + γ Σ_{s'} p(s'|s,a) V(s') ]
       se a_old ≠ π(s): policy_stabile ← falso
   se policy_stabile: restituisci V ≈ V* e π ≈ π*
   altrimenti: vai al passo 2

Un accorgimento pratico importante: al ritorno al passo 2 la valutazione della nuova policy non riparte da zero, ma dalla value function della policy precedente. Poiché policy consecutive sono simili, le loro value function lo sono altrettanto, e il “warm start” riduce drasticamente il numero di sweep necessari.

Idea chiave: policy iteration è una scalata monotona nello spazio (finito) delle policy deterministiche: ogni giro produce una policy non peggiore, nessuna policy viene mai rivisitata, e l’unica condizione di arresto possibile è l’ottimalità. La convergenza non è asintotica ma esatta e in un numero finito di passi.

In parole semplici: valuto la strategia che ho, poi in ogni situazione sostituisco la mossa prescritta con la migliore secondo i valori appena calcolati, e ricomincio. A ogni giro la strategia migliora davvero da qualche parte; siccome le strategie possibili sono in numero finito, prima o poi il giro non cambia più nulla, e a quel punto ho in mano la strategia ottima certificata.

4.2 Un esempio più ricco: gridworld con celle penalizzanti#

L’ambiente dell’esempio. Gridworld 4 \times 4: la cella grigia in alto a sinistra è il terminale, le celle blu sono penalizzanti (reward -10 entrandovi, contro -1 delle celle ordinarie); \gamma = 1. (Slide del corso.)

Per vedere la dinamica di policy iteration su qualche iterazione in più conviene un gridworld meno banale. L’ambiente è una griglia 4×44 \times 4 con lo stato terminale nell’angolo in alto a sinistra e un gruppo di celle penalizzanti disposte su due file: ogni passo ordinario costa 1-1, ma entrare in una cella penalizzante costa 10-10; il task è episodico e non scontato (γ=1\gamma = 1). La struttura del problema rende sconveniente qualunque cammino che attraversi l’area penalizzante: anche quando il terminale è “in linea d’aria” oltre le celle cattive, il percorso ottimo le aggira, perché un solo ingresso nell’area costa quanto una decina di passi normali. L’esecuzione di policy iteration partendo dalla policy casuale uniforme procede così.

Prima valutazione e primo miglioramento. La value function della policy casuale è molto negativa ovunque (fino a 242-242 nell’angolo più lontano), perché una passeggiata casuale vaga a lungo e attraversa ripetutamente l’area penalizzante. Ciononostante i valori sono già informativi: contengono l’ordinamento giusto tra i vicini in gran parte della griglia. Per esempio, dalla cella con valore 181-181 il vicino “in alto” vale 137,5-137{,}5 e il vicino “a sinistra” 129,5-129{,}5: il miglioramento greedy sceglie di andare a sinistra, non perché 129,5-129{,}5 sia un buon valore, ma perché è meno peggio degli altri. La policy greedy risultante è già ragionevole, ma non ovunque: le celle della prima riga puntano ancora a sinistra attraverso l’area penalizzante, perché i valori della policy casuale non distinguono ancora bene il cammino diretto da quello che aggira le celle blu.

Valutazione della policy casuale. I valori arrivano a -242; i riquadri evidenziano le celle penalizzanti. (Slide del corso.)
Primo miglioramento greedy. Le frecce scelgono il vicino “meno peggio”; nella prima riga puntano ancora attraverso l’area blu. (Slide del corso.)

Seconda valutazione e correzioni successive. Valutando la nuova policy i valori cambiano radicalmente (molto meno negativi, perché ora la policy “ha senso”) e rendono visibili gli errori residui. Un esempio concreto: la cella d’angolo in alto a destra vale 21-21 perché la sua policy passa per la cella penalizzante adiacente (valore 11-11); il confronto tra i QQ al miglioramento successivo rende evidente che conviene invece scendere e aggirare l’area. Lo stesso accade nell’ultima riga: il cammino corretto esce a destra e risale lungo la colonna libera, e la correzione si propaga all’indietro una cella per giro (prima 147-14 \to -7, poi 138-13 \to -8, infine 129-12 \to -9), perché a ogni giro l’informazione buona arretra di un passo lungo il percorso. Gli stati vicini al terminale si sistemano per primi; quelli più lontani richiedono più iterazioni. Dopo pochi giri il miglioramento non modifica più alcuna azione: la policy è ottima e la value function corrente è VV^{*}.

Valutazione della policy migliorata. I valori crollano in modulo; l’angolo in alto a destra (-21) e l’ultima riga rivelano i cammini ancora sbagliati. (Slide del corso.)
Policy e value function ottime. Tutti i cammini aggirano l’area penalizzante; l’ultima riga esce a destra e risale. (Slide del corso.)

In parole semplici: anche i valori di una strategia pessima insegnano qualcosa, perché dicono quale mossa è “meno peggio” delle altre. Il primo giro sistema le scelte vicino all’obiettivo, i giri successivi propagano la correzione alle zone lontane, come un’onda che torna indietro dal traguardo. Quando l’onda ha raggiunto tutto, nessuna mossa cambia più: si è arrivati all’ottimo.

4.3 Il collo di bottiglia#

Il costo di policy iteration è dominato dal passo di valutazione: ogni iterazione esterna richiede molti sweep completi dello spazio degli stati solo per valutare, con precisione θ\theta, una policy che con ogni probabilità verrà scartata subito dopo. L’esempio del gridworld ha già suggerito che si tratta di uno spreco: la policy greedy si stabilizza ben prima che la valutazione converga. La domanda diventa: quanto si può troncare la valutazione senza perdere la convergenza all’ottimo? La cornice concettuale che risponde “quanto si vuole” è la generalized policy iteration della prossima sezione; la realizzazione estrema, un solo sweep di valutazione per miglioramento, è value iteration.

5. Generalized policy iteration#

L’idea che valutazione e miglioramento possano essere interlacciati a qualunque granularità ha un nome: generalized policy iteration (GPI). Il termine indica ogni schema in cui due processi interagiscono:

Policy iteration è il caso estremo in cui la valutazione arriva a convergenza prima di ogni miglioramento; value iteration, oggetto della prossima sezione, è il caso estremo opposto, con un solo sweep di valutazione per miglioramento; la DP asincrona della sezione 7 interlaccia i due processi a grana ancora più fine, aggiornando singoli stati. In tutti i casi il comportamento qualitativo è lo stesso della scalata a zigzag di policy iteration: una traiettoria che rimbalza tra due “bersagli” mobili, con la valutazione che tira la value function verso il vincolo “VV coerente con π\pi” e il miglioramento che tira la policy verso il vincolo “π\pi greedy rispetto a VV”. I due processi in parte competono, perché ogni miglioramento rende la value function corrente obsoleta e ogni valutazione rende la policy corrente non più greedy; ma nel complesso cooperano, e la traiettoria converge verso l’unico punto in cui entrambi i vincoli sono soddisfatti simultaneamente.

V = Vππ = greedy(V)V0, π0V*, π*valutazioni parziali e miglioramenti interlacciati: stessa destinazione

Quel punto è caratterizzato con precisione: se la value function è coerente con la policy (V=VπV = V^{\pi}) e la policy è greedy rispetto alla value function, allora

Vπ(s)=maxaA(s)[r(s,a)+γsp(ss,a)Vπ(s)]sV^{\pi}(s) = \max_{a \in \mathcal{A}(s)} \left[ r(s, a) + \gamma \sum_{s'} p(s' \mid s, a) \, V^{\pi}(s') \right] \qquad \forall s

cioè vale l’equazione di ottimalità di Bellman: V=VV = V^{*} e π=π\pi = \pi^{*}. La stabilità congiunta dei due processi implica l’ottimalità, e viceversa; per questo qualunque interlacciamento che continui a far progredire entrambi i processi finisce nell’ottimo.

La portata della GPI va molto oltre questo capitolo: quasi tutti i metodi di reinforcement learning che si incontreranno, compresi quelli model-free, sono istanze di GPI in cui cambia soltanto come viene realizzato il processo di valutazione (per esempio con stime campionarie invece che con backup esatti sul modello) e quanto spesso si migliora.

Idea chiave: valutazione e miglioramento sono due forze che si tirano a vicenda: qualunque modo di alternarle, anche parziale, sbilanciato o asincrono, converge allo stesso punto di equilibrio, l’unico in cui la policy è greedy rispetto alla propria value function. Quel punto è l’ottimo di Bellman.

In parole semplici: non importa se si misura tanto e si corregge poco, o si misura poco e si corregge subito: finché si continua sia a misurare sia a correggere, si finisce sempre nello stesso posto, dove misura e strategia non si contraddicono più. Quel posto è la soluzione ottima, e quasi tutto il reinforcement learning è una variazione su questo schema.

6. La scorciatoia: value iteration#

6.1 Fondere valutazione e miglioramento in un unico aggiornamento#

Si consideri l’istanza di GPI in cui il passo di valutazione esegue un solo sweep e si ferma. La sequenza delle operazioni per uno stato ss diventa: un backup di valutazione con la policy corrente π\pi,

Vk+1(s)=r(s,π(s))+γsp(ss,π(s))Vk(s)V_{k+1}(s) = r\big(s, \pi(s)\big) + \gamma \sum_{s'} p\big(s' \mid s, \pi(s)\big) \, V_k(s')

seguito subito dal miglioramento greedy, che ridefinisce π(s)=argmaxa[r(s,a)+γsp(ss,a)V(s)]\pi(s) = \arg\max_a [\, r(s,a) + \gamma \sum_{s'} p(s' \mid s,a) V(s') \,]. Ma se il miglioramento viene comunque eseguito subito dopo, tanto vale usare direttamente l’azione massimizzante dentro il backup di valutazione: i due passi si fondono in un unico aggiornamento che non fa più riferimento ad alcuna policy esplicita,

Vk+1(s)=maxaA(s)[r(s,a)+γsp(ss,a)Vk(s)]sSV_{k+1}(s) = \max_{a \in \mathcal{A}(s)} \left[ r(s, a) + \gamma \sum_{s'} p(s' \mid s, a) \, V_k(s') \right] \qquad \forall s \in \mathcal{S}

Questo è l’aggiornamento di value iteration, e la sua forma è inconfondibile: è l’equazione di ottimalità di Bellman trasformata in regola di aggiornamento, esattamente come la iterative policy evaluation era l’equazione di aspettativa trasformata in regola di aggiornamento. In forma compatta, Vk+1=TVkV_{k+1} = T^{*} V_k con TT^{*} operatore di ottimalità di Bellman.

Idea chiave: value iteration elimina la policy dal ciclo: a ogni sweep ogni stato prende direttamente il valore della sua azione migliore rispetto alla stima corrente. Valutazione e miglioramento avvengono simultaneamente dentro il max\max, e l’informazione fluisce verso l’ottimo a ogni sweep, senza sprecare sweep per valutare con precisione policy intermedie.

In parole semplici: invece di “prima misuro bene quanto rende la mia strategia, poi la correggo”, si fa tutto in un colpo: ogni situazione assume subito il valore della sua mossa migliore, ricalcolato a ogni giro. Non esiste più una strategia esplicita durante l’esecuzione; la strategia “implicita” cambia da sola a ogni giro, e alla fine si estrae quella ottima dai valori.

6.2 Convergenza e proprietà#

La convergenza di value iteration discende dalle proprietà di TT^{*} stabilite nel capitolo precedente: per γ<1\gamma < 1, TT^{*} è una γ\gamma-contrazione in norma del massimo e il suo unico punto fisso è VV^{*}. Quindi, per qualunque inizializzazione V0V_0,

VkVγkV0VlimkVk=V\left\lVert V_k - V^{*} \right\rVert_{\infty} \leq \gamma^k \left\lVert V_0 - V^{*} \right\rVert_{\infty} \qquad \Longrightarrow \qquad \lim_{k \to \infty} V_k = V^{*}

La convergenza è geometrica di fattore γ\gamma ma, a differenza di policy iteration, asintotica: in generale nessuna iterata finita coincide esattamente con VV^{*}, e ci si arresta quando la variazione massima di uno sweep scende sotto una soglia θ\theta (con la stessa garanzia sulla distanza residua vista per la policy evaluation). Due osservazioni caratterizzano l’algoritmo:

π(s)=argmaxaA(s)[r(s,a)+γsp(ss,a)V(s)]\pi(s) = \arg\max_{a \in \mathcal{A}(s)} \left[ r(s, a) + \gamma \sum_{s'} p(s' \mid s, a) \, V(s') \right]

Questo passo finale è legittimo proprio perché applicato a (un’approssimazione di) VV^{*}: come stabilito nel capitolo precedente, la policy greedy rispetto alla value function ottima è la policy ottima.

Lo pseudocodice, sensibilmente più semplice di quello di policy iteration (un solo loop invece di due annidati):

Value Iteration
Input: modello (p, r), discount γ, soglia θ > 0

Inizializza V(s) arbitrariamente per ogni s ∈ S (V = 0 sugli stati terminali)
ripeti
    Δ ← 0
    per ogni s ∈ S:
        v ← V(s)
        V(s) ← max_a [ r(s,a) + γ Σ_{s'} p(s'|s,a) V(s') ]
        Δ ← max(Δ, |v − V(s)|)
finché Δ < θ
Output: policy deterministica π(s) = argmax_a [ r(s,a) + γ Σ_{s'} p(s'|s,a) V(s') ]

6.3 Policy iteration e value iteration a confronto#

Aspetto Policy iteration Value iteration
Equazione di Bellman usata aspettativa (valutazione) + greedy (miglioramento) ottimalità, come unico aggiornamento
Struttura del codice due loop annidati (valutazione dentro il ciclo esterno) un solo loop
Policy esplicita durante l’esecuzione sì, aggiornata a ogni iterazione esterna no, estratta solo alla fine
Iterate intermedie VπiV^{\pi_i}: vere value function di policy VkV_k: in generale di nessuna policy
Costo per iterazione alto (valutazione completa, molti sweep) uno sweep, O(S2A)O(\vert \mathcal{S}\vert ^2 \vert \mathcal{A}\vert )
Numero di iterazioni finito, tipicamente piccolo asintotico, errore γk\propto \gamma^k
Convergenza esatta a π\pi^{*} in un numero finito di giri a VV^{*} al limite, arresto a soglia

Nessuno dei due domina l’altro in assoluto: policy iteration fa poche iterazioni costose, value iteration molte iterazioni economiche; quale sia più veloce dipende dal problema. Value iteration ha però il pregio della semplicità e propaga informazione verso l’ottimo a ogni singolo sweep, senza mai “fermarsi a rifinire” la valutazione di una policy provvisoria. Concettualmente, i due algoritmi restano gli estremi dello spettro della generalized policy iteration: valutazione completa a ogni giro da un lato, valutazione troncata a un solo sweep dall’altro, con tutte le vie di mezzo ugualmente legittime.

7. Programmazione dinamica asincrona#

Gli algoritmi visti finora sono sincroni: ogni iterazione esegue uno sweep esaustivo, aggiornando tutti gli stati uno dopo l’altro in un ordine fissato. Su spazi di stati molto grandi questo è un vincolo pesante: un singolo sweep può essere proibitivo, e molti aggiornamenti sono sprecati su stati i cui valori sono già accurati o irrilevanti. La DP asincrona rimuove il vincolo dello sweep: gli stati vengono aggiornati singolarmente, in qualunque ordine, usando ogni volta i valori correnti (aggiornamento in place) degli altri stati. Lo schema generale è:

La convergenza ai valori corretti resta garantita a una condizione: nessuno stato deve essere abbandonato per sempre, cioè ogni stato deve continuare a essere selezionato (tutti gli stati devono essere aggiornati infinite volte, nel limite). All’interno di questo vincolo, la libertà nell’ordine di aggiornamento apre tre opportunità concrete:

La DP asincrona non riduce il costo teorico del problema, ma permette spesso di trovare policy buone con molto meno calcolo di quello richiesto da sweep esaustivi, e di applicare la DP a problemi più grandi di quelli trattabili in forma sincrona.

In parole semplici: non serve rifare tutti i conti su tutta la mappa a ogni giro: si possono aggiornare le caselle una alla volta, in qualsiasi ordine, magari partendo da quelle più sbagliate o da quelle che l’agente incontra davvero. Basta non dimenticarsi per sempre di nessuna casella, e il risultato finale è lo stesso, spesso con molta meno fatica.

8. Efficienza e limiti della programmazione dinamica#

8.1 Complessità computazionale#

Quanto costa la DP? La buona notizia è che trovare una policy ottima con la programmazione dinamica ha costo polinomiale nel numero di stati e di azioni, laddove la ricerca diretta nello spazio delle policy dovrebbe esaminarne AS|\mathcal{A}|^{|\mathcal{S}|}, un numero esponenziale: rispetto alla forza bruta, la DP è esponenzialmente più efficiente. Le stime di riferimento:

In entrambi i casi il fattore 1/(1γ)1/(1-\gamma) segnala che problemi molto lungimiranti (con γ\gamma vicino a 1) sono intrinsecamente più costosi: la contrazione è più lenta e l’informazione deve propagarsi su orizzonti effettivi più lunghi. Esistono anche approcci alternativi alla DP basati sulla programmazione lineare, che riformulano la ricerca di VV^{*} come problema di ottimizzazione lineare; in teoria sono eleganti, ma in pratica scalano peggio della DP al crescere del problema.

8.2 La maledizione della dimensionalità#

La cattiva notizia è che “polinomiale in S|\mathcal{S}|” è una consolazione solo apparente, perché S|\mathcal{S}| stesso è spesso astronomico. Il fenomeno ha un nome: curse of dimensionality (maledizione della dimensionalità). Se lo stato è descritto da nn variabili, ciascuna con dd valori possibili, allora S=dn|\mathcal{S}| = d^n: il numero di stati cresce esponenzialmente con il numero di variabili di stato, non con la loro dimensione fisica. Una scacchiera ha 64 caselle ma circa 104410^{44} configurazioni; un robot con una decina di sensori continui discretizzati ha uno spazio di stati che nessuna tabella può contenere.

≈ 106 stati:portata pratica della DP tabellared = 2d = 5d = 10100103106109101204812n (numero di variabili di stato, ciascuna con d valori)|S| = dn (scala log)

In pratica:

In parole semplici: il costo della DP cresce “solo” come una potenza del numero di stati, ma il numero di stati esplode come una potenza del numero di variabili che descrivono la situazione. Basta aggiungere qualche sensore o qualche caratteristica allo stato e la tabella dei valori diventa più grande di qualunque memoria: è questo, non l’algoritmo, il vero muro.

8.3 Il limite fondamentale: serve il modello#

C’è però un limite ancora più radicale del costo computazionale, ed è visibile in ogni singola formula di questo capitolo: ogni backup di DP richiede r(s,a)r(s, a) e p(ss,a)p(s' \mid s, a), cioè la dinamica one-step completa dell’MDP. La DP non è un metodo di apprendimento ma di pianificazione: calcola la soluzione a partire dalla descrizione perfetta del problema. Nei problemi reali questa descrizione spesso non c’è:

Ciò che invece è quasi sempre disponibile, o generabile con un simulatore, è l’esperienza: traiettorie di stati, azioni e reward osservate interagendo con l’ambiente. I metodi dei prossimi capitoli, detti model-free, ripartono esattamente da qui: mantengono l’architettura concettuale costruita in questo capitolo, la generalized policy iteration, ma sostituiscono i backup esatti sul modello con stime ottenute dai campioni. Il primo rappresentante della famiglia, i metodi Monte Carlo, stima le value function mediando i return effettivamente osservati; questa sostituzione, come si vedrà, porta con sé un problema nuovo e centrale, quello dell’esplorazione. Le equazioni di Bellman e lo schema valutazione-miglioramento restano il filo conduttore: cambia solo il modo di calcolare le aspettative quando il modello non c’è.

Idea chiave: la DP risolve gli MDP alla perfezione, ma a due condizioni che il mondo reale raramente concede: uno spazio di stati abbastanza piccolo da essere spazzato, e un modello completo della dinamica. Il reinforcement learning propriamente detto nasce rinunciando alla seconda condizione: stessi obiettivi, stesse equazioni, ma aspettative stimate dall’esperienza invece che calcolate dal modello.

9. Esempio svolto: value iteration sul robot riciclatore#

Per chiudere il cerchio si applica value iteration, passo per passo, al piccolo MDP del robot riciclatore già risolto analiticamente nel capitolo precedente, di cui si conoscono quindi in anticipo la soluzione ottima e la value function ottima: un banco di prova ideale.

9.1 Il modello e le equazioni di aggiornamento#

attendi1, rattcercaα, rcerca1-α, rcercaricarica1, 0attendi1, rattcercaβ, rcerca1-β, -3(soccorso)altabassa

Richiamo dei dati: stati {A,B}\{A, B\} (batteria alta e bassa), γ=0,9\gamma = 0{,}9. Nello stato AA le azioni sono cerca (reward 22; resta in AA con probabilità 0,90{,}9, scende in BB con probabilità 0,10{,}1) e attendi (reward 11; resta in AA). Nello stato BB le azioni sono cerca (reward atteso 00, perché 0,62+0,4(3)=00{,}6 \cdot 2 + 0{,}4 \cdot (-3) = 0; resta in BB con probabilità 0,60{,}6, con probabilità 0,40{,}4 la batteria si esaurisce e il robot viene soccorso e riportato in AA), attendi (reward 11; resta in BB) e ricarica (reward 00; va in AA). La soluzione nota: la policy ottima è π=(cerca in A, ricarica in B)\pi^{*} = (\text{cerca in } A,\ \text{ricarica in } B), con V(A)18,35V^{*}(A) \approx 18{,}35 e V(B)16,51V^{*}(B) \approx 16{,}51.

L’aggiornamento di value iteration, scritto esplicitamente per i due stati:

Vk+1(A)=max{2+0,9(0,9Vk(A)+0,1Vk(B))cerca, 1+0,9Vk(A)attendi}V_{k+1}(A) = \max \Big\{ \underbrace{2 + 0{,}9 \big( 0{,}9 \, V_k(A) + 0{,}1 \, V_k(B) \big)}_{\text{cerca}}, \ \underbrace{1 + 0{,}9 \, V_k(A)}_{\text{attendi}} \Big\}

Vk+1(B)=max{0,9(0,6Vk(B)+0,4Vk(A))cerca, 1+0,9Vk(B)attendi, 0,9Vk(A)ricarica}V_{k+1}(B) = \max \Big\{ \underbrace{0{,}9 \big( 0{,}6 \, V_k(B) + 0{,}4 \, V_k(A) \big)}_{\text{cerca}}, \ \underbrace{1 + 0{,}9 \, V_k(B)}_{\text{attendi}}, \ \underbrace{0{,}9 \, V_k(A)}_{\text{ricarica}} \Big\}

9.2 Le prime iterazioni a mano#

Si parte da V0=(0,0)V_0 = (0, 0).

Iterazione 1. In AA: cerca dà 2+0,90=22 + 0{,}9 \cdot 0 = 2, attendi dà 11: vince cerca, V1(A)=2V_1(A) = 2. In BB: cerca dà 00, attendi dà 11, ricarica dà 00: vince attendi, V1(B)=1V_1(B) = 1.

Iterazione 2. In AA: cerca dà 2+0,9(0,92+0,11)=2+0,91,9=3,712 + 0{,}9 (0{,}9 \cdot 2 + 0{,}1 \cdot 1) = 2 + 0{,}9 \cdot 1{,}9 = 3{,}71; attendi dà 1+1,8=2,81 + 1{,}8 = 2{,}8: vince cerca, V2(A)=3,71V_2(A) = 3{,}71. In BB: cerca dà 0,9(0,61+0,42)=1,260{,}9 (0{,}6 \cdot 1 + 0{,}4 \cdot 2) = 1{,}26; attendi dà 1+0,9=1,91 + 0{,}9 = 1{,}9; ricarica dà 0,92=1,80{,}9 \cdot 2 = 1{,}8: vince ancora attendi, per un soffio, V2(B)=1,9V_2(B) = 1{,}9.

Iterazione 3. In AA: cerca dà 2+0,9(0,93,71+0,11,9)=2+0,93,5295,182 + 0{,}9 (0{,}9 \cdot 3{,}71 + 0{,}1 \cdot 1{,}9) = 2 + 0{,}9 \cdot 3{,}529 \approx 5{,}18; attendi dà 4,344{,}34: V3(A)5,18V_3(A) \approx 5{,}18. In BB: cerca dà 0,9(0,61,9+0,43,71)2,360{,}9 (0{,}6 \cdot 1{,}9 + 0{,}4 \cdot 3{,}71) \approx 2{,}36; attendi dà 1+1,71=2,711 + 1{,}71 = 2{,}71; ricarica dà 0,93,713,340{,}9 \cdot 3{,}71 \approx 3{,}34: qui avviene il sorpasso, vince ricarica, V3(B)3,34V_3(B) \approx 3{,}34. Il motivo è leggibile: man mano che Vk(A)V_k(A) cresce, il valore di “tornare in AA” cresce con lui, finché il guadagno immediato di attendi (+1+1) non basta più a compensare la rinuncia a trovarsi in AA.

La tabella riassume le prime iterazioni e, per ciascuna VkV_k, la policy greedy che se ne estrarrebbe:

kk Vk(A)V_k(A) Vk(B)V_k(B) greedy in AA greedy in BB
0 0,000{,}00 0,000{,}00 cerca attendi
1 2,002{,}00 1,001{,}00 cerca attendi
2 3,713{,}71 1,901{,}90 cerca ricarica
3 5,185{,}18 3,343{,}34 cerca ricarica
4 6,496{,}49 4,664{,}66 cerca ricarica
5 7,687{,}68 5,845{,}84 cerca ricarica
\infty 18,3518{,}35 16,5116{,}51 cerca ricarica
V*(A) ≈ 18,35V*(B) ≈ 16,51da k = 2 la policy greedy estratta è già π*Vk(A)Vk(B)sweep kVk0

9.3 Che cosa insegna l’esempio#

Tre osservazioni condensano i messaggi del capitolo:

In parole semplici: l’algoritmo scopre quasi subito “che cosa” conviene fare (cercare con batteria alta, ricaricare con batteria bassa) e impiega molto più tempo a stabilire con precisione “quanto vale” farlo. Se l’obiettivo è la strategia, ci si può fermare presto; se servono i valori esatti, si paga la lentezza della contrazione, tanto più cara quanto più γ\gamma è vicino a 1.

Glossario#

Termine Definizione
Programmazione dinamica (DP) Famiglia di metodi che risolve problemi complessi decomponendoli ricorsivamente in sottoproblemi; negli MDP, algoritmi di pianificazione basati sulle equazioni di Bellman con modello noto.
Sottostruttura ottima Proprietà per cui la soluzione ottima si compone dalle soluzioni ottime dei sottoproblemi; negli MDP è espressa dalla ricorsione di Bellman.
Sottoproblemi ricorrenti Proprietà per cui gli stessi sottoproblemi si ripresentano e le soluzioni possono essere memorizzate; negli MDP la value function funge da cache.
Prediction Problema di calcolare VπV^{\pi} dati MDP e policy π\pi.
Control Problema di trovare VV^{*} e π\pi^{*} dato l’MDP.
Iterative policy evaluation Calcolo di VπV^{\pi} applicando ripetutamente l’equazione di aspettativa di Bellman come aggiornamento: Vk+1=TπVkV_{k+1} = T^{\pi} V_k; converge per contrazione da qualunque V0V_0.
Sweep Applicazione dell’aggiornamento di Bellman a tutti gli stati dello spazio, una volta ciascuno.
Backup completo (full-width) Aggiornamento di un singolo stato che considera tutte le azioni e tutti i successori pesati con il modello pp e rr.
Aggiornamento in place Variante con un solo array in cui i valori appena aggiornati sono subito usati nello stesso sweep; converge e di solito accelera.
Policy improvement Costruzione della policy greedy π(s)=argmaxaQπ(s,a)\pi'(s) = \arg\max_a Q^{\pi}(s,a) a partire da VπV^{\pi}; non peggiora mai la policy.
Teorema di policy improvement Se Qπ(s,π(s))Vπ(s)Q^{\pi}(s, \pi'(s)) \geq V^{\pi}(s) per ogni ss, allora Vπ(s)Vπ(s)V^{\pi'}(s) \geq V^{\pi}(s) per ogni ss: un vantaggio a un passo si estende all’intera traiettoria.
Policy iteration Alternanza di valutazione completa e miglioramento greedy: π0Vπ0π1π\pi_0 \to V^{\pi_0} \to \pi_1 \to \cdots \to \pi^{*}; converge esattamente in un numero finito di iterazioni.
Generalized policy iteration (GPI) Cornice generale in cui valutazione e miglioramento interagiscono a qualunque granularità; il punto di equilibrio congiunto è (VV^{*}, π\pi^{*}).
Value iteration Iterazione dell’equazione di ottimalità di Bellman come aggiornamento: Vk+1(s)=maxa[r(s,a)+γsp(ss,a)Vk(s)]V_{k+1}(s) = \max_a [r(s,a) + \gamma \sum_{s'} p(s' \mid s,a) V_k(s')]; converge a VV^{*} per contrazione, policy estratta alla fine.
DP asincrona DP senza sweep esaustivi: aggiornamenti di singoli stati in qualunque ordine (anche in parallelo); converge purché nessuno stato sia trascurato per sempre.
Prioritized sweeping Selezione asincrona degli stati da aggiornare in base alla priorità, tipicamente il modulo dell’errore di Bellman, con propagazione ai predecessori.
Real-time DP DP asincrona guidata dall’esperienza: si aggiornano gli stati effettivamente visitati dall’agente.
Errore di Bellman Scarto maxa[r(s,a)+γsp(ss,a)V(s)]V(s)\lvert \max_a [r(s,a) + \gamma \sum_{s'} p(s' \mid s,a) V(s')] - V(s) \rvert tra il backup e il valore corrente; misura quanto uno stato “ha bisogno” di aggiornamento.
Criterio d’arresto (θ\theta, Δ\Delta) Arresto delle iterazioni quando la variazione massima Δ\Delta in uno sweep scende sotto la soglia θ\theta; la distanza residua da VπV^{\pi} o VV^{*} è controllata dalla contrazione.
Curse of dimensionality Crescita esponenziale di S\vert \mathcal{S}\vert con il numero di variabili di stato, che rende impraticabile la DP tabellare sui problemi grandi.
Model-based / model-free Metodi che richiedono la dinamica one-step (rr, pp), come la DP, contro metodi che apprendono solo dall’esperienza campionata, come Monte Carlo.

Dispensa Machine Learning · Politecnico di Milano