Questo progetto confronta due approcci value-based di Reinforcement Learning su IDSGame (scenario di cyber-defense):
- SARSA(0) con Function Approximation lineare
- Double Deep Q-Network (DDQN)
L’obiettivo è capire come reward shaping e feature engineering influenzino stabilità e performance, e perché un algoritmo “più potente” (DDQN) possa performare peggio se alimentato con input troppo semplificati.
- Approssimazione di Q(s,a) con pesi W[a, :] su feature 1D
- Training on-policy con ε-greedy
- Valutazione periodica greedy e visualizzazione dei pesi appresi (heatmap)
- Replay Buffer
- Policy network e Target network
- Aggiornamento DDQN (azione migliore dalla policy, valore dalla target)
- Rete neurale MLP semplice: Linear → ReLU → Linear → ReLU → Linear
Ho introdotto un wrapper dedicato per gestire differenze tra API vecchie/nuove di Gym e normalizzare:
reset()/step()- conversione dello stato in
np.ndarraycoerente
In ambienti con reward sparsi, il reward shaping rende l’apprendimento più stabile:
- penalità forte se
hacked - reward positivo se “safe”
- reward denso legato alla variazione di vulnerabilità nello stato
Nel notebook viene usata extract_state_features(state) che trasforma lo stato 2D (4×5) in 11 feature:
- 4 medie per nodo (righe)
- 5 medie per attributo (colonne)
- totale medio + bias
✅ Questo è molto efficace per SARSA lineare (feature “buone” e compatte).
| Metodo | Reward medio / valutazione | Note |
|---|---|---|
| Baseline | ~ -100 | comportamento scarso |
| SARSA-FA | 32.70 | miglioramento netto: feature lineari efficaci |
| DDQN | ~ -21 | meglio del baseline, ma molto sotto SARSA-FA |
Il problema non sembra l’algoritmo (DDQN è teoricamente superiore), ma l’implementazione specifica:
- rete troppo basilare
- input 1D troppo aggregato → la rete non può imparare rappresentazioni complesse
- usare lo stato intero
(4,5)come input - sostituire MLP con CNN (stile Nature DQN) per catturare struttura spaziale
- rimuovere dipendenza da variabili globali in DDQN (
LR,MEMORY_SIZE, ecc.)- passare hyperparams nel costruttore o in un oggetto
Config(dataclass)
- passare hyperparams nel costruttore o in un oggetto
- spezzare
sarsa_linear_fa_train:- creare classe
SARSALinearFAAgent - separare update pesi, selection policy, evaluation loop
- creare classe