Vai al contenuto principale

Reinforcement Learning con Gymnasium: una guida pratica

Comprendi le basi del Reinforcement Learning (RL) ed esplora il pacchetto software Gymnasium per creare e testare algoritmi RL con Python.
Aggiornato 29 set 2026  · 15 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

Il Reinforcement Learning (RL) è uno dei tre principali paradigmi del machine learning, insieme all’apprendimento supervisionato e non supervisionato. Nell’RL, un agente impara a interagire con l’ambiente per massimizzare le ricompense cumulative. Impara l’azione ottimale in diverse condizioni ambientali tramite tentativi ed errori. Il Reinforcement Learning con feedback umano (RLHF) permette all’agente di modificare il comportamento in base agli input umani a ogni passaggio.

L’RL risolve problemi come le auto a guida autonoma, il trading automatizzato, i giocatori computerizzati nei videogiochi, l’addestramento di robot e altro ancora. Quando si usano reti neurali profonde per applicare algoritmi di RL, si parla di Deep Reinforcement Learning. 

In questo tutorial ti mostrerò come iniziare con Gymnasium, una libreria Python open source per sviluppare e confrontare algoritmi di reinforcement learning. Vedremo come installarla, esplorare vari ambienti RL e usare Python per creare un semplice agente che implementi un algoritmo di RL. 

Che cos’è Gymnasium?

Gymnasium è una libreria Python open source progettata per supportare lo sviluppo di algoritmi di RL. Per facilitare la ricerca e lo sviluppo in RL, Gymnasium fornisce: 

  • Un’ampia varietà di ambienti, dai giochi semplici a problemi che imitano scenari reali.
  • API e wrapper semplificati per interfacciarsi con gli ambienti.
  • La possibilità di creare ambienti personalizzati e sfruttare il framework dell’API.

Gli sviluppatori possono creare algoritmi di RL e usare chiamate API per attività come:

  • Passare l’azione scelta dall’agente all’ambiente.
  • Conoscere lo stato dell’ambiente e la ricompensa dopo ciascuna azione. 
  • Addestrare il modello.
  • Testare le prestazioni del modello.

OpenAI Gym vs Gymnasium di Farama

OpenAI non ha dedicato risorse significative allo sviluppo di Gym perché non era una priorità aziendale. La Farama Foundation è stata creata per standardizzare e mantenere a lungo termine le librerie di RL. Gymnasium è il fork della Farama Foundation di OpenAI Gym. Gymnasium 0.26.2 è un sostituto immediato di Gym 0.26.2. Con il fork, Farama punta ad aggiungere metodi funzionali (oltre a quelli basati su classi) per tutte le chiamate API, supportare ambienti vettoriali e migliorare i wrapper. L’obiettivo generale è rendere il framework più pulito ed efficiente.

Configurare Gymnasium

Gymnasium richiede versioni specifiche (non le ultime release) di varie dipendenze come NumPy e PyTorch. Per questo consigliamo di creare un nuovo ambiente Conda o venv, oppure un nuovo notebook, per installare, usare Gymnasium ed eseguire programmi RL. 

Puoi usare questo workbook DataLab per seguire il tutorial.

Installare Gymnasium

Per installare Gymnasium su un server o su una macchina locale, esegui: 

$ pip install gymnasium 

Per installare tramite un Notebook come Colab di Google o DataLab di DataCamp, usa:

!pip install gymnasium

Il comando sopra installa Gymnasium e le versioni corrette delle dipendenze.

Esplorare gli ambienti di Gymnasium

A novembre 2024, Gymnasium include oltre 60 ambienti integrati. Per sfogliare gli ambienti disponibili, usa la funzione gym.envs.registry.all(), come mostrato nell’esempio seguente: 

import gymnasium as gym
for i in gym.envs.registry.keys():
	print(i)

Puoi anche visitare la homepage di Gymnasium. La colonna di sinistra contiene i link a tutti gli ambienti. La pagina web di ciascun ambiente include dettagli come azioni, stati, ecc. 

