Deep Q-Learning con Space Invaders

Deep Q-Learning con Space Invaders

Unità 3, della classe di Deep Reinforcement Learning con Hugging Face 🤗

⚠️ È disponibile una nuova versione aggiornata di questo articolo qui 👉 https://huggingface.co/deep-rl-course/unit1/introduction

Questo articolo fa parte della classe di Deep Reinforcement Learning. Un corso gratuito dalla base all’esperto. Controlla il programma qui.


⚠️ È disponibile una nuova versione aggiornata di questo articolo qui 👉 https://huggingface.co/deep-rl-course/unit1/introduction

Questo articolo fa parte della classe di Deep Reinforcement Learning. Un corso gratuito dalla base all’esperto. Controlla il programma qui.

Nell’ultima unità, abbiamo imparato il nostro primo algoritmo di reinforcement learning: Q-Learning, implementato da zero, e lo abbiamo addestrato in due ambienti, FrozenLake-v1 ☃️ e Taxi-v3 🚕.

Abbiamo ottenuto ottimi risultati con questo semplice algoritmo. Ma questi ambienti erano relativamente semplici perché lo spazio di stato era discreto e piccolo (14 stati diversi per FrozenLake-v1 e 500 per Taxi-v3).

Ma come vedremo, produrre e aggiornare una tabella Q può diventare inefficace in ambienti con uno spazio di stato ampio.

Quindi oggi, <strong-studieremo il nostro primo agente di Deep Reinforcement Learning: Deep Q-Learning. Invece di utilizzare una tabella Q, Deep Q-Learning utilizza una rete neurale che prende uno stato e approssima i valori Q per ogni azione basata su quello stato.

E lo addestreremo a giocare a Space Invaders e ad altri ambienti Atari utilizzando RL-Zoo, un framework di addestramento per RL che utilizza Stable-Baselines e fornisce script per l’addestramento, la valutazione degli agenti, l’ottimizzazione degli iperparametri, la visualizzazione dei risultati e la registrazione di video.

Quindi iniziamo! 🚀

Per essere in grado di capire questa unità, devi prima comprendere il Q-Learning.

  • Dal Q-Learning al Deep Q-Learning
  • La rete Deep Q
    • Elaborazione dell’input e limitazione temporale
  • L’algoritmo Deep Q-Learning
    • Experience Replay per un uso più efficiente delle esperienze
    • Q-Target fisso per stabilizzare l’addestramento
    • Double DQN

Dal Q-Learning al Deep Q-Learning

Abbiamo imparato che il Q-Learning è un algoritmo che utilizziamo per addestrare la nostra Q-Function, una funzione valore-azione che determina il valore di trovarsi in uno stato particolare e prendere un’azione specifica in quel stato.

Date uno stato e un'azione, la nostra Q Function restituisce un valore stato-azione (chiamato anche valore Q)

Il Q deriva dalla “qualità” di quell’azione in quello stato.

Internamente, la nostra Q-function ha una tabella Q, una tabella in cui ogni cella corrisponde a una coppia stato-azione. Pensate a questa tabella Q come la memoria o la “spiegazione” della nostra Q-function.

Il problema è che il Q-Learning è un metodo tabulare. Anche detto, un problema in cui gli spazi di stato e azioni sono abbastanza piccoli da poter approssimare le funzioni di valore da rappresentare come array e tabelle. E questo non è scalabile.

Il Q-Learning funzionava bene con ambienti con spazi di stato ridotti come:

  • FrozenLake, avevamo 14 stati.
  • Taxi-v3, avevamo 500 stati.

Ma pensate a quello che faremo oggi: addestreremo un agente a imparare a giocare a Space Invaders utilizzando i fotogrammi come input.

Come <strong-ha menzionato Nikita Melkozerov, gli ambienti Atari hanno uno spazio di osservazione con una forma di (210, 160, 3), contenente valori compresi tra 0 e 255, quindi otteniamo 256^(210x160x3) = 256^100800 (a titolo di confronto, ci sono circa 10^80 atomi nell’universo osservabile).

