From b88c22e93a13105d614864bf8b28c646c0048fea Mon Sep 17 00:00:00 2001
From: Jossua Seksik <jossua.seksik@ecl20.ec-lyon.fr>
Date: Tue, 5 Mar 2024 19:46:29 +0100
Subject: [PATCH] 2 scripts & Readme

---
 README.md             | 195 ++----------------------------------------
 a2c_sb3_cartpole.py   |  28 ++++++
 image.png             | Bin 0 -> 36284 bytes
 reinforce_cartpole.py |  96 +++++++++++++++++++++
 4 files changed, 132 insertions(+), 187 deletions(-)
 create mode 100644 a2c_sb3_cartpole.py
 create mode 100644 image.png
 create mode 100644 reinforce_cartpole.py

diff --git a/README.md b/README.md
index 009ba30..1b112f4 100644
--- a/README.md
+++ b/README.md
@@ -2,209 +2,30 @@
 
 MSO 3.4 Apprentissage Automatique
 
-# 
-
-In this hands-on project, we will first implement a simple RL algorithm and apply it to solve the CartPole-v1 environment. Once we become familiar with the basic workflow, we will learn to use various tools for machine learning model training, monitoring, and sharing, by applying these tools to train a robotic arm.
-
-## To be handed in
-
-This work must be done individually. The expected output is a repository named `hands-on-rl` on https://gitlab.ec-lyon.fr. 
-
-We assume that `git` is installed, and that you are familiar with the basic `git` commands. (Optionnaly, you can use GitHub Desktop.)
-We also assume that you have access to the [ECL GitLab](https://gitlab.ec-lyon.fr/). If necessary, please consult [this tutorial](https://gitlab.ec-lyon.fr/edelland/inf_tc2/-/blob/main/Tutoriel_gitlab/tutoriel_gitlab.md).
-
-Your repository must contain a `README.md` file that explains **briefly** the successive steps of the project. It must be private, so you need to add your teacher as "developer" member.
-
-Throughout the subject, you will find a 🛠 symbol indicating that a specific production is expected.
-
-The last commit is due before 11:59 pm on March 5, 2024. Subsequent commits will not be considered.
-
-> ⚠️ **Warning**
-> Ensure that you only commit the files that are requested. For example, your directory should not contain the generated `.zip` files, nor the `runs` folder... At the end, your repository must contain one `README.md`, three python scripts, and optionally image files for the plots.
-
-## Before you start
-
-Make sure you know the basics of Reinforcement Learning. In case of need, you can refer to the [introduction of the Hugging Face RL course](https://huggingface.co/blog/deep-rl-intro).
-
-## Introduction to Gym
-
-[Gym](https://gymnasium.farama.org/) is a framework for developing and evaluating reinforcement learning environments. It offers various environments, including classic control and toy text scenarios, to test RL algorithms.
 
 ### Installation
 
-We recommend to use Python virtual environnements to install the required modules : https://docs.python.org/3/library/venv.html
-
-First, install Pytorch : https://pytorch.org/get-started/locally.
-
-Then install the following modules :
-
+Modules to be installed in order to start the project :
 
 ```sh
 pip install gym==0.26.2
-```
-
-Install also pyglet for the rendering.
-
-```sh
 pip install pyglet==2.0.10
-```
-
-If needed 
-
-```sh
 pip install pygame==2.5.2
-```
-
-```sh
 pip install PyQt5
-```
-
-
-### Usage
-
-Here is an example of how to use Gym to solve the `CartPole-v1` environment [Documentation](https://gymnasium.farama.org/environments/classic_control/cart_pole/):
-
-```python
-import gym
-
-# Create the environment
-env = gym.make("CartPole-v1", render_mode="human")
-
-# Reset the environment and get the initial observation
-observation = env.reset()
-
-for _ in range(100):
-    # Select a random action from the action space
-    action = env.action_space.sample()
-    # Apply the action to the environment
-    # Returns next observation, reward, done signal (indicating
-    # if the episode has ended), and an additional info dictionary
-    observation, reward, terminated, truncated, info = env.step(action)
-    # Render the environment to visualize the agent's behavior
-    env.render()
-    if terminated: 
-        # Terminated before max step
-        break
-
-env.close()
-```
-
-## REINFORCE
-
-The REINFORCE algorithm (also known as Vanilla Policy Gradient) is a policy gradient method that optimizes the policy directly using gradient descent. The following is the pseudocode of the REINFORCE algorithm:
-
-```txt
-Setup the CartPole environment
-Setup the agent as a simple neural network with:
-    - One fully connected layer with 128 units and ReLU activation followed by a dropout layer
-    - One fully connected layer followed by softmax activation
-Repeat 500 times:
-    Reset the environment
-    Reset the buffer
-    Repeat until the end of the episode:
-        Compute action probabilities 
-        Sample the action based on the probabilities and store its probability in the buffer 
-        Step the environment with the action
-        Compute and store in the buffer the return using gamma=0.99 
-    Normalize the return
-    Compute the policy loss as -sum(log(prob) * return)
-    Update the policy using an Adam optimizer and a learning rate of 5e-3
-```
 
-To learn more about REINFORCE, you can refer to [this unit](https://huggingface.co/learn/deep-rl-course/unit4/introduction).
-
-> 🛠 **To be handed in**
-> Use PyTorch to implement REINFORCE and solve the CartPole environement. Share the code in `reinforce_cartpole.py`, and share a plot showing the total reward accross episodes in the `README.md`.
-
-## Familiarization with a complete RL pipeline: Application to training a robotic arm
-
-In this section, you will use the Stable-Baselines3 package to train a robotic arm using RL. You'll get familiar with several widely-used tools for training, monitoring and sharing machine learning models.
-
-### Get familiar with Stable-Baselines3
-
-Stable-Baselines3 (SB3) is a high-level RL library that provides various algorithms and integrated tools to easily train and test reinforcement learning models.
-
-#### Installation
-
-```sh
 pip install stable-baselines3
 pip install moviepy
 ```
 
-#### Usage
-
-Use the [Stable-Baselines3 documentation](https://stable-baselines3.readthedocs.io/en/master/) to implement the code to solve the CartPole environment with the Advantage Actor-Critic (A2C) algorithm.
-
-
-> 🛠 **To be handed in**
-> Store the code in `a2c_sb3_cartpole.py`. Unless otherwise stated, you'll work upon this file for the next sections.
-
-### Get familiar with Hugging Face Hub
-
-Hugging Face Hub is a platform for easy sharing and versioning of trained machine learning models. With Hugging Face Hub, you can quickly and easily share your models with others and make them usable through the API. For example, see the trained A2C agent for CartPole: https://huggingface.co/sb3/a2c-CartPole-v1. Hugging Face Hub provides an API to download and upload SB3 models.
-
-#### Installation of `huggingface_sb3`
-
-```sh
-pip install huggingface-sb3==2.3.1
-```
-
-#### Upload the model on the Hub
-
-Follow the [Hugging Face Hub documentation](https://huggingface.co/docs/hub/stable-baselines3) to upload the previously learned model to the Hub.
-
-> 🛠 **To be handed in**
-> Link the trained model in the `README.md` file.
-
-> 📝 **Note**
->  [RL-Zoo3](https://stable-baselines3.readthedocs.io/en/master/guide/rl_zoo.html) provides more advanced features to save hyperparameters, generate renderings and metrics. Feel free to try them.
-
-### Get familiar with Weights & Biases
-
-Weights & Biases (W&B) is a tool for machine learning experiment management. With W&B, you can track and compare your experiments, visualize your model training and performance.
-
-#### Installation
-
-You'll need to install both `wand` and `tensorboar`.
-
-```shell
-pip install wandb tensorboard
-```
-
-Use the documentation of [Stable-Baselines3](https://stable-baselines3.readthedocs.io/en/master/) and [Weights & Biases](https://docs.wandb.ai/guides/integrations/stable-baselines-3) to track the CartPole training. Make the run public.
-
-🛠 Share the link of the wandb run in the `README.md` file.
-
-> ⚠️ **Warning**
-> Make sure to make the run public!
-
-### Full workflow with panda-gym
-
-[Panda-gym](https://github.com/qgallouedec/panda-gym) is a collection of environments for robotic simulation and control. It provides a range of challenges for training robotic agents in a simulated environment. In this section, you will get familiar with one of the environments provided by panda-gym, the `PandaReachJointsDense-v3`. The objective is to learn how to reach any point in 3D space by directly controlling the robot's articulations.
-
-#### Installation
-
-```shell
-pip install panda-gym==3.0.7
-```
-
-#### Train, track, and share
-
-Use the Stable-Baselines3 package to train A2C model on the `PandaReachJointsDense-v2` environment. 500k timesteps should be enough. Track the environment with Weights & Biases. Once the training is over, upload the trained model on the Hub.
-
-> 🛠 **To be handed in**
-> Share all the code in `a2c_sb3_panda_reach.py`. Share the link of the wandb run and the trained model in the `README.md` file.
-
-## Contribute
-
-This tutorial may contain errors, inaccuracies, typos or areas for improvement. Feel free to contribute to its improvement by opening an issue.
+## REINFORCE
 
-## Author
+You will find the reinforcement algorithm on the .py file : 'reinforce_cartpole.py'.
 
-Quentin Gallouédec
+Here is the final plot obtained after running it, showing the total reward after the 200 episodes.
 
-Updates by Léo Schneider, Emmanuel Dellandréa
+![alt text](image.png)
 
-## License
+## Stable-Baselines3 and HuggingFace
 
-MIT
+We are now solving the CartPole with the A2C algorithm, from the Stable-Baselines3 package.
+We saved the model through Hugging Face, which is available via the following link : https://huggingface.co/jossuaseksik/a2c-sb3_cartpole/tree/main
diff --git a/a2c_sb3_cartpole.py b/a2c_sb3_cartpole.py
new file mode 100644
index 0000000..32bc0f3
--- /dev/null
+++ b/a2c_sb3_cartpole.py
@@ -0,0 +1,28 @@
+import gym
+from stable_baselines3 import A2C
+from gymnasium.envs.registration import register
+from huggingface_sb3 import push_to_hub
+
+
+config = {
+    "policy_type": "MlpPolicy",
+    "total_timesteps": 5000,
+    "env_name": "CartPole-v1",
+    }
+
+
+register(id="CartPole-v1", entry_point='gym.envs.classic_control:CartPoleEnv', max_episode_steps=200)
+
+env = gym.make("CartPole-v1", render_mode="rgb_array")
+
+model = A2C("MlpPolicy", env, verbose=1)
+model.learn(total_timesteps=config["total_timesteps"])
+
+model.save("CartPole-v1.zip")
+
+push_to_hub(
+    repo_id="jossuaseksik/a2c-sb3_cartpole",
+    filename="CartPole-v1.zip",
+    commit_message="Adding CartPole model trained with A2C on HuggingFace",
+    token="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"
+)
diff --git a/image.png b/image.png
new file mode 100644
index 0000000000000000000000000000000000000000..59fdf54caa6ef3a676612dbad4245f41682f57af
GIT binary patch
literal 36284
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

literal 0
HcmV?d00001

diff --git a/reinforce_cartpole.py b/reinforce_cartpole.py
new file mode 100644
index 0000000..0eec71b
--- /dev/null
+++ b/reinforce_cartpole.py
@@ -0,0 +1,96 @@
+import matplotlib.pyplot as plt
+
+# PyTorch
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import torch.optim as optim
+from torch.distributions import Categorical
+
+# Gym
+import gym
+import pygame
+
+
+env_id = "CartPole-v1"
+# Create the env
+env = gym.make(env_id, render_mode="human")
+
+# Get the state space and action space
+s_size = env.observation_space.shape[0]
+a_size = env.action_space.n
+
+# 4 entrées : la position du cart, sa vitesse, l'angle de la barre, sa vitesse angulaire 
+# 2 sorties : aller à droite et aller a gauche
+agent = nn.Sequential(nn.Linear(s_size, 128),
+                         nn.ReLU(),
+                         nn.Dropout(),
+                         nn.Linear(128,a_size),
+                         nn.Softmax()) 
+
+print(agent)
+
+optimizer = optim.Adam(agent.parameters(), lr=5e-3)
+
+episode_rewards = []
+gamma=0.99
+
+for _ in range (200):
+    observation = env.reset()
+    
+    rewards = []
+    log_probs = []
+    terminated = False
+    total_reward = 0
+
+    while not(terminated):
+        # Convert observation to tensor
+        observation_array = observation[0] if isinstance(observation, tuple) else observation
+        observation_tensor = torch.FloatTensor(observation_array).unsqueeze(0)
+        # observation_tensor = torch.FloatTensor(observation).unsqueeze(0)
+        # Compute action probabilities
+        probs = agent(observation_tensor)
+        m = Categorical(probs)
+        # Sample action
+        action = m.sample()
+        log_prob = m.log_prob(action)
+        observation, reward, terminated, truncated, info = env.step(action.item())
+        env.render()
+        
+        log_probs.append(log_prob)
+        rewards.append(reward)
+        total_reward += reward
+        
+
+    episode_rewards.append(total_reward)
+
+    # Compute returns
+    R = 0
+    returns = []
+    for r in rewards[::-1]:
+        R = r + gamma * R
+        returns.insert(0, R)
+    returns = torch.tensor(returns)
+    returns = (returns - returns.mean()) / (returns.std() + 1e-5)
+
+    # Compute policy loss
+    policy_loss = []
+    for log_prob, R in zip(log_probs, returns):
+        policy_loss.append(log_prob * R)
+    policy_loss = - torch.cat(policy_loss).sum()
+
+    # Update policy
+    optimizer.zero_grad()
+    policy_loss.backward()
+    optimizer.step()
+
+    print(f'Episode {_} finished')
+
+env.close()
+
+
+plt.plot(episode_rewards)
+plt.title('Total Reward per Episode')
+plt.xlabel('Episode')
+plt.ylabel('Total Reward')
+plt.show()
\ No newline at end of file
-- 
GitLab