L’apprentissage par renforcement (RL) est l’un des trois principaux paradigmes d’apprentissage automatique, les deux autres étant l’apprentissage supervisé et non supervisé. En RL, un agent apprend à interagir avec son environnement pour maximiser les récompenses cumulatives. Il apprend l’action optimale dans différentes conditions environnementales par essai et erreur. L’apprentissage par renforcement avec retour humain (RLHF) permet à l’agent de modifier son comportement en fonction des entrées humaines à chaque étape.
RL résout des problèmes tels que les voitures autonomes, le trading automatisé, les joueurs d’ordinateur dans les jeux vidéo, la formation de robots, et plus encore. Lorsque des réseaux neuronaux profonds sont utilisés pour appliquer des algorithmes RL, on parle de l’apprentissage par renforcement profond.
Dans ce tutoriel, je vais vous montrer comment commencer avec Gymnasium, une bibliothèque Python open-source pour développer et comparer des algorithmes d’apprentissage par renforcement. Je vais vous montrer comment le configurer, explorer divers environnements RL, et utiliser Python pour construire un agent simple afin de mettre en œuvre un algorithme RL.
Qu’est-ce que Gymnasium?
Gymnasium est une bibliothèque Python open-source conçue pour soutenir le développement d’algorithmes de RL. Pour faciliter la recherche et le développement en RL, Gymnasium fournit :
- Une grande variété d’environnements, des jeux simples aux problèmes imitant des scénarios de la vie réelle.
- Des API rationalisées et des wrappers pour interagir avec les environnements.
- La possibilité de créer des environnements personnalisés et de tirer parti du framework API.
Les développeurs peuvent construire des algorithmes de RL et utiliser des appels API pour des tâches telles que :
- Transmettre l’action choisie par l’agent à l’environnement.
- Connaître l’état de l’environnement et la récompense après chaque action.
- Former le modèle.
- Tester les performances du modèle.
OpenAI Gym versus Gymnase de Farama
OpenAI n’a pas alloué de ressources significatives au développement de Gym car ce n’était pas une priorité commerciale pour l’entreprise. La Fondation Farama a été créée pour normaliser et maintenir les bibliothèques RL à long terme. Gymnasium est le fork de la Fondation Farama du Gym d’OpenAI. Gymnasium 0.26.2 est un remplacement plug-and-play pour Gym 0.26.2. Avec le fork, Farama vise à ajouter des méthodes fonctionnelles (en plus des méthodes basées sur les classes) pour tous les appels API, prendre en charge les environnements vectoriels et améliorer les wrappers. L’objectif global est de rendre le framework plus propre et plus efficace.
Configuration de Gymnasium
Le Gymnasium nécessite des versions spécifiques (pas les dernières versions) de divers programmes de dépendance comme NumPy et PyTorch. Ainsi, nous recommandons de créer un nouvel environnement Conda ou venv ou un nouveau notebook pour installer, utiliser Gymnasium et exécuter des programmes RL.
Vous pouvez utiliser ce carnet DataLab pour suivre le tutoriel.
Installation de Gymnasium
Pour installer Gymnasium sur un serveur ou une machine locale, exécutez :
$ pip install gymnasium
Pour installer en utilisant un Notebook comme Google Colab ou DataLab de DataCamp, utilisez :
!pip install gymnasium
La commande ci-dessus installe Gymnasium et les bonnes versions des dépendances.
Explorer les environnements Gymnasium
A partir de novembre 2024, Gymnasium comprend plus de 60 environnements intégrés. Pour parcourir les environnements intégrés disponibles, utilisez la fonction gym.envs.registry.all()
, comme illustré dans l’exemple ci-dessous :
import gymnasium as gym for i in gym.envs.registry.keys(): print(i)
Vous pouvez également visiter la page d’accueil de Gymnasium. La colonne de gauche contient des liens vers tous les environnements. La page web de chaque environnement inclut des détails à son sujet, tels que les actions, les états, etc.
Les environnements sont organisés en catégories comme Contrôle Classique, Box2D, et plus encore. Ci-dessous, je liste quelques-uns des environnements courants dans chaque groupe :
- Contrôle Classique : Ce sont des environnements canoniques utilisés dans le développement RL ; ils forment la base de nombreux exemples de manuels. Ils offrent le bon mélange de complexité et de simplicité pour tester et évaluer de nouveaux algorithmes RL. Les environnements de contrôle classique dans Gymnasium incluent :
- Acrobot
- Cart Pole
- Mountain Car Discret
- Mountain Car Continu
- Pendule
- Box2D: Box2D est un moteur de physique 2D pour les jeux. Les environnements basés sur ce moteur comprennent des jeux simples tels que :
- Lunar Lander
- Car Racing
- ToyText: Ce sont de petits environnements simples souvent utilisés pour déboguer des algorithmes RL. Beaucoup de ces environnements sont basés sur le modèle de petit monde en grille et des jeux de cartes simples. Les exemples incluent :
- Blackjack
- Taxi
- Frozen Lake
- MuJoCo: Multi-Joint dynamics with Contact (MuJoCo) est un moteur de physique open-source qui simule des environnements pour des applications telles que la robotique, la biomécanique, le ML, etc. Les environnements MuJoCo dans Gymnasium incluent :
- Ant
- Hopper
- Humanoid
- Swimmer
- Et plus encore
En plus des environnements intégrés, Gymnasium peut être utilisé avec de nombreux environnements externes en utilisant la même API.
Nous utiliserons l’un des environnements de Contrôle Classique canoniques dans ce tutoriel. Pour importer un environnement spécifique, utilisez la commande .make()
et passez le nom de l’environnement en argument. Par exemple, pour créer un nouvel environnement basé sur CartPole (version 1), utilisez la commande ci-dessous:
import gymnasium as gym env = gym.make("CartPole-v1")
Comprendre les Concepts de l’Apprentissage par Renforcement dans le Gymnase
En résumé, l’Apprentissage par Renforcement consiste en un agent (comme un robot) qui interagit avec son environnement. Une politique décide des actions de l’agent. Selon les actions de l’agent, l’environnement donne une récompense (ou une pénalité) à chaque pas de temps. L’agent utilise l’AR pour déterminer la politique optimale qui maximise les récompenses totales que l’agent gagne.
Composants d’un environnement AR
Voici les principaux composants d’un environnement RL:
- Environnement: Le système externe, le monde ou le contexte. L’agent interagit avec l’environnement en une série d’intervalles de temps. À chaque intervalle de temps, en fonction de l’action de l’agent, l’environnement:
- Donne une récompense (ou une pénalité)
- Décide de l’état suivant
- État: Une représentation mathématique de la configuration actuelle de l’environnement.
- Par exemple, l’état d’un environnement de pendule peut inclure la position du pendule et la vitesse angulaire à chaque instant.
- État terminal : Un état qui ne mène pas à de nouveaux/autres états.
- Agent : L’algorithme qui observe l’environnement et prend diverses actions en fonction de cette observation. L’objectif de l’agent est de maximiser ses récompenses.
- Par exemple, l’agent décide de la force et de la direction avec lesquelles pousser le pendule.
- Observation: Une représentation mathématique de la vision de l’agent de l’environnement, acquise, par exemple, à l’aide de capteurs.
- Action: La décision prise par l’agent avant de passer à l’étape suivante. L’action affecte l’état suivant de l’environnement et rapporte à l’agent une récompense.
- Récompense: Le retour de l’environnement à l’agent. Il peut être positif ou négatif, en fonction de l’action et de l’état de l’environnement.
- Retourner: Le retour cumulatif attendu sur les prochains pas de temps. Les récompenses des prochains pas de temps peuvent être actualisées en utilisant un facteur d’actualisation.
- Politique: La stratégie de l’agent concernant quelle action prendre dans divers états. Elle est généralement représentée sous forme de matrice de probabilité, P, qui associe les états aux actions.
- Étant donné un ensemble fini de m états possibles et n actions possibles, l’élément Pmn dans la matrice désigne la probabilité de prendre l’action an dans l’état sm.
- Épisode: La série de pas de temps depuis l’état initial (randomisé) jusqu’à ce que l’agent atteigne un état terminal.
Espace d’observation et espace d’action
L’observation est l’information que l’agent recueille sur l’environnement. Un agent, par exemple un robot, pourrait collecter des informations environnementales à l’aide de capteurs. Idéalement, l’agent devrait être capable d’observer l’état complet, qui décrit tous les aspects de l’environnement. En pratique, l’agent utilise ses observations comme un substitut de l’état. Ainsi, les observations déterminent les actions de l’agent.
Un espace est analogue à un ensemble mathématique. L’espace d’éléments X comprend toutes les instances possibles de X. L’espace de X définit également la structure (syntaxe et format) de tous les éléments de type X. Chaque environnement de Gymnase a deux espaces, l’espace d’action, action_space
, et l’espace d’observation, observation_space
. Les espaces d’action et d’observation dérivent tous deux de la superclasse parent gymnasium.spaces.Space
.
Espace d’observation
L’espace d’observation est l’espace qui inclut toutes les observations possibles. Il définit également le format dans lequel les observations sont stockées. L’espace d’observation est généralement représenté comme un objet de type Box. Il s’agit d’un ndarray qui décrit les paramètres des observations. La boîte spécifie les limites de chaque dimension. Vous pouvez afficher l’espace d’observation pour un environnement en utilisant la méthode observation_space
:
print("observation space: ", env.observation_space)
Dans le cas de l’environnement CartPole-v1
, la sortie ressemble à l’exemple ci-dessous :
observation space: Box([-4.8 -inf -0.41887903 -inf], [4.8 inf 0.41887903 inf], (4,), float32)
Dans cet exemple, l’espace d’observation CartPole-v1
a 4 dimensions. Les 4 éléments du tableau d’observation sont :
- Position du chariot – varie entre -4.8 et +4.8
- Vitesse du chariot – varie entre – et +
- Angle du poteau – varie entre -0,4189 et +0,4189
- Vitesse angulaire des pôles – varie entre – et +
Pour voir un exemple d’un tableau d’observation individuel, utilisez la commande .reset()
.
observation, info = env.reset() print("observation: ", observation)
Dans le cas de l’environnement CartPole-v1
, la sortie ressemble à l’exemple ci-dessous :
[ 0.03481963 -0.0277232 0.01703267 -0.04870504]
Les quatre éléments de cet array correspondent aux quatre quantités observées (position du chariot, vitesse du chariot, angle du poteau, vitesse angulaire du poteau), comme expliqué précédemment.
Espace d’action
L’espace d’action comprend toutes les actions possibles que l’agent peut prendre. L’espace d’action définit également le format dans lequel les actions sont représentées. Vous pouvez visualiser l’espace d’action pour un environnement en utilisant la méthode action_space
:
print("action space: ", env.action_space)
Dans le cas de l’environnement CartPole-v1
, la sortie ressemble à l’exemple ci-dessous :
action space: Discrete(2)
Dans le cas de l’environnement CartPole-v1
, l’espace d’action est discret. Il y a un total de deux actions que l’agent peut effectuer :
- 0 : Pousser le chariot vers la gauche
- 1 : Pousser le chariot vers la droite
Construction de votre premier agent RL avec Gymnasium
Dans les sections précédentes, nous avons exploré les concepts de base du RL et de Gymnasium. Cette section vous montre comment utiliser Gymnasium pour construire un agent RL.
Création et réinitialisation de l’environnement
La première étape consiste à créer une instance de l’environnement. Pour créer de nouveaux environnements, utilisez la méthode .make()
.
env = gym.make('CartPole-v1')
Les interactions de l’agent modifient l’état de l’environnement. La méthode .reset()
réinitialise l’environnement à un état initial. Par défaut, l’environnement est initialisé à un état aléatoire. Vous pouvez utiliser un paramètre SEED
avec la méthode .reset()
pour initialiser l’environnement au même état chaque fois que le programme est exécuté. Le code ci-dessous montre comment faire cela :
SEED = 1111 env.reset(seed=SEED)
L’échantillonnage des actions implique également une part de hasard. Pour contrôler ce hasard et obtenir un chemin d’entraînement entièrement reproductible, nous pouvons initialiser les générateurs aléatoires de NumPy et PyTorch :
np.random.seed(SEED) torch.manual_seed(SEED)
Actions aléatoires versus actions intelligentes
À chaque étape d’un processus de Markov, l’agent peut choisir une action au hasard et explorer l’environnement jusqu’à atteindre un état terminal. En choisissant des actions de manière aléatoire :
- Il peut falloir beaucoup de temps pour atteindre l’état terminal.
- Les récompenses cumulées sont bien inférieures à ce qu’elles auraient pu être.
Former l’agent à optimiser la sélection des actions en fonction des expériences précédentes (d’interaction avec l’environnement) est plus efficace pour maximiser les récompenses à long terme.
L’agent non entraîné commence avec des actions aléatoires basées sur une politique initialisée au hasard. Cette politique est généralement représentée comme un réseau de neurones. Pendant l’entraînement, l’agent apprend la politique optimale qui maximise les récompenses. Dans l’apprentissage par renforcement, le processus d’entraînement est également appelé optimisation de la politique.
Il existe différentes méthodes d’optimisation de la politique. Les équations de Bellman décrivent comment calculer la valeur des politiques en apprentissage par renforcement et déterminer la politique optimale. Dans ce tutoriel, nous utiliserons une technique simple appelée gradients de politique. D’autres méthodes existent, telles que l’optimisation de politique proximale (PPO).
Implémentation d’un agent simple basé sur les gradients de politique
Pour créer un agent RL qui utilise des gradients de politique, nous créons un réseau neuronal pour implémenter la politique, écrivons des fonctions pour calculer les rendements et les pertes à partir des récompenses étape par étape et des probabilités d’action, et mettons à jour itérativement la politique en utilisant des techniques standard de rétropropagation.
Mise en place du réseau de politique
Nous utilisons un réseau neuronal pour implémenter la politique. Parce que CartPole-v1
est un environnement simple, nous utilisons un réseau neuronal avec :
- Des dimensions d’entrée égales à la dimension de l’espace d’observation de l’environnement.
- Une seule couche cachée avec 64 neurones.
- Les dimensions de sortie sont égales à la dimension de l’espace d’action de l’environnement.
Ainsi, la fonction du réseau de politique est de mapper les états observés aux actions. Étant donné une observation en entrée, il prédit la bonne action. Le code ci-dessous implémente le réseau de politique :
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
Collecte de récompenses et passage en avant
Comme mentionné, à chaque étape du processus de Markov, l’environnement donne une récompense basée sur l’action et l’état de l’agent. L’objectif en RL est de maximiser le retour total.
- Le retour à chaque pas de temps est la somme cumulative des récompenses obtenues depuis le début jusqu’à cette étape.
- Le retour total de chaque épisode est obtenu en accumulant toutes les récompenses étape par étape de cet épisode. Ainsi, le retour total est le retour à la dernière étape (lorsque l’agent atteint un état terminal).
En pratique, lors de l’accumulation des récompenses, il est courant de :
- Ajuster les récompenses futures en utilisant un facteur d’actualisation.
- Normaliser le tableau des retours étape par étape pour garantir un entraînement fluide et stable.
Le code ci-dessous montre comment faire cela :
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
Le passage avant consiste à faire fonctionner l’agent en fonction de la politique actuelle jusqu’à ce qu’il atteigne un état terminal et à collecter les récompenses étape par étape et les probabilités d’action. Les étapes ci-dessous expliquent comment mettre en œuvre le passage avant :
- Réinitialisez l’environnement à un état initial.
- Initialisez des tampons pour stocker les probabilités d’action, les récompenses et le retour cumulatif
- Utilisez la fonction
.step()
pour exécuter de manière itérative l’agent dans l’environnement jusqu’à ce qu’il se termine : - Obtenez l’observation de l’état de l’environnement.
- Obtenez l’action prédite par la politique basée sur l’observation.
- Utilisez la fonction
Softmax
pour estimer la probabilité de prendre l’action prédite. - Simulez une distribution de probabilité catégorielle basée sur ces probabilités estimées.
- Échantillonnez cette distribution pour obtenir l’action de l’agent.
- Estimez la probabilité logarithmique de l’action échantillonnée à partir de la distribution simulée.
- Ajoutez la probabilité logarithmique des actions et des récompenses de chaque étape à leurs tampons respectifs.
- Estimez les valeurs normalisées et actualisées des retours à chaque étape en fonction des récompenses.
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
Mise à jour de la politique basée sur les récompenses
La perte représente la quantité sur laquelle nous appliquons la descente de gradient. L’objectif en RL est de maximiser les retours. Ainsi, nous utilisons la valeur de retour attendue comme un proxy pour la perte. La valeur de retour attendue est calculée comme le produit des retours attendus par étape et de la probabilité logarithmique des actions par étape. Le code ci-dessous calcule la perte:
def calculate_loss(stepwise_returns, log_prob_actions): loss = -(stepwise_returns * log_prob_actions).sum() return loss
Pour mettre à jour la politique, vous exécutez la retropropagation par rapport à la fonction de perte. La méthode update_policy()
ci-dessous invoque la méthode calculate_loss()
. Ensuite, elle exécute la rétropropagation sur cette perte pour mettre à jour les paramètres de la politique, c’est-à-dire les poids du modèle du réseau de politique.
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()
Mettre à jour la politique en fonction du gradient des retours est appelé la méthode des gradients de politique.
Entraîner la politique
Nous avons maintenant tous les composants nécessaires pour entraîner et évaluer la politique. Nous implémentons la boucle d’entraînement comme expliqué dans les étapes suivantes :
Avant de commencer, nous déclarons les hyperparamètres, instancions une politique et créons un optimiseur :
- Déclarez les hyperparamètres en tant que constantes Python :
MAX_EPOCHS
est le nombre maximum d’itérations que nous sommes prêts à exécuter pour entraîner la politique.DISCOUNT_FACTOR
décide de l’importance relative des récompenses des étapes futures. Un facteur de réduction de 1 signifie que toutes les récompenses sont également importantes, tandis qu’une valeur de 0 signifie que seule la récompense de l’étape temporelle actuelle est importante.N_TRIALS
est le nombre d’épisodes sur lesquels nous calculons la moyenne des rendements pour évaluer la performance de l’agent. Nous considérons que l’entraînement est réussi si le rendement moyen surN_TRIALS
épisodes est supérieur au seuil.REWARD_THRESHOLD
: Si la politique peut atteindre un rendement supérieur au seuil, elle est considérée comme réussie.DROPOUT
décide de la fraction des poids qui doivent être aléatoirement mis à zéro. La fonction de dropout met aléatoirement à zéro une fraction des poids du modèle. Cela réduit la dépendance à des neurones spécifiques et prévient le surajustement, rendant le réseau plus robuste.TAUX_APPRENTISSAGE
décide dans quelle mesure les paramètres de la politique peuvent être modifiés à chaque étape. La mise à jour des paramètres à chaque itération est le produit du gradient et du taux d’apprentissage.- Définissez la politique en tant qu’instance de la classe
PolicyNetwork
(implémentée précédemment). - Créez un optimiseur en utilisant l’algorithme Adam et le taux d’apprentissage.
Pour entraîner la politique, nous exécutons de manière itérative les étapes d’entraînement jusqu’à ce que le retour moyen (sur N_TRIALS
) soit supérieur au seuil de récompense :
- Pour chaque épisode, exécutez la passe avant une fois. Collectez la probabilité logarithmique des actions, les retours étape par étape, et le retour total de cet épisode. Accumulez les retours épisodiques dans un tableau.
- Calculez la perte en utilisant les probabilités logarithmiques et les rendements par étapes. Effectuez la rétropropagation sur la perte. Utilisez l’optimiseur pour mettre à jour les paramètres de la politique.
- Vérifiez si le rendement moyen sur
N_TRIALS
dépasse le seuil de récompense.
Le code ci-dessous implémente ces étapes :
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
Enfin, invoquez la fonction main()
pour entraîner la politique :
main()
Utilisez ce carnet de données DataLab pour exécuter l’algorithme ci-dessus directement et résoudre l’environnement CartPole en utilisant RL.
Techniques avancées dans Gymnasium
Après avoir démontré comment implémenter un algorithme RL, nous discutons maintenant de certaines techniques avancées couramment utilisées en pratique.
Utilisation d’architectures préconstruites
L’implémentation d’algorithmes RL à partir de zéro est un processus long et difficile, surtout pour des environnements complexes et des politiques à la pointe de la technologie.
Une alternative plus pratique est d’utiliser des logiciels comme Stable Baselines3. Il propose des implémentations éprouvées d’algorithmes RL. Il comprend des agents pré-entraînés, des scripts d’entraînement, des outils d’évaluation et des modules pour tracer des graphiques et enregistrer des vidéos.
Ray RLib est un autre outil populaire pour le RL. RLib est conçu comme une solution évolutive, ce qui facilite la mise en œuvre des algorithmes RL sur des systèmes multi-GPU. Il prend également en charge le RL multi-agent, ce qui ouvre de nouvelles possibilités telles que :
- Apprentissage multi-agent indépendant : Chaque agent considère les autres agents comme faisant partie de l’environnement.
- Entraînement multi-agents collaboratif : Un groupe d’agents partage la même politique et les mêmes fonctions de valeur et apprend les uns des expériences des autres en parallèle.
- Entraînement adversarial : Les agents (ou groupes d’agents) se disputent dans des environnements compétitifs de type jeu.
Avec RLib et Stable Baselines3, vous pouvez importer et utiliser des environnements de OpenAI Gymnasium.
Environnements personnalisés
Les environnements fournis avec Gymnasium sont le bon choix pour tester de nouvelles stratégies de RL et entraîner des politiques. Cependant, pour la plupart des applications pratiques, vous devez créer et utiliser un environnement qui reflète avec précision le problème que vous souhaitez résoudre. Vous pouvez utiliser Gymnasium pour créer un environnement personnalisé. L’avantage d’utiliser des environnements personnalisés de Gymnasium est que de nombreux outils externes comme RLib et Stable Baselines3 sont déjà configurés pour fonctionner avec la structure de l’API de Gymnasium.
Pour créer un environnement personnalisé dans Gymnasium, vous devez définir :
- L’espace d’observation.
- Les conditions terminales.
- L’ensemble des actions que l’agent peut choisir.
- Comment initialiser l’environnement (lorsque la fonction
reset()
est appelée). - Comment l’environnement décide de l’état suivant en fonction des actions de l’agent (lorsque la fonction
step()
est appelée).
Pour en savoir plus, suivez le guide du Gymnase sur la création d’environnements personnalisés.
Meilleures pratiques pour utiliser le Gymnase
Expérimentez avec différents environnements
Le code de ce tutoriel a montré comment implémenter l’algorithme du gradient de politique dans l’environnement CartPole. Il s’agit d’un environnement simple avec un espace d’action discret. Pour mieux comprendre l’apprentissage par renforcement, nous vous conseillons d’appliquer le même algorithme du gradient de politique (et d’autres algorithmes, comme PPO) dans d’autres environnements.
Par exemple, l’environnement Pendulum a un espace d’action continu. Il se compose d’une seule entrée représentée sous forme de variable continue – le couple (magnitude et direction du) appliqué au pendule dans n’importe quel état. Ce couple peut prendre n’importe quelle valeur entre -2 et +2.
Expérimenter avec différents algorithmes dans divers environnements vous aide à mieux comprendre différents types de solutions RL et leurs défis.
Suivre la progression de l’entraînement
Les environnements de RL consistent souvent en des robots, des pendules, des voitures de montagne, des jeux vidéo, etc. La visualisation des actions de l’agent dans l’environnement permet une meilleure compréhension intuitive des performances de la politique.
Dans Gymnasium, la méthode env.render()
visualise les interactions de l’agent avec l’environnement. Elle affiche graphiquement l’état actuel de l’environnement – les écrans de jeu, la position du pendule ou du poteau de chariot, etc. Les retours visuels sur les actions de l’agent et les réponses de l’environnement aident à surveiller les performances de l’agent et sa progression tout au long du processus d’entraînement.
Il existe quatre modes de rendu : « humain », « rgb_array », « ansi » et « rgb_array_list ». Pour visualiser les performances de l’agent, utilisez le mode de rendu « humain ». Le mode de rendu est spécifié lors de l’initialisation de l’environnement. Par exemple :
env = gym.make(‘CartPole-v1’, render_mode=’human’)
Pour effectuer le rendu, impliquez la méthode .render()
après chaque action effectuée par l’agent (en appelant la méthode .step()
). Le pseudo-code ci-dessous illustre comment faire cela :
while not done: … step, reward, terminated, truncated, info = env.step(action.item()) env.render() …
Résolution des erreurs courantes
Gymnasium facilite l’interface avec des environnements RL complexes. Cependant, c’est un logiciel constamment mis à jour avec de nombreuses dépendances. Ainsi, il est essentiel de rester attentif à quelques types d’erreurs courantes.
Correspondance des versions
- Version incohérente du Gymnase: Le logiciel Gymnasium de Farama a été bifurqué à partir du Gymnase d’OpenAI depuis la version 0.26.2. Il y a eu quelques changements importants entre les anciennes versions du Gymnase et les nouvelles versions du Gymnasium. De nombreuses implémentations disponibles publiquement sont basées sur les anciennes versions du Gymnase et peuvent ne pas fonctionner directement avec la dernière version. Dans de tels cas, il est nécessaire soit de revenir à une ancienne version de l’installation, soit d’adapter le code pour fonctionner avec la nouvelle version.
- Version de l’environnement incompatible: De nombreux environnements de gymnase ont des versions différentes. Par exemple, il y a deux environnements CartPole –
CartPole-v1
etCartPole-v0
. Bien que le comportement de l’environnement soit le même pour les deux versions, certains paramètres, tels que la durée de l’épisode, le seuil de récompense, etc., peuvent être différents. Une politique entraînée sur une version peut ne pas bien fonctionner sur une autre version du même environnement. Vous devez mettre à jour les paramètres d’entraînement et ré-entraîner la politique pour chaque version de l’environnement. - Problème de conflit de versions des dépendances : Gymnasium dépend de bibliothèques telles que NumPy et PyTorch. En décembre 2024, les versions les plus récentes de ces dépendances sont
numpy 2.1.3
ettorch 2.5.1
. Cependant, Gymnasium fonctionne mieux avectorch 1.13.0
etnumpy 1.23.3
. Vous pourriez rencontrer des problèmes si vous installez Gymnasium dans un environnement avec ces dépendances déjà installées. Nous vous recommandons d’installer et de travailler avec Gymnasium dans un nouvel environnement Conda.
Problèmes de convergence.
- Hyperparamètres: Comme d’autres algorithmes d’apprentissage automatique, les politiques de RL sont sensibles aux hyperparamètres tels que le taux d’apprentissage, le facteur de remise, etc. Nous recommandons d’expérimenter et d’ajuster les hyperparamètres manuellement ou en utilisant des techniques automatisées comme la recherche en grille et la recherche aléatoire.
- Exploration versus exploitation: Pour certaines classes de politiques (comme le PPO), l’agent adopte une stratégie à deux volets : explorer l’environnement pour découvrir de nouveaux chemins et adopter une approche avide pour maximiser les récompenses en fonction des chemins connus jusqu’à présent. S’il explore trop, la politique ne converge pas. En revanche, elle n’essaie jamais le chemin optimal si elle n’explore pas assez. Ainsi, trouver le bon équilibre entre l’exploration et l’exploitation est essentiel. Il est également courant de prioriser l’exploration dans les premiers épisodes et l’exploitation dans les épisodes ultérieurs pendant l’entraînement.
Instabilité de l’entraînement
- Taux d’apprentissage élevés : Si le taux d’apprentissage est trop élevé, les paramètres de la politique subissent de grandes mises à jour à chaque étape. Cela pourrait potentiellement conduire à manquer l’ensemble optimal de valeurs. Une solution courante consiste à réduire progressivement le taux d’apprentissage, garantissant des mises à jour plus petites et plus stables à mesure que l’entraînement converge.
- Exploration excessive : Trop de randomité (entropie) dans la sélection des actions empêche la convergence et entraîne de grandes variations dans la fonction de perte entre les étapes successives. Pour avoir un processus d’entraînement stable et convergent, il est important d’équilibrer l’exploration avec l’exploitation.
- Mauvais choix d’algorithme : Des algorithmes simples comme le gradient de politique peuvent conduire à un entraînement instable dans des environnements complexes avec de grands espaces d’action et d’état. Dans de tels cas, nous recommandons d’utiliser des algorithmes plus robustes comme PPO et l’optimisation de politique par région de confiance (TRPO). Ces algorithmes évitent de grandes mises à jour de politique à chaque étape et peuvent être plus stables.
- Aléa : Les algorithmes RL sont notoirement sensibles aux états initiaux et à l’aléa inhérent à la sélection d’actions. Lorsqu’un entraînement est instable, il peut parfois être stabilisé en utilisant une graine aléatoire différente ou en réinitialisant la politique.
Conclusion
Dans ce tutoriel, nous avons exploré les principes de base de RL, discuté de Gymnasium en tant que package logiciel avec une API propre pour interagir avec divers environnements RL, et montré comment écrire un programme Python pour implémenter un algorithme RL simple et l’appliquer dans un environnement Gymnasium.
Après avoir compris les bases de ce tutoriel, je recommande d’utiliser les environnements Gymnasium pour appliquer les concepts de RL afin de résoudre des problèmes pratiques tels que l’optimisation des trajets en taxi et les simulations de trading d’actions.
Source:
https://www.datacamp.com/tutorial/reinforcement-learning-with-gymnasium