Quindi, lo spazio degli stati è gigantesco; pertanto creare e aggiornare una tabella Q per quell’ambiente non sarebbe efficiente. In questo caso, la migliore idea è approssimare i valori Q invece di una tabella Q utilizzando una funzione Q parametrizzata Q θ ( s , a ) Q_{\theta}(s,a) Q θ ​ ( s , a ) .

Questa rete neurale approssimerà, dato uno stato, i diversi valori Q per ogni possibile azione nello stato. Ed è esattamente ciò che fa Deep Q-Learning.

Ora che abbiamo compreso il Deep Q-Learning, immergiamoci ancora di più nella Deep Q-Network.

La Deep Q-Network (DQN)

Questa è l’architettura della nostra rete Deep Q-Learning:

Come input, prendiamo uno stack di 4 frame passato attraverso la rete come stato e produciamo un vettore di valori Q per ogni possibile azione nello stato. Quindi, come con il Q-Learning, dobbiamo solo utilizzare la nostra politica epsilon-greedy per selezionare quale azione intraprendere.

Quando la rete neurale viene inizializzata, la stima del valore Q è terribile. Ma durante l’addestramento, il nostro agente Deep Q-Network assocerà una situazione con l’azione appropriata e imparerà a giocare bene al gioco.

Preelaborazione dell’input e limitazione temporale

Abbiamo accennato che preelaboriamo l’input. È un passaggio essenziale poiché vogliamo ridurre la complessità del nostro stato per ridurre il tempo di calcolo necessario per l’addestramento.

Quindi ciò che facciamo è ridurre lo spazio degli stati a 84×84 e convertirlo in scala di grigi (poiché i colori negli ambienti Atari non aggiungono informazioni importanti). Questo è un risparmio essenziale poiché riduciamo i nostri tre canali di colore (RGB) a 1.

Possiamo anche ritagliare una parte dello schermo in alcuni giochi se non contiene informazioni importanti. Poi impiliamo quattro frame insieme.

Perché impiliamo quattro frame insieme? Impiliamo i frame insieme perché ci aiuta a gestire il problema della limitazione temporale. Prendiamo ad esempio il gioco del Pong. Quando vedi questo frame:

Puoi dirmi dove va la palla? No, perché un frame non è sufficiente per avere una percezione del movimento! Ma se aggiungo altri tre frame? Qui puoi vedere che la palla si sta dirigendo verso destra.

Ecco perché, per catturare informazioni temporali, impiliamo quattro frame insieme.

Successivamente, i frame impilati vengono elaborati da tre strati convoluzionali. Questi strati ci consentono di catturare ed utilizzare relazioni spaziali nelle immagini. Ma anche, poiché i frame sono impilati insieme, puoi sfruttare alcune proprietà spaziali tra quei frame.

Infine, abbiamo un paio di strati completamente connessi che generano un valore Q per ogni possibile azione nello stato.

Quindi, vediamo che Deep Q-Learning utilizza una rete neurale per approssimare, dato uno stato, i diversi valori Q per ogni possibile azione nello stato. Ora studiamo l’algoritmo Deep Q-Learning.

L’algoritmo Deep Q-Learning

Abbiamo appreso che Deep Q-Learning utilizza una rete neurale profonda per approssimare i diversi valori Q per ogni possibile azione in uno stato (stima della funzione valore).

La differenza è che, durante la fase di addestramento, anziché aggiornare direttamente il valore Q di una coppia stato-azione come abbiamo fatto con il Q-Learning:

In Deep Q-Learning, creiamo una funzione di perdita tra la nostra previsione del valore Q e il Q-target e utilizziamo la discesa del gradiente per aggiornare i pesi della nostra Deep Q-Network per approssimare meglio i nostri valori Q.

L’algoritmo di addestramento Deep Q-Learning ha due fasi:

  • Campionamento: eseguiamo azioni e memorizziamo le tuple di esperienze osservate in una memoria di riproduzione.
  • Addestramento: selezioniamo una piccola batch di tuple casualmente e impariamo da essa utilizzando un passo di aggiornamento del gradiente discendente.

Ma questo non è l’unico cambiamento rispetto al Q-Learning. L’addestramento Deep Q-Learning potrebbe soffrire di instabilità, principalmente a causa della combinazione di una funzione di valore Q non lineare (rete neurale) e del bootstrapping (quando aggiorniamo i target con stime esistenti e non con un ritorno completo effettivo).

