Q-learning con processing.org
Il reinforcement learning (o apprendimento con rinforzo) è una approcio che appartiene alla categoria dei sistemi intelligenti e che si applica a tutte quelle casistiche nelle quali un agente deve esplorare ed interagire con l’ambiente circostante.
Il principio base che sottende tutti gli algoritmi di reinforcement learning è lo stesso: ad ogni interazione con l’ambiente circostante l’agente viene premiato o punito a seconda dell’azione intrapresa in quel particolare stato. A fronte di questi premi/punizioni l’agente impara col tempo a collezionare il maggior numero di premi possibili evitando le punizioni.
Possiamo formalizzare quanto appena enunciato come segue: dato un’insieme di stati S={s0,s1…,sn}, un’insieme di azioni A={a1,a2…,am} dobbiamo trovare una corrispondenza stato-azione (detta policy p[s,a] ) in modo da massimizzare il reward R={r1,r2…,rl} che l’ambiente ci fornisce ogniqualvolta in un determinato stato eseguiamo una determinata azione.
Chiaramente a questo enunciato devono seguire alcune considerazioni (che ci porteranno poi alla stesura dell’algoritmo Q-learning), ad esempio risulta ovvio pensare che se dall’azione che eseguo all’istante t ottengo una punizione questa non sarà (probabilmente) legata solo a quello che ho scelto di fare in quell’istante ma anche da tutte le scelte che ho fatto prima.
Ecco dunque che nasce la necessità di aggiungere una nuova definizone a quanto già espresso precedentemente, definiamo q[s,a] come la misura del premio/punizione che mi dovrebbe attendere a lungo termine se intraprendo quella azione in quello stato. Quindi una q[s,a] abbastanza alta dovrebbe rassicurare il mio agente e fargli intraprendere quell’azione in quanto, se prendiamo come esempio gli scacchi, poche mosse dopo quella che stò per fare potrei vincere.
Ottenere un buon indicatore di questa q non è esattamente facile. Per farlo deve necessariamente esplorare l’ambiente in modo da collezionare un po di ‘esperienza’ sul campo, esperienza che poi potrò utilizzare proprio per stillare la policy (perchè unendo i concetti fin qui esposti risulta ben chiaro che se dovessi mai avere la q ‘perfetta’ per ogni copia di stato/azione la mia policy si risolverebbe nell’eseguire di volta in volta l’azione con la q più alta per quello stato).
L’algoritmo Q-learning che stò per enunciare unisce il concetto di ‘calcolo della q’ al concetto di ‘elaborazione della policy’ semplicemente accontentandosi di volta in volta di scelgiere l’azione con la q più alta tra quelle disponibili in quello stato e successivamente di retro-modificare la q scelta incrementandola se l’azione (e quelle successive) hanno portato ad un premio e decrementandola viceversa.
In questo modo dopo un certo numero di ‘episodi’ la q che l’agente si è calcolato dovrebbe essere almeno vicina a quella reale.
Scrivo ora l’algoritmo del Q-learning cosi come descritto nei paragrafi precedenti:
Variabili iniziali:
S = {s1,s2,...sn} # Stati (ad esempio in un labirinto ogni casella)
A ={a1,a2,...an} # Azioni (potrebbero non esserci tutte per ogni stato, in un labirinto
# potrebbero essere su, giu, sx, dx)
Setup iniziale:
q = 0 # Per ogni coppia di stato/azione
r = 0 # Per ogni coppia di stato/azione imposto il reward a zero
imposta_reward() # Per ogni coppia di stato azione significativa ( ad esempio in un
# labirinto l'uscita) imposto un
# reward diverso dallo zero ( ad esempio uscita: +10, rovi: -5 )
stati_terminali = s1,s2 # Vanno identificati gli stati terminali (quelli in cui,
# cioè l'episodio finisce - ad esempio l'uscaita dal labirinto)
stato_corrente = stato_inizale # Va impostato uno stato iniziale
azione_corrente = azione_iniziale # Va impostata la prima azione
alpha = xx # costante, indica quanto la variazione dei q futuri incida sul q
# corrente
gamma = xx # costante, indica quanto 'ridimensionare' la variazione dei q futuri
Algoritmo:
Finche la policy non converge:
prossimo_stato = recupera_prossimo_stato(stato_corrente,azione_corrente)
reward = recupera_reward(stato_corrente,azione_corrente)
prossima_azione = recupera_l_azione_col_q_maggiore(prossimo_stato)
q[stato_corrente,azione_corrente] = q[stato_corrente,azione_corrente] + alpha * ( reward +
gamma * q[prossimo_stato,prossima_azione] -
q[stato_corrente,azione_corrente])
# se prossimo_stato è una stato terminale stato_corrente deve tornare ad
# essere stato_iniziale a meno che la policy non si sia stabilizzata.
stato_corrente = prossimo_stato
azione_corrente = prossima_azione
end
Ho implementato questo algoritmo in Processing.org ma a differenza del post precedente non posso visualizzarlo nel browser in quanto computazionalmente è troppo impegnativo; potere comunque scaricarlo dal mio accounti di GitHub.
Ecco la spiegazione del programma: il quadrato arancio è lo stato terminale, e frutta al nostro agente +1 di ricompensa, i bordi invece quando colpiti fruttano -1 (quindi l’agente tenderà ad evitarli). Dopo qualche minuto dovreste cominciare a notare dei cambiamenti di colore sulla griglia, le celle con q negativo tendono a colorarsi di blu mentre quelle con q positivo tendono ad un viola molto acceso.
L’agente è rappresentato da un quadrato verde e viene disegnato con un scia al seguito; tale scia rappresenta (e lo vedremo meglio la prossima volta) il modo in cui la variazione di q si distribuisce sulle scelte precedenti.
Se avete la pazienza di attendere 5-6 minuti dovreste scorgere con chiarezza una specie di ‘percorso più chiaro’, rappresentato da tutte quelle celle che hanno un q positivo, che parte dallo stato iniziale e guida l’agente verso quello terminale.
Scarica Q-learning con Processing.org dal mio account di GitHub
Tags: Apprendimento con Rinforzo, Processing, Q-learning, Reinforcement Learning