Gli ambienti sono organizzati in categorie come Classic Control, Box2D e altro. Di seguito elenco alcuni ambienti comuni per ciascun gruppo:

  • Classic Control: sono ambienti canonici usati nello sviluppo RL; costituiscono la base di molti esempi da manuale. Offrono il giusto mix di complessità e semplicità per testare e fare benchmark di nuovi algoritmi RL. Gli ambienti classic control in Gymnasium includono: 
    • Acrobot
    • Cart Pole
    • Mountain Car Discrete
    • Mountain Car Continuous
    • Pendulum
  • Box2D: Box2D è un motore fisico 2D per giochi. Gli ambienti basati su questo motore includono giochi semplici come:
    • Lunar Lander
    • Car Racing
  • ToyText: sono ambienti piccoli e semplici, spesso usati per effettuare il debug degli algoritmi RL. Molti di questi ambienti si basano su piccoli grid world e semplici giochi di carte. Esempi: 
    • Blackjack
    • Taxi
    • Frozen Lake
  • MuJoCo: Multi-Joint dynamics with Contact (MuJoCo) è un motore fisico open source che simula ambienti per applicazioni come robotica, biomeccanica, ML, ecc. Gli ambienti MuJoCo in Gymnasium includono:
    • Ant
    • Hopper
    • Humanoid
    • Swimmer
    • E altri

Oltre agli ambienti integrati, Gymnasium può essere usato con molti ambienti esterni usando la stessa API. 

In questo tutorial useremo uno degli ambienti canonici Classic Control. Per importare un ambiente specifico, usa il comando .make() e passa il nome dell’ambiente come argomento. Per esempio, per creare un nuovo ambiente basato su CartPole (versione 1), usa il comando seguente: 

import gymnasium as gym
env = gym.make("CartPole-v1")

Comprendere i concetti di Reinforcement Learning in Gymnasium

In poche parole, il Reinforcement Learning consiste in un agente (come un robot) che interagisce con il suo ambiente. Una politica decide le azioni dell’agente. A seconda delle azioni, l’ambiente fornisce una ricompensa (o penalità) a ogni timestep. L’agente usa l’RL per trovare la politica ottimale che massimizza le ricompense totali ottenute. 

Componenti di un ambiente RL

Di seguito sono riportati i componenti chiave di un ambiente RL: 

  • Ambiente: il sistema, mondo o contesto esterno. L’agente interagisce con l’ambiente in una serie di timestep. In ciascun timestep, in base all’azione dell’agente, l’ambiente:
    • Fornisce una ricompensa (o penalità) 
    • Decide lo stato successivo 
  • Stato: una rappresentazione matematica della configurazione attuale dell’ambiente. 
    • Per esempio, lo stato di un ambiente pendulum può includere la posizione del pendolo e la velocità angolare a ogni timestep. 
    • Stato terminale: uno stato che non porta a nuovi/altri stati. 
  • Agente: l’algoritmo che osserva l’ambiente e compie varie azioni in base a questa osservazione. L’obiettivo dell’agente è massimizzare le ricompense. 
    • Per esempio, l’agente decide con quanta forza e in quale direzione spingere il pendolo.  
  • Osservazione: una rappresentazione matematica della “vista” dell’agente sull’ambiente, acquisita, ad esempio, tramite sensori. 
  • Azione: la decisione presa dall’agente prima di procedere allo step successivo. L’azione influenza lo stato successivo dell’ambiente e fa ottenere all’agente una ricompensa. 
  • Ricompensa: il feedback dall’ambiente all’agente. Può essere positiva o negativa, a seconda dell’azione e dello stato dell’ambiente. 
  • Rendimento (Return): il rendimento cumulativo atteso sui timestep futuri. Le ricompense dei timestep futuri possono essere scontate tramite un fattore di sconto. 
  • Politica (Policy): la strategia dell’agente su quale azione intraprendere nei vari stati. È tipicamente rappresentata come una matrice di probabilità, P, che mappa stati ad azioni.
    • Dato un insieme finito di m stati possibili e n azioni possibili, l’elemento Pmn nella matrice denota la probabilità di compiere l’azione an nello stato sm.  
  • Episodio: la serie di timestep dallo stato iniziale (randomizzato) finché l’agente non raggiunge uno stato terminale.

Spazio delle osservazioni e spazio delle azioni

L’osservazione è l’informazione che l’agente raccoglie sull’ambiente. Un agente, per esempio un robot, può raccogliere informazioni sull’ambiente tramite sensori. Idealmente, l’agente dovrebbe poter osservare lo stato completo, che descrive tutti gli aspetti dell’ambiente. In pratica, l’agente usa le proprie osservazioni come proxy dello stato. Di conseguenza, le osservazioni determinano le azioni dell’agente. 