Per aiutarci a stabilizzare l’addestramento, implementiamo tre diverse soluzioni:

  1. Riproduzione delle esperienze, per fare un uso più efficiente delle esperienze.
  2. Q-Target fisso per stabilizzare l’addestramento.
  3. Double Deep Q-Learning, per gestire il problema della sovrastima dei valori Q.

Riproduzione delle esperienze per fare un uso più efficiente delle esperienze

Perché creiamo una memoria di riproduzione?

La riproduzione delle esperienze nel Deep Q-Learning ha due funzioni:

  1. Fare un uso più efficiente delle esperienze durante l’addestramento.
  • La riproduzione delle esperienze ci aiuta a fare un uso più efficiente delle esperienze durante l’addestramento. Di solito, nell’apprendimento per rinforzo online, interagiamo con l’ambiente, otteniamo esperienze (stato, azione, ricompensa e stato successivo), impariamo da esse (aggiorniamo la rete neurale) e le scartiamo.
  • Ma con la riproduzione delle esperienze, creiamo un buffer di riproduzione che salva campioni di esperienze che possiamo riutilizzare durante l’addestramento.

⇒ Questo ci consente di imparare dalle singole esperienze più volte.

  1. Evitare di dimenticare le esperienze precedenti e ridurre la correlazione tra esperienze.
  • Il problema che otteniamo se diamo campioni sequenziali di esperienze alla nostra rete neurale è che tende a dimenticare le esperienze precedenti mentre sovrascrive nuove esperienze. Ad esempio, se siamo nel primo livello e poi nel secondo, che è diverso, il nostro agente può dimenticare come comportarsi e giocare nel primo livello.

La soluzione è creare un buffer di riproduzione che memorizzi tuple di esperienze durante l’interazione con l’ambiente e quindi campionare una piccola batch di tuple. Questo impedisce alla rete di imparare solo su ciò che ha appena fatto.

La riproduzione delle esperienze ha anche altri vantaggi. Campionando casualmente le esperienze, rimuoviamo la correlazione nelle sequenze di osservazioni e evitiamo che i valori delle azioni oscillino o divergano catastroficamente.

Nel pseudocodice del Deep Q-Learning, vediamo che iniziamo una memoria di riproduzione D con una capacità N (N è un iperparametro che puoi definire). Poi memorizziamo le esperienze nella memoria e campioniamo una minibatch di esperienze da alimentare alla Deep Q-Network durante la fase di addestramento.

Q-Target fisso per stabilizzare l’addestramento

Quando vogliamo calcolare l’errore di TD (detto anche perdita), calcoliamo la differenza tra il target TD (Q-Target) e il valore Q corrente (stima di Q).

Ma non abbiamo alcuna idea del vero target TD. Dobbiamo stimarlo. Utilizzando l’equazione di Bellman, abbiamo visto che il target TD è semplicemente la ricompensa di compiere quell’azione in quello stato più il valore Q scontato più alto per lo stato successivo.

Tuttavia, il problema è che stiamo usando gli stessi parametri (pesi) per stimare il target TD e il valore Q. Di conseguenza, c’è una significativa correlazione tra il target TD e i parametri che stiamo modificando.

Quindi, significa che ad ogni passo di addestramento, i nostri valori Q si spostano ma anche il valore target si sposta. Quindi, ci stiamo avvicinando al nostro obiettivo, ma l’obiettivo si sta anche muovendo. È come inseguire un obiettivo in movimento! Questo ha portato a una significativa oscillazione nell’addestramento.

È come se tu fossi un cowboy (la stima di Q) e volessi catturare la mucca (l’obiettivo Q), devi avvicinarti (ridurre l’errore).

Ad ogni passo temporale, stai cercando di avvicinarti alla mucca, che si sposta anche ad ogni passo temporale (perché usi gli stessi parametri).

Questo porta a un percorso bizzarro di inseguimento (una significativa oscillazione nell’addestramento).

