Un progetto di reinforcement learning che dimostra come un agente impara a raggiungere un obiettivo usando l'algoritmo Q-learning.
- Ambiente: Griglia 10x10 con agente, obiettivo e ostacoli
- Algoritmo: Q-learning con Q-table
- Visualizzazione: Interfaccia grafica in tempo reale
- Controlli: Pulsanti per training e inferenza
- Statistiche: Monitoraggio del progresso dell'apprendimento
- Apri
index.html
nel browser - Clicca "Inizia Training" per far imparare l'agente
- Attendi che il training sia completato (1000 episodi)
- Clicca "Mostra Inferenza" per vedere l'agente applicare la conoscenza appresa
- Usa "Reset" per ricominciare da capo
- 🔴 Agente (cerchio rosso): Deve imparare a raggiungere l'obiettivo
- 🟢 Obiettivo (cerchio verde): Da raggiungere per ottenere ricompensa (+100)
- ⚫ Ostacoli (cerchi neri): Da evitare (penalità -10)
- ⬜ Spazio libero: Movimento consentito (penalità -1 per step)
- Learning Rate: 0.1
- Discount Factor: 0.95
- Epsilon iniziale: 1.0 (esplorazione al 100%)
- Epsilon finale: 0.01 (esplorazione all'1%)
- Epsilon Decay: 0.995
- Max Episodi: 1000
- Max Steps per episodio: 100
- Stati: Posizioni (x,y) nella griglia 10×10 = 100 stati possibili
- Azioni: 4 movimenti possibili (su, giù, sinistra, destra)
- Spazio di osservazione: Posizione corrente dell'agente
- Dinamiche: Regole di movimento e collisioni
- Obiettivo raggiunto: +100 punti (rinforzo positivo forte)
- Ostacoli/Muri: -10 punti (penalità per errori)
- Ogni passo: -1 punto (incoraggia efficienza)
- Bilanciamento: Ricompense progettate per guidare l'apprendimento
- Dimensioni: 100 stati × 4 azioni = 400 valori Q
- Valori iniziali: Tutti inizializzati a 0
- Struttura:
qTable[stato][azione] = valore_Q
- Epsilon iniziale: 1.0 (100% esplorazione casuale)
- Epsilon finale: 0.01 (1% esplorazione, 99% exploitation)
- Decay: 0.995 per episodio (riduzione graduale)
- Bilanciamento: Esplorazione → Exploitation nel tempo
Q(s,a) = Q(s,a) + α × [r + γ × max(Q(s',a')) - Q(s,a)]
- α (Learning Rate): 0.1 - velocità di apprendimento
- γ (Discount Factor): 0.95 - importanza del futuro
🔴 INIZIO EPISODIO N:
resetAgent()
- Agente torna a posizione (0,0)clearPathTrail()
- Pulisce la traccia visivastepCount = 0
- Reset contatore passiaddToPathTrail(0,0)
- Segna posizione iniziale
STEP 1 - OSSERVAZIONE:
let currentState = getStateString(agentPos.x, agentPos.y); // es: "3,7"
STEP 2 - SCELTA AZIONE (ε-greedy):
if (Math.random() < epsilon) {
// ESPLORAZIONE: azione casuale
action = Math.floor(Math.random() * 4);
} else {
// EXPLOITATION: migliore azione conosciuta
let qValues = qTable[currentState]; // [0.2, -0.5, 1.3, 0.8]
action = indexOfMax(qValues); // sceglie azione con Q-value più alto
}
STEP 3 - ESECUZIONE AZIONE:
let newX = agentPos.x + actions[action].x; // nuova coordinata X
let newY = agentPos.y + actions[action].y; // nuova coordinata Y
// Controlla validità movimento
if (isValidPosition(newX, newY)) {
agentPos.x = newX;
agentPos.y = newY;
addToPathTrail(newX, newY); // Aggiorna traccia visiva
}
STEP 4 - CALCOLO RICOMPENSA:
let reward = getReward(agentPos.x, agentPos.y);
// Possibili valori:
// +100 se raggiunge obiettivo (9,9)
// -10 se va su ostacolo o fuori griglia
// -1 per movimento normale (costo del tempo)
STEP 5 - AGGIORNAMENTO Q-TABLE (BELLMAN):
let oldQ = qTable[currentState][action]; // Q-value precedente
let newState = getStateString(agentPos.x, agentPos.y);
let maxNewQ = Math.max(...qTable[newState]); // Miglior Q-value nel nuovo stato
let newQ = oldQ + 0.1 * (reward + 0.95 * maxNewQ - oldQ); // Bellman!
qTable[currentState][action] = newQ; // Aggiorna conoscenza
STEP 6 - CONTROLLO FINE EPISODIO:
if (agentPos.x === 9 && agentPos.y === 9) {
// 🎯 SUCCESSO! Obiettivo raggiunto
successes++;
scores.push(stepCount);
episodeEnded = true;
} else if (stepCount >= 100) {
// ⏰ TIMEOUT! Troppi passi
scores.push(-stepCount);
episodeEnded = true;
}
if (episodeEnded) {
episodeCount++;
epsilon = Math.max(0.01, epsilon * 0.995); // Riduce esplorazione
resetAgent(); // Torna a (0,0) per nuovo episodio
updateStats(); // Aggiorna statistiche visuali
}
EPISODI 1-100:
- ε ≈ 0.9 → Esplorazione quasi totale, movimenti casuali
- Q-table piena di valori quasi zero
- Successi rari e casuali
EPISODI 100-500:
- ε ≈ 0.6 → Inizia a usare conoscenza appresa
- Alcuni Q-values diventano positivi verso l'obiettivo
- Aumento graduale del tasso di successo
EPISODI 500-1000:
- ε ≈ 0.1 → Prevalentemente exploitation
- Q-table converge verso politica ottimale
- Percorsi sempre più diretti ed efficienti
🎯 OBIETTIVO: Dimostrare la politica ottimale appresa senza più esplorare
epsilon = 0; // ZERO esplorazione, solo exploitation
isInference = true; // Modalità inferenza attivata
isPaused = false; // Reset stato pausa
resetAgent(); // Parte da (0,0)
OGNI STEP DI INFERENZA:
STEP 1 - OSSERVAZIONE:
let currentState = getStateString(agentPos.x, agentPos.y); // es: "4,2"
STEP 2 - SCELTA AZIONE (SOLO EXPLOITATION):
// NESSUNA esplorazione casuale!
let qValues = qTable[currentState]; // [0.8, -0.2, 2.3, 1.1]
let maxQ = Math.max(...qValues); // 2.3
let bestActions = [];
for (let i = 0; i < qValues.length; i++) {
if (qValues[i] === maxQ) {
bestActions.push(i); // [2] (azione "sinistra")
}
}
action = bestActions[Math.floor(Math.random() * bestActions.length)];
STEP 3 - ESECUZIONE AZIONE:
let newX = agentPos.x + actions[action].x;
let newY = agentPos.y + actions[action].y;
if (isValidPosition(newX, newY)) {
agentPos.x = newX;
agentPos.y = newY;
addToPathTrail(newX, newY); // Traccia BLU per inferenza
}
STEP 4 - NESSUN APPRENDIMENTO:
// ❌ NON aggiorna Q-table!
// ❌ NON calcola reward per apprendimento!
// ✅ Solo esecuzione della politica appresa
STEP 5 - CONTROLLO OBIETTIVO:
if (agentPos.x === 9 && agentPos.y === 9) {
// 🎯 SUCCESSO! Attiva celebrazione
isPaused = true;
pauseStartTime = millis();
// Mostra messaggio verde: "🎯 OBIETTIVO RAGGIUNTO!"
// Countdown 3 secondi: "Riavvio in 3... 2... 1..."
} else if (stepCount >= 100) {
// ⏰ TIMEOUT: Reset immediato (non dovrebbe succedere se ben addestrato)
resetAgent();
}
function handleInferencePause() {
if (millis() - pauseStartTime >= 3000) { // 3 secondi di pausa
isPaused = false;
resetAgent(); // Nuovo tentativo da (0,0)
// Ciclo infinito: dimostra ripetutamente la soluzione ottimale
}
}
- Traccia BLU: Percorso durante inferenza (vs rosso in training)
- Movimento più lento:
frameCount % 10
(vsframeCount % 3
in training) - Percorso diretto: Dovrebbe seguire il percorso ottimale appreso
- Celebrazione: Schermo verde + countdown quando raggiunge obiettivo
Aspetto | Training | Inferenza |
---|---|---|
Epsilon | 1.0 → 0.01 | 0.0 (fisso) |
Azioni | Casuali + Ottime | Solo Ottime |
Apprendimento | ✅ Aggiorna Q-table | ❌ Nessun aggiornamento |
Traccia | 🟥 Rossa | 🟦 Blu |
Velocità | Veloce | Più lenta (osservabile) |
Reset | Automatico | Pausa celebrativa |
Episodi | 1000 fissi | Infiniti |
- Percorso ottimale: Linea diretta verso obiettivo
- Consistenza: Stesso percorso ogni volta
- Efficienza: Minimo numero di passi possibile
- Successo garantito: 100% tasso di successo (se ben addestrato)
Buon addestramento:
- Percorso diretto e consistente
- Raggiunge obiettivo in ~18 passi
- Evita completamente ostacoli
Addestramento insufficiente:
- Movimenti non ottimali
- Occasionali "esitazioni"
- Percorsi più lunghi del necessario
- Episodio corrente: Numero di episodi completati
- Punteggio medio: Media degli ultimi 100 episodi
- Tasso di successo: Percentuale di episodi che raggiungono l'obiettivo
- Epsilon: Livello attuale di esplorazione
- Modalità: Stato corrente (Pronto/Training/Inferenza)
Contiene tutta la logica del Q-learning:
- Gestione dell'ambiente e rendering
- Implementazione dell'algoritmo Q-learning
- Controllo dei pulsanti e aggiornamento delle statistiche
- Logiche di training e inferenza
Interfaccia utente con:
- Canvas p5.js per la visualizzazione
- Pulsanti di controllo
- Pannello delle statistiche
- Styling CSS
Il Q-learning è un algoritmo di reinforcement learning che impara una funzione Q(s,a) che rappresenta la "qualità" di eseguire l'azione a
nello stato s
.
Q(s,a) = Q(s,a) + α × [r + γ × max(Q(s',a')) - Q(s,a)]
Dove:
α
= learning rate (quanto velocemente si apprende)r
= ricompensa immediataγ
= discount factor (importanza delle ricompense future)s'
= nuovo statoa'
= possibili azioni nel nuovo stato
- Con probabilità
ε
: scegli azione casuale (esplorazione) - Con probabilità
1-ε
: scegli migliore azione conosciuta (exploitation)
L'agente inizia con molta esplorazione (ε=1.0) e gradualmente riduce l'esplorazione man mano che impara (ε→0.01).
Puoi modificare facilmente:
- Dimensione della griglia (
gridSize
) - Posizioni di agente, obiettivo e ostacoli
- Parametri di Q-learning (learning rate, discount factor, ecc.)
- Ricompense e penalità
- Velocità di visualizzazione
- Ricompensa finale elevata: Incentiva il raggiungimento dell'obiettivo
- Penalità moderate: Evita comportamenti indesiderati senza bloccare l'esplorazione
- Costo del tempo: Piccola penalità per step incoraggia efficienza
- Learning Rate (α): 0.1-0.3 per apprendimento stabile
- Discount Factor (γ): 0.9-0.99 per bilanciare presente/futuro
- Epsilon Decay: Lento per problemi complessi, veloce per semplici
- Tasso di successo: Percentuale di episodi che raggiungono l'obiettivo
- Score medio: Efficienza degli episodi recenti
- Stabilità: Variazioni minime nelle performance
- Visualizzazione del percorso: Tracce colorate per capire il comportamento
- Salvataggio Q-table: Conserva l'addestramento per test multipli
- Parametri adattivi: Epsilon decay e learning rate variabili
- p5.js: Libreria per la visualizzazione e l'animazione
- HTML/CSS/JavaScript: Interfaccia utente e logica
- Q-learning: Algoritmo di reinforcement learning