Uno spazio è analogo a un insieme matematico. Lo spazio degli elementi X include tutte le istanze possibili di X. Lo spazio di X definisce anche la struttura (sintassi e formato) di tutti gli elementi di tipo X. Ogni ambiente Gymnasium ha due spazi: lo spazio delle azioni, action_space, e lo spazio delle osservazioni, observation_space. Entrambi derivano dalla superclasse gymnasium.spaces.Space. 

Spazio delle osservazioni 

Lo spazio delle osservazioni è lo spazio che include tutte le possibili osservazioni. Definisce anche il formato in cui le osservazioni sono memorizzate. Lo spazio delle osservazioni è tipicamente rappresentato come un oggetto di tipo dati Box. Si tratta di un’ndarray che descrive i parametri delle osservazioni. Il box specifica i limiti di ciascuna dimensione. Puoi visualizzare lo spazio delle osservazioni per un ambiente usando il metodo observation_space:

print("observation space: ", env.observation_space)

Nel caso dell’ambiente CartPole-v1, l’output è simile all’esempio seguente: 

observation space:  Box([-4.8 -inf -0.41887903 -inf], [4.8 inf 0.41887903 inf], (4,), float32)

In questo esempio, lo spazio delle osservazioni di CartPole-v1 ha 4 dimensioni. I 4 elementi dell’array di osservazione sono:

  • Posizione del carrello - varia tra -4,8 e +4,8
  • Velocità del carrello - varia tra - e +
  • Angolo dell’asta - varia tra -0,4189 e +0,4189
  • Velocità angolare dell’asta - varia tra  - e +

Per vedere un esempio di singolo array di osservazione, usa il comando .reset(). 

observation, info = env.reset()
print("observation: ", observation)

Nel caso dell’ambiente CartPole-v1, l’output è simile all’esempio seguente: 

[ 0.03481963 -0.0277232   0.01703267 -0.04870504]                                                                                                       

I quattro elementi di questo array corrispondono alle quattro quantità osservate (posizione del carrello, velocità del carrello, angolo dell’asta, velocità angolare dell’asta), come spiegato in precedenza. 

Spazio delle azioni

Lo spazio delle azioni include tutte le possibili azioni che l’agente può compiere. Definisce anche il formato con cui le azioni sono rappresentate. Puoi visualizzare lo spazio delle azioni per un ambiente usando il metodo action_space:

print("action space: ", env.action_space)

Nel caso dell’ambiente CartPole-v1, l’output è simile all’esempio seguente: 

action space:  Discrete(2)

Nel caso dell’ambiente CartPole-v1, lo spazio delle azioni è discreto. Ci sono in totale due azioni che l’agente può compiere:

  • 0: spingere il carrello a sinistra
  • 1: spingere il carrello a destra

Creare il tuo primo agente RL con Gymnasium

Nelle sezioni precedenti abbiamo esplorato i concetti base di RL e Gymnasium. In questa sezione vedrai come usare Gymnasium per costruire un agente RL. 

Creare e resettare l’ambiente

Il primo passo è creare un’istanza dell’ambiente. Per creare nuovi ambienti, usa il metodo .make(). 

env = gym.make('CartPole-v1')

Le interazioni dell’agente cambiano lo stato dell’ambiente. Il metodo .reset() riporta l’ambiente a uno stato iniziale. Per impostazione predefinita, l’ambiente viene inizializzato a uno stato casuale. Puoi usare un parametro SEED con il metodo .reset() per inizializzare l’ambiente allo stesso stato ogni volta che il programma viene eseguito. Il codice seguente mostra come fare:

SEED = 1111
env.reset(seed=SEED)

Il campionamento delle azioni comporta anch’esso casualità. Per controllare questa casualità e ottenere un percorso di addestramento completamente riproducibile, possiamo fissare i semi dei generatori casuali di NumPy e PyTorch:

np.random.seed(SEED)
torch.manual_seed(SEED)

Azioni casuali vs azioni intelligenti

A ogni passo in un processo di Markov, l’agente può scegliere casualmente un’azione ed esplorare l’ambiente finché non arriva a uno stato terminale. Scegliendo azioni a caso: 

  • Può volerci molto tempo per raggiungere lo stato terminale.
  • Le ricompense cumulative sono molto inferiori a quelle che potrebbero essere.