Invece, quello che vediamo nel pseudo-codice è che:

  • Utilizziamo una rete separata con un parametro fisso per stimare il TD Target
  • Copiamo i parametri dalla nostra Deep Q-Network ad ogni passo C per aggiornare la rete target.

Double DQN

I Double DQN, o Double Learning, sono stati introdotti da Hado van Hasselt. Questo metodo gestisce il problema della sovrastima dei valori Q.

Per capire questo problema, ricordiamo come calcoliamo il TD Target:

Affrontiamo un problema semplice calcolando il TD target: come possiamo essere sicuri che l’azione migliore per lo stato successivo sia l’azione con il valore Q più alto?

Sappiamo che l’accuratezza dei valori Q dipende dall’azione che abbiamo provato e dagli stati vicini che abbiamo esplorato.

Di conseguenza, non abbiamo informazioni sufficienti sull’azione migliore da intraprendere all’inizio dell’addestramento. Pertanto, prendere il valore Q massimo (che è rumoroso) come l’azione migliore da intraprendere può portare a falsi positivi. Se le azioni non ottimali vengono regolarmente assegnate un valore Q più alto rispetto all’azione migliore ottimale, l’apprendimento sarà complicato.

La soluzione è: quando calcoliamo il Q target, utilizziamo due reti per separare la selezione dell’azione dalla generazione del valore Q target. Noi:

  • Utilizziamo la nostra rete DQN per selezionare l’azione migliore da intraprendere per lo stato successivo (l’azione con il valore Q più alto).
  • Utilizziamo la nostra rete target per calcolare il valore Q target dell’azione presa nello stato successivo.

Quindi, il Double DQN ci aiuta a ridurre la sovrastima dei valori q e, di conseguenza, ci aiuta ad addestrare più velocemente e ad avere un apprendimento più stabile.

Dal momento che sono state apportate queste tre migliorie al Deep Q-Learning, ne sono state aggiunte molte altre come la Prioritized Experience Replay, il Dueling Deep Q-Learning. Tuttavia, sono al di fuori dello scopo di questo corso, ma se sei interessato, controlla i link che abbiamo inserito nell’elenco delle letture. 👉 https://github.com/huggingface/deep-rl-class/blob/main/unit3/README.md

Ora che hai studiato la teoria dietro al Deep Q-Learning, sei pronto per addestrare il tuo agente di Deep Q-Learning a giocare ai giochi Atari. Inizieremo con Space Invaders, ma potrai utilizzare qualsiasi gioco Atari tu voglia 🔥

Stiamo utilizzando l’integrazione RL-Baselines-3 Zoo, una versione base di Deep Q-Learning senza estensioni come Double-DQN, Dueling-DQN e Prioritized Experience Replay.

Inizia il tutorial qui 👉 https://colab.research.google.com/github/huggingface/deep-rl-class/blob/main/unit3/unit3.ipynb

La classifica per confrontare i tuoi risultati con quelli dei tuoi compagni di classe 🏆 👉 https://huggingface.co/spaces/chrisjay/Deep-Reinforcement-Learning-Leaderboard


Congratulazioni per aver completato questo capitolo! C’era molta informazione. E congratulazioni per aver completato il tutorial. Hai appena addestrato il tuo primo agente di Deep Q-Learning e lo hai condiviso sul Hub 🥳.

È normale se ti senti ancora confuso con tutti questi elementi. È stato lo stesso per me e per tutte le persone che hanno studiato RL.

Prenditi il tempo necessario per comprendere davvero il materiale prima di continuare.

Non esitare a allenare il tuo agente in altri ambienti (Pong, Seaquest, QBert, Ms Pac Man). Il modo migliore per imparare è provare da soli!

Abbiamo pubblicato letture aggiuntive nel programma se vuoi approfondire 👉 https://github.com/huggingface/deep-rl-class/blob/main/unit3/README.md

Nella prossima unità, impareremo i metodi dei Policy Gradients.

E non dimenticare di condividere con i tuoi amici che vogliono imparare 🤗!

In conclusione, vogliamo migliorare e aggiornare il corso in modo iterativo con il tuo feedback. Se ne hai, compila questo modulo 👉 https://forms.gle/3HgA7bEHwAmmLfwh9

Continua a imparare, resta fantastico,