Addestrare l’agente a ottimizzare la selezione delle azioni in base alle esperienze precedenti (di interazione con l’ambiente) è più efficiente per massimizzare le ricompense a lungo termine. 

L’agente non addestrato parte con azioni casuali basate su una politica inizializzata a caso. Questa politica è tipicamente rappresentata come una rete neurale. Durante l’addestramento, l’agente impara la politica ottimale che massimizza le ricompense. In RL, il processo di addestramento è detto anche ottimizzazione della politica (policy optimization). 

Esistono vari metodi di policy optimization. Le equazioni di Bellman descrivono come calcolare il valore delle politiche RL e determinare la politica ottimale. In questo tutorial useremo una tecnica semplice chiamata policy gradients. Esistono anche altri metodi, come la Proximal Policy Optimization (PPO). 

Implementare un semplice agente con Policy Gradient

Per costruire un agente RL che usa i policy gradients, creiamo una rete neurale per implementare la politica, scriviamo funzioni per calcolare i return e la loss dalle ricompense per step e dalle probabilità delle azioni, e aggiorniamo iterativamente la politica usando tecniche standard di backpropagation. 

Impostare la rete di policy

Usiamo una rete neurale per implementare la politica. Poiché CartPole-v1 è un ambiente semplice, usiamo una rete neurale con:

  • Dimensioni di input uguali alla dimensionalità dello spazio delle osservazioni dell’ambiente. 
  • Un solo livello nascosto con 64 neuroni. 
  • Dimensioni di output uguali alla dimensionalità dello spazio delle azioni dell’ambiente.

Quindi, la funzione della rete di policy è mappare gli stati osservati alle azioni. Data un’osservazione in input, predice l’azione giusta. Il codice seguente implementa la rete di policy:

class PolicyNetwork(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, dropout):
        super().__init__()
        self.layer1 = nn.Linear(input_dim, hidden_dim)
        self.layer2 = nn.Linear(hidden_dim, output_dim)
        self.dropout = nn.Dropout(dropout)
    def forward(self, x):
        x = self.layer1(x)
        x = self.dropout(x)
        x = F.relu(x)
        x = self.layer2(x)
        return x

Raccolta delle ricompense e forward pass

Come detto, a ogni step del processo di Markov l’ambiente fornisce una ricompensa in base all’azione e allo stato dell’agente. L’obiettivo in RL è massimizzare il return totale. 

  • Il return a ogni timestep è la somma cumulativa delle ricompense ottenute dall’inizio fino a quello step. 
  • Il return totale in ciascun episodio si ottiene accumulando tutte le ricompense step-by-step di quell’episodio. Quindi, il return totale è il return all’ultimo timestep (quando l’agente raggiunge uno stato terminale). 

In pratica, durante l’accumulo delle ricompense è comune: 

  • Adeguare le ricompense future usando un fattore di sconto. 
  • Normalizzare l’array dei return per step per garantire un training fluido e stabile. 

Il codice seguente mostra come fare: 

def calculate_stepwise_returns(rewards, discount_factor):
    returns = []
    R = 0
    for r in reversed(rewards):
        R = r + R * discount_factor
        returns.insert(0, R)
    returns = torch.tensor(returns)
    normalized_returns = (returns - returns.mean()) / returns.std()
    return normalized_returns

Il forward pass consiste nel far funzionare l’agente in base all’attuale politica fino al raggiungimento di uno stato terminale e nel raccogliere le ricompense per step e le probabilità delle azioni. I passaggi seguenti spiegano come implementare il forward pass: 

  • Resetta l’ambiente a uno stato iniziale. 
  • Inizializza buffer per memorizzare le probabilità delle azioni, le ricompense e il return cumulativo
  • Usa la funzione .step() per eseguire iterativamente l’agente nell’ambiente fino alla terminazione:
    • Ottieni l’osservazione dello stato dell’ambiente.
    • Ottieni l’azione predetta dalla politica sulla base dell’osservazione.
    • Usa la funzione Softmax per stimare la probabilità di compiere l’azione predetta.
    • Simula una distribuzione di probabilità categorica basata su queste probabilità stimate.
    • Campiona da questa distribuzione per ottenere l’azione dell’agente.
    • Stima la log-probabilità dell’azione campionata a partire dalla distribuzione simulata. 
  • Aggiungi le log-probabilità delle azioni e le ricompense di ciascuno step ai rispettivi buffer. 
  • Stima i valori normalizzati e scontati dei return a ogni step in base alle ricompense. 
def forward_pass(env, policy, discount_factor):
    log_prob_actions = []
    rewards = []
    done = False
    episode_return = 0
    policy.train()
    observation, info = env.reset()
    while not done:
        observation = torch.FloatTensor(observation).unsqueeze(0)
        action_pred = policy(observation)
        action_prob = F.softmax(action_pred, dim = -1)
        dist = distributions.Categorical(action_prob)
        action = dist.sample()
        log_prob_action = dist.log_prob(action)
        observation, reward, terminated, truncated, info = env.step(action.item())
        done = terminated or truncated
        log_prob_actions.append(log_prob_action)
        rewards.append(reward)
        episode_return += reward
    log_prob_actions = torch.cat(log_prob_actions)
    stepwise_returns = calculate_stepwise_returns(rewards, discount_factor)
    return episode_return, stepwise_returns, log_prob_actions

Aggiornare la policy in base alle ricompense

La loss rappresenta la quantità su cui applichiamo la discesa del gradiente. L’obiettivo in RL è massimizzare i return. Quindi, usiamo il valore atteso del return come proxy della loss. Il valore atteso del return si calcola come prodotto tra i return attesi per step e la log-probabilità delle azioni per step. Il codice seguente calcola la loss:

def calculate_loss(stepwise_returns, log_prob_actions):
    loss = -(stepwise_returns * log_prob_actions).sum()
    return loss

Per aggiornare la policy, esegui la backpropagation rispetto alla funzione di loss. Il metodo update_policy() qui sotto invoca il metodo calculate_loss(). Poi esegue la backpropagation su questa loss per aggiornare i parametri della policy, ovvero i pesi del modello della rete di policy.

def update_policy(stepwise_returns, log_prob_actions, optimizer):
    stepwise_returns = stepwise_returns.detach()
    loss = calculate_loss(stepwise_returns, log_prob_actions)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    return loss.item()

Aggiornare la policy in base al gradiente dei return si chiama metodo del policy gradient. 

Addestrare la policy

Ora abbiamo tutti i componenti necessari per addestrare e valutare la policy. Implementiamo il ciclo di training come spiegato nei passaggi seguenti:  

Prima di iniziare, dichiariamo gli iperparametri, istanziamo una policy e creiamo un ottimizzatore:

  • Dichiara gli iperparametri come costanti Python:
    • MAX_EPOCHS è il numero massimo di iterazioni che siamo disposti a eseguire per addestrare la policy. 
    • DISCOUNT_FACTOR decide la rilevanza relativa delle ricompense dei timestep futuri. Un fattore di sconto pari a 1 significa che tutte le ricompense sono ugualmente importanti, mentre un valore 0 significa che conta solo la ricompensa del timestep corrente. 
    • N_TRIALS è il numero di episodi su cui facciamo la media dei return per valutare le prestazioni dell’agente. Consideriamo l’addestramento riuscito se il return medio su N_TRIALS episodi supera la soglia.
    • REWARD_THRESHOLD: se la policy riesce a ottenere un return superiore alla soglia, è considerata di successo. 
    • DROPOUT decide la frazione di pesi che deve essere azzerata casualmente. La funzione di dropout imposta casualmente una frazione dei pesi del modello a zero. Questo riduce la dipendenza da neuroni specifici e previene l’overfitting, rendendo la rete più robusta.
    • LEARNING_RATE decide quanto possono essere modificati i parametri della policy a ogni step. L’aggiornamento dei parametri a ogni iterazione è il prodotto tra il gradiente e il learning rate. 
  • Definisci la policy come istanza della classe PolicyNetwork (implementata in precedenza). 
  • Crea un ottimizzatore usando l’algoritmo Adam e il learning rate. 

Per addestrare la policy, eseguiamo iterativamente i passaggi di training finché il return medio (su N_TRIALS) è superiore alla soglia di ricompensa:

  • Per ogni episodio, esegui una volta il forward pass. Raccogli la log-probabilità delle azioni, i return per step e il return totale di quell’episodio. Accumula i return per episodio in un array. 
  • Calcola la loss usando le log-probabilità e i return per step. Esegui la backpropagation sulla loss. Usa l’ottimizzatore per aggiornare i parametri della policy. 
  • Controlla se il return medio su N_TRIALS supera la soglia di ricompensa. 

Il codice seguente implementa questi passaggi:

def main(): 
    MAX_EPOCHS = 500
    DISCOUNT_FACTOR = 0.99
    N_TRIALS = 25
    REWARD_THRESHOLD = 475
    PRINT_INTERVAL = 10
    INPUT_DIM = env.observation_space.shape[0]
    HIDDEN_DIM = 128
    OUTPUT_DIM = env.action_space.n
    DROPOUT = 0.5
    episode_returns = []
    policy = PolicyNetwork(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT)
    LEARNING_RATE = 0.01
    optimizer = optim.Adam(policy.parameters(), lr = LEARNING_RATE)
    for episode in range(1, MAX_EPOCHS+1):
        episode_return, stepwise_returns, log_prob_actions = forward_pass(env, policy, DISCOUNT_FACTOR)
        _ = update_policy(stepwise_returns, log_prob_actions, optimizer)
        episode_returns.append(episode_return)
        mean_episode_return = np.mean(episode_returns[-N_TRIALS:])
        if episode % PRINT_INTERVAL == 0:
            print(f'| Episode: {episode:3} | Mean Rewards: {mean_episode_return:5.1f} |')
        if mean_episode_return >= REWARD_THRESHOLD:
            print(f'Reached reward threshold in {episode} episodes')
            break

Infine, richiama la funzione main() per addestrare la policy:

main()

Usa questo workbook DataLab per eseguire direttamente l’algoritmo sopra e risolvere l’ambiente CartPole usando l’RL. 

Tecniche avanzate in Gymnasium

Dopo aver mostrato come implementare un algoritmo RL, parliamo ora di alcune tecniche avanzate comunemente usate in pratica. 

Usare architetture predefinite

Implementare algoritmi RL da zero è un processo lungo e difficile, soprattutto per ambienti complessi e politiche all’avanguardia. 

Un’alternativa più pratica è usare software come Stable Baselines3. Include implementazioni collaudate di algoritmi RL. Contiene agenti pre-addestrati, script di training, strumenti di valutazione e moduli per tracciare grafici e registrare video. 

Ray RLib è un altro strumento popolare per l’RL. RLib è progettato come una soluzione scalabile, che facilita l’implementazione di algoritmi RL su sistemi multi-GPU. Supporta anche l’RL multi-agente, che apre nuove possibilità come:

  • Apprendimento multi-agente indipendente: ogni agente tratta gli altri agenti come parte dell’ambiente.
  • Training collaborativo multi-agente: un gruppo di agenti condivide le stesse funzioni di policy e valore e impara in parallelo dalle esperienze reciproche. 
  • Addestramento avversariale: agenti (o gruppi di agenti) competono tra loro in ambienti competitivi simili a giochi. 

Con RLib e Stable Baselines3 puoi importare e usare ambienti da OpenAI Gymnasium. 

Ambienti personalizzati

Gli ambienti forniti con Gymnasium sono la scelta giusta per testare nuove strategie RL e addestrare le policy. Tuttavia, per la maggior parte delle applicazioni pratiche, devi creare e usare un ambiente che rispecchi accuratamente il problema che vuoi risolvere. Puoi usare Gymnasium per creare un ambiente personalizzato. Il vantaggio degli ambienti personalizzati Gymnasium è che molti strumenti esterni come RLib e Stable Baselines3 sono già configurati per funzionare con la struttura API di Gymnasium. 

Per creare un ambiente personalizzato in Gymnasium, devi definire: 

  • Lo spazio delle osservazioni.
  • Le condizioni terminali.
  • L’insieme di azioni tra cui l’agente può scegliere.
  • Come inizializzare l’ambiente (quando viene chiamata la funzione reset()). 
  • Come l’ambiente decide lo stato successivo date le azioni dell’agente (quando viene chiamata la funzione step()). 

Per saperne di più, segui la guida Gymnasium su come creare ambienti personalizzati. 

Best practice per usare Gymnasium

Sperimenta con ambienti diversi

Il codice in questo tutorial ha mostrato come implementare l’algoritmo del policy gradient nell’ambiente CartPole. Si tratta di un ambiente semplice con spazio delle azioni discreto. Per comprendere meglio l’RL, ti consigliamo di applicare lo stesso algoritmo di policy gradient (e altri algoritmi, come la PPO) in altri ambienti. 

Per esempio, l’ambiente Pendulum ha uno spazio delle azioni continuo. Consiste in un singolo input rappresentato come variabile continua: la (magnitudo e direzione della) coppia applicata al pendolo in un dato stato. Questa coppia può assumere qualsiasi valore tra -2 e +2. 

Sperimentare diversi algoritmi in vari ambienti ti aiuta a comprendere meglio i diversi tipi di soluzioni RL e le relative sfide. 

Monitora i progressi del training

Gli ambienti RL spesso comprendono robot, pendoli, mountain car, videogiochi, ecc. Visualizzare le azioni dell’agente nell’ambiente offre una comprensione intuitiva migliore delle prestazioni della policy. 

In Gymnasium, il metodo env.render() visualizza le interazioni dell’agente con l’ambiente. Mostra graficamente lo stato corrente dell’ambiente — schermate di gioco, la posizione del pendolo o del cart-pole, ecc. Il feedback visivo delle azioni dell’agente e delle risposte dell’ambiente aiuta a monitorare le prestazioni e i progressi dell’agente durante il training. 

Esistono quattro modalità di render: “human”, “rgb_array”, “ansi” e “rgb_array_list”. Per visualizzare le prestazioni dell’agente, usa la modalità “human”. La modalità di render si specifica quando si inizializza l’ambiente. Per esempio:

env = gym.make(‘CartPole-v1’, render_mode=’human’)

Per effettuare il rendering, richiama il metodo .render() dopo ogni azione eseguita dall’agente (tramite la chiamata al metodo .step()). Il seguente pseudocodice illustra come fare:

while not done:
    …
   step, reward, terminated, truncated, info = env.step(action.item())
   env.render()
    …

Risoluzione degli errori comuni

Gymnasium semplifica l’interfacciamento con ambienti RL complessi. Tuttavia, è un software in continuo aggiornamento con molte dipendenze. È quindi importante prestare attenzione ad alcuni tipi comuni di errori.

Incongruenze di versione

  • Incongruenza di versione di Gymnasium: il pacchetto Gymnasium di Farama è stato forkato da OpenAI Gym a partire dalla versione 0.26.2. Ci sono stati alcuni breaking change tra le vecchie versioni di Gym e le nuove versioni di Gymnasium. Molte implementazioni pubbliche sono basate sulle vecchie release di Gym e potrebbero non funzionare direttamente con l’ultima release. In tali casi, è necessario effettuare il rollback a una versione precedente o adattare il codice per funzionare con la nuova release. 
  • Incongruenza di versione dell’ambiente: molti ambienti Gymnasium hanno versioni differenti. Per esempio, esistono due ambienti CartPole - CartPole-v1 e CartPole-v0. Sebbene il comportamento dell’ambiente sia lo stesso in entrambe le versioni, alcuni parametri, come la lunghezza dell’episodio, la soglia di ricompensa, ecc., possono essere diversi. Una policy addestrata su una versione potrebbe non funzionare altrettanto bene su un’altra versione dello stesso ambiente. Devi aggiornare i parametri di training e riaddestrare la policy per ciascuna versione dell’ambiente. 
  • Incongruenza delle versioni delle dipendenze: Gymnasium dipende da librerie come NumPy e PyTorch. A dicembre 2024, le ultime versioni di queste dipendenze sono numpy 2.1.3 e torch 2.5.1. Tuttavia, Gymnasium funziona al meglio con torch 1.13.0 e numpy 1.23.3. Potresti riscontrare problemi se installi Gymnasium in un ambiente con queste dipendenze già preinstallate. Raccomandiamo di installare e lavorare con Gymnasium in un nuovo ambiente Conda. 

Problemi di convergenza

  • Iperparametri: come altri algoritmi di machine learning, le policy RL sono sensibili a iperparametri come learning rate, fattore di sconto, ecc. Consigliamo di sperimentare e sintonizzare gli iperparametri manualmente o usando tecniche automatiche come grid search e random search. 
  • Esplorazione vs sfruttamento: per alcune classi di policy (come PPO), l’agente adotta una strategia a due vie: esplorare l’ambiente per scoprire nuovi percorsi e adottare un approccio greedy per massimizzare le ricompense in base ai percorsi noti finora. Se esplora troppo, la policy non converge. Al contrario, se esplora troppo poco, non proverà mai il percorso ottimale. Trovare il giusto equilibrio tra esplorazione e sfruttamento è quindi essenziale. È anche comune dare priorità all’esplorazione nelle fasi iniziali e allo sfruttamento in quelle successive durante l’addestramento. 

Instabilità del training

  • Learning rate elevati: se il learning rate è troppo alto, i parametri della policy subiscono aggiornamenti ampi a ogni step. Questo può portare a mancare l’insieme ottimale di valori. Una soluzione comune è far decadere gradualmente il learning rate, garantendo aggiornamenti più piccoli e stabili man mano che il training converge. 
  • Esplorazione eccessiva: troppa casualità (entropia) nella selezione delle azioni impedisce la convergenza e porta a grandi variazioni della loss tra step successivi. Per avere un processo di training stabile e convergente, bilancia l’esplorazione con lo sfruttamento. 
  • Scelta sbagliata dell’algoritmo: algoritmi semplici come il policy gradient possono portare a training instabile in ambienti complessi con grandi spazi di azione e stato. In questi casi, consigliamo di usare algoritmi più robusti come PPO e Trust Region Policy Optimization (TRPO). Questi algoritmi evitano grandi aggiornamenti di policy a ogni step e possono essere più stabili.
  • Casualità: gli algoritmi RL sono notoriamente sensibili agli stati iniziali e alla casualità insita nella selezione delle azioni. Quando un training è instabile, a volte può essere stabilizzato usando un seed casuale diverso o reinizializzando la policy.

Conclusione

In questo tutorial abbiamo esplorato i principi di base dell’RL, discusso Gymnasium come pacchetto software con un’API pulita per interfacciarsi con vari ambienti RL e mostrato come scrivere un programma Python per implementare un semplice algoritmo RL e applicarlo in un ambiente Gymnasium.

Dopo aver compreso le basi in questo tutorial, ti consiglio di usare ambienti Gymnasium per applicare i concetti di RL a problemi pratici come l’ottimizzazione dei percorsi dei taxi e le simulazioni di trading azionario.

FAQ

Qual è il ruolo di Gymnasium nel reinforcement learning?

Gymnasium include molti ambienti predefiniti per testare e sviluppare algoritmi RL. Standardizza l’interfaccia per questi ambienti e per i nuovi ambienti personalizzati. Questo rende più semplice implementare e valutare algoritmi RL.

Con OpenAI Gymnasium sei limitato agli ambienti integrati?

No. Oltre a più di 60 ambienti predefiniti, Gymnasium ti permette di creare nuovi ambienti dichiarandone gli spazi di stato e azione e definendo come l’ambiente deve rispondere alle varie azioni.

Qual è la differenza tra Gym e Gymnasium?

In poche parole, Gymnasium, mantenuto dalla Farama Foundation, è la nuova versione aggiornata di Gym, che OpenAI non mantiene più. Gymnasium dovrebbe funzionare come sostituto diretto di Gym 0.26.2.

Qual è la differenza tra metodi RL basati sulla policy e basati sul valore?

Nei metodi basati sulla policy, come i policy gradients, l’agente modifica direttamente i parametri della policy per trovare quale politica porta al massimo return atteso. 

Nei metodi basati sul valore, l’agente viene addestrato sulla funzione di valore. Imparare la funzione di valore ottimale aiuta a derivare la policy ottimale.

Codificare a mano gli algoritmi è l’unico modo migliore per risolvere problemi RL?

Scrivere codice da zero è il modo migliore per capire i diversi algoritmi RL. Per l’uso in produzione, ci sono strumenti come Stable Baselines3, RLib e CleanRL. Questi strumenti includono implementazioni pronte dei principali algoritmi RL, che devi configurare e ottimizzare in base all’ambiente.


Arun Nanda's photo
Author
Arun Nanda
LinkedIn

Arun è un ex fondatore di startup a cui piace creare cose nuove. Attualmente sta esplorando le basi tecniche e matematiche dell’Intelligenza Artificiale. Ama condividere ciò che ha imparato, quindi ne scrive.

Oltre a DataCamp, puoi leggere i suoi articoli su Medium, Airbyte e Vultr.

Argomenti
Machine Learning
Python

Approfondisci il reinforcement learning con questi corsi!

Corso

Reinforcement Learning con Gymnasium in Python

4 ore
13.8K
Inizia il tuo viaggio nell'apprendimento rinforzato! Scopri come gli agenti possono imparare a risolvere i problemi attraverso le interazioni.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

Mostra AltroMostra Altro