{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "adZiEPrJGbby" }, "source": [ "# PPO\n", "\n", "The goal of this exercise is to use the `tianshou` library to apply PPO on the cartpole environment. `tianshou` is the latest and most up-to-date DRL library. It is based on pytorch for the deep networks and is the only library currently compatible with gymnasium, not gym.\n", "\n", "Github: \\\n", "Documentation: \n", "\n", "Install it in a new virtual environment simply with:\n", "\n", "```bash\n", "pip install -U gymnasium==0.28.1 pygame swig moviepy==1.0.3\n", "pip install -U tianshou\n", "```\n", "\n", "It will also install pytorch. It is strongly advised to create a new environment, as it requires an older version of gymnasium (0.28.1) than the one currently available (1.x).\n", "\n", "Let's first import the usual stuff:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "qDFNoQzZGbb0", "outputId": "9de7d1a4-f70b-457b-f1f0-de08399eac9e" }, "outputs": [], "source": [ "try:\n", " import google.colab\n", " IN_COLAB = True\n", "except:\n", " IN_COLAB = False\n", "\n", "if IN_COLAB:\n", " !pip install -U gymnasium==0.28.1 pygame swig\n", " !pip install -U moviepy==1.0.3\n", " !pip install -U tianshou" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "pfVxfZJwGbb1", "outputId": "515fb277-06fb-48d8-b5ac-068ee5e0bac9" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "gym version: 0.28.1\n", "tianshou version: 1.1.0\n", "Device: cpu\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/vitay/.virtualenvs/deeprl/.venv/lib/python3.12/site-packages/pygame/pkgdata.py:25: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html\n", " from pkg_resources import resource_stream, resource_exists\n" ] } ], "source": [ "import numpy as np\n", "rng = np.random.default_rng()\n", "import matplotlib.pyplot as plt\n", "import os\n", "from IPython.display import clear_output\n", "from collections import deque\n", "import tqdm\n", "\n", "import gymnasium as gym\n", "print(\"gym version:\", gym.__version__)\n", "\n", "import tianshou as ts\n", "print(\"tianshou version:\", ts.__version__)\n", "\n", "import torch\n", "if torch.cuda.is_available(): # GPU\n", " device = torch.device(\"cuda\")\n", "else: # CPU\n", " device = torch.device(\"cpu\")\n", "print(f\"Device: {device}\")\n", "\n", "import pygame\n", "from moviepy.editor import ImageSequenceClip, ipython_display\n", "\n", "\n", "class GymRecorder(object):\n", " \"\"\"\n", " Simple wrapper over moviepy to generate a .gif with the frames of a gym environment.\n", "\n", " The environment must have the render_mode `rgb_array_list`.\n", " \"\"\"\n", " def __init__(self, env):\n", " self.env = env\n", " self._frames = []\n", "\n", " def record(self, frames):\n", " \"To be called at the end of an episode.\"\n", " for frame in frames:\n", " self._frames.append(np.array(frame))\n", "\n", " def make_video(self, filename):\n", " \"Generates the gif video.\"\n", " directory = os.path.dirname(os.path.abspath(filename))\n", " if not os.path.exists(directory):\n", " os.mkdir(directory)\n", " self.clip = ImageSequenceClip(list(self._frames), fps=self.env.metadata[\"render_fps\"])\n", " self.clip.write_gif(filename, fps=self.env.metadata[\"render_fps\"], loop=0)\n", " del self._frames\n", " self._frames = []" ] }, { "cell_type": "markdown", "metadata": { "id": "BQfBNFaKGbb1" }, "source": [ "## tianshou\n", "\n", "### Structure\n", "\n", "``tianshou`` provides an implementation of most model-free algorithms seen in the course: DQN and its variants, A3C, DDPG, PPO and more. It also has several offline RL algorithms. You can see the list of algorithms here:\n", "\n", "\n", "\n", "``tianshou`` relies on several concepts, which are explained here:\n", "\n", "\n", "\n", "![](https://tianshou.readthedocs.io/en/latest/_images/concepts_arch2.png)\n", "\n", "* The **policy** is actually the DRL algorithm (DQN, PPO), not the mapping from states into actions used in the course. It relies on one (or more) neural networks called the **model**.\n", "* The interaction of the policy with the environment is done by the **collector**. By default, the collector used **distributed learning**, i.e. it uses parallel workers to interact with copies of the environment, thereby speeding up data collection. This is used even for algorithms which do not need distributed learning (DQN), as it is only beneficial.\n", "* The data collected by the collector is stored in a **buffer**, which can be an ERM for off-policy algorithms or a temporary buffer for on-policy ones.\n", "* The (distributed) data is stored in **batches**. How data circulates between the collector, the policy and the buffer during training is controlled by the **trainer**.\n", "\n", "Let's demonstrate this interaction with a dummy DQN network on Cartpole:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "NGu4yxawGbb2", "outputId": "1901d0b0-91ea-4a1e-e4ca-5d65ad1edc5d" }, "outputs": [], "source": [ "env = gym.make('CartPole-v0')" ] }, { "cell_type": "markdown", "metadata": { "id": "4jFmDJiJGbb2" }, "source": [ "### Policy\n", "\n", "The first step is to create the neural network for the DQN network. It must have `env.observation_space.shape=4` input neurons and `env.action_space.n=2` discrete output neurons. Let's put two hidden layers with 64 neurons for now:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "9F2zWhtjGbb2" }, "outputs": [], "source": [ "net = ts.utils.net.common.Net(\n", " env.observation_space.shape,\n", " env.action_space.n,\n", " hidden_sizes=[64, 64],\n", " device=device,\n", ").to(device)\n", "\n", "optim = torch.optim.Adam(net.parameters(), lr=0.001)" ] }, { "cell_type": "markdown", "metadata": { "id": "pqXfmFKvGbb2" }, "source": [ "`optim` is the Adam optimizer in pytorch, modifying all parameters (weights and biases) of the value network. Check the doc of `Net()` if you want a more specific architecture.\n", "\n", "The output layer of the network is discrete, so that tianshou knows how to sample an action from the output (here the output neurons represent the Q-values, but it could be logits of a continuous policy).\n", "\n", "Now that we have the neural network, we can create the DQN policy object:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "id": "JN5C_dnmGbb2" }, "outputs": [], "source": [ "policy = ts.policy.DQNPolicy(\n", " model=net, # value network\n", " optim=optim, # optimizer\n", " discount_factor=0.95, # gamma\n", " target_update_freq=1000, # how often to update the target network\n", " action_space=env.action_space, # action space\n", ")\n", "policy.set_eps(0.1) # epsilon-greedy action selection" ] }, { "cell_type": "markdown", "metadata": { "id": "falJwESWGbb3" }, "source": [ "Check the doc of `DQNPolicy` for additional parameters (e.g. to implement a double duelling DQN).\n", "\n", "We can now use the policy to interact with the environment as usual and visualize a trial with an untrained network:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 530 }, "id": "DIgKgYSVGbb3", "outputId": "892c632f-9e21-4ece-91e8-4a37d27b2193" }, "outputs": [], "source": [ "# Evaluation mode\n", "policy.eval()\n", "\n", "# Create a recordable environment\n", "env = gym.make('CartPole-v0', render_mode=\"rgb_array_list\")\n", "recorder = GymRecorder(env)\n", "\n", "# Sample the initial state\n", "state, info = env.reset()\n", "\n", "# One episode:\n", "done = False\n", "return_episode = 0\n", "while not done:\n", "\n", " # Select an action from the learned policy\n", " action = policy.forward(ts.data.Batch(obs=[state], info=None)).act[0]\n", "\n", " # Sample a single transition\n", " next_state, reward, terminal, truncated, info = env.step(action)\n", "\n", " # End of the episode\n", " done = terminal or truncated\n", "\n", " # Update undiscounted return\n", " return_episode += reward\n", "\n", " # Go in the next state\n", " state = next_state\n", "\n", "print(\"Return:\", return_episode)\n", "\n", "recorder.record(env.render())\n", "video = \"videos/cartpole-before.gif\"\n", "recorder.make_video(video)\n", "ipython_display(video)" ] }, { "cell_type": "markdown", "metadata": { "id": "ZumM2wCUGbb3" }, "source": [ "The action selection is done by calling `policy.forward()` on a batch of data containing only the current state:\n", "\n", "```python\n", "action = policy.forward(ts.data.Batch(obs=[state], info=None)).act[0]\n", "```\n", "\n", "### Collector\n", "\n", "As we have seen in the DQN exercise, using a neural network with a batch size of 1 is extremely inefficient and slow. It is much better to use **distributed learning** and parallel workers to collect data. That way, we can form a minibatch of states that can be processed efficiently by the NN." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "id": "6zvLrWhWGbb3" }, "outputs": [], "source": [ "collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " exploration_noise=True\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "tQLZduU8Gbb3" }, "source": [ "`policy` is the exploration policy. The `exploration_noise` flag allows to switch exploration on and off. For a discrete DQN policy, this impacts the $\\epsilon$-greedy action selection scheme, but other algorithms might use another mechanism (softmax, Gaussian policies, Ornstein-Uhlenbeck, noisy parameters, etc).\n", "\n", "`ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)])` means that we create 10 copies of the Cartpole environment which will be acted upon in parallel using the policy.\n", "\n", "Let's collect some data with the collector. We can either collect a fixed number of steps (over the parallel workers) or episodes. Let's start with 10 steps:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "m6-9_loYGbb3", "outputId": "89b2c0b5-6846-4d66-cf64-d14c9850daad" }, "outputs": [ { "data": { "text/plain": [ "CollectStats(n_collected_episodes=0, n_collected_steps=10, collect_time=0.0013911724090576172, collect_speed=7188.181662382177, returns=array([], dtype=float64), returns_stat=None, lens=array([], dtype=int64), lens_stat=None)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "collector.reset()\n", "collector.collect(n_step=10)" ] }, { "cell_type": "markdown", "metadata": { "id": "PB-jgu9nGbb3" }, "source": [ "That's weird, we apparently did not receive any reward. Let's try to collect more steps." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "GOXCcL0EGbb3", "outputId": "4b8e5933-a44e-487f-f412-c23979478d3b" }, "outputs": [ { "data": { "text/plain": [ "CollectStats(n_collected_episodes=97, n_collected_steps=1000, collect_time=0.04027390480041504, collect_speed=24829.973774723094, returns=array([ 8., 9., 9., 10., 10., 10., 10., 11., 11., 12., 10., 8., 10.,\n", " 9., 9., 11., 10., 12., 9., 13., 10., 9., 9., 10., 10., 10.,\n", " 12., 10., 11., 9., 9., 8., 9., 9., 10., 11., 9., 10., 13.,\n", " 12., 8., 8., 9., 10., 9., 9., 8., 11., 12., 10., 13., 9.,\n", " 10., 10., 9., 11., 14., 10., 9., 14., 11., 9., 8., 10., 9.,\n", " 12., 9., 9., 10., 10., 10., 9., 9., 12., 9., 11., 11., 9.,\n", " 10., 9., 8., 10., 10., 10., 10., 10., 8., 10., 8., 10., 8.,\n", " 10., 12., 9., 10., 11., 10.]), returns_stat=SequenceSummaryStats(mean=9.938144329896907, std=1.3379044469115828, max=14.0, min=8.0), lens=array([ 8, 9, 9, 10, 10, 10, 10, 11, 11, 12, 10, 8, 10, 9, 9, 11, 10,\n", " 12, 9, 13, 10, 9, 9, 10, 10, 10, 12, 10, 11, 9, 9, 8, 9, 9,\n", " 10, 11, 9, 10, 13, 12, 8, 8, 9, 10, 9, 9, 8, 11, 12, 10, 13,\n", " 9, 10, 10, 9, 11, 14, 10, 9, 14, 11, 9, 8, 10, 9, 12, 9, 9,\n", " 10, 10, 10, 9, 9, 12, 9, 11, 11, 9, 10, 9, 8, 10, 10, 10, 10,\n", " 10, 8, 10, 8, 10, 8, 10, 12, 9, 10, 11, 10]), lens_stat=SequenceSummaryStats(mean=9.938144329896907, std=1.3379044469115828, max=14.0, min=8.0))" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "collector.collect(n_step=1000)" ] }, { "cell_type": "markdown", "metadata": { "id": "0tdvK4eOGbb4" }, "source": [ "Alright, returns are only reported at the end of an episode. With 1000 steps (in parallel over 10 workers, i.e. each of them did 100 steps), we collected around 100 episodes of length 9 or 10, i.e. the cartpole falls right away, as expected with a random policy.\n", "\n", "Can we collect complete episodes? Yes:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "iKwp_ckCGbb4", "outputId": "cc7f69a5-37f2-40eb-a475-cd88e6bb04fb" }, "outputs": [ { "data": { "text/plain": [ "CollectStats(n_collected_episodes=10, n_collected_steps=107, collect_time=0.005922079086303711, collect_speed=18067.978904142677, returns=array([ 9., 10., 10., 10., 10., 10., 11., 11., 12., 14.]), returns_stat=SequenceSummaryStats(mean=10.7, std=1.345362404707371, max=14.0, min=9.0), lens=array([ 9, 10, 10, 10, 10, 10, 11, 11, 12, 14]), lens_stat=SequenceSummaryStats(mean=10.7, std=1.345362404707371, max=14.0, min=9.0))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "collector.reset()\n", "collector.collect(n_episode=10)" ] }, { "cell_type": "markdown", "metadata": { "id": "FJtOHCq8Gbb4" }, "source": [ "\n", "But where is the data, i.e. the collected transitions? Nowhere, because we forgot to create a buffer to store them. Let's fix that mistake." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7eR-wH8fGbb4", "outputId": "fd1a2220-16f9-4dc4-e826-cd5d68701a23" }, "outputs": [], "source": [ "collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " buffer=ts.data.VectorReplayBuffer(1000, 10),\n", " exploration_noise=True,\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "j4ClkHQOGbb4" }, "source": [ "We preallocate an ERM of max 1000 transitions for each of the 10 workers. One could use a single replay buffer 10 times bigger, but tianshou requires it . Let's collect some episodes and look at the data stored in the first buffer. \n", "\n", "Notice that the collector must be reset before collecting complete episodes. This makes sure that the environments are initialized correctly. " ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "K1LqeZxOGbb4", "outputId": "9effb81f-65ce-4c62-ca1b-621a94b5ea1e" }, "outputs": [ { "data": { "text/plain": [ "ReplayBuffer(\n", " terminated: array([False, False, False, False, False, False, False, False, True,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False]),\n", " act: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),\n", " obs: array([[ 4.1719373e-02, -1.8188158e-02, 3.1984810e-02, -5.8095651e-03],\n", " [ 4.1355610e-02, -2.1375386e-01, 3.1868618e-02, 2.9679090e-01],\n", " [ 3.7080534e-02, -4.0931529e-01, 3.7804436e-02, 5.9935188e-01],\n", " [ 2.8894227e-02, -6.0494518e-01, 4.9791474e-02, 9.0369892e-01],\n", " [ 1.6795322e-02, -8.0070490e-01, 6.7865454e-02, 1.2116072e+00],\n", " [ 7.8122411e-04, -9.9663413e-01, 9.2097595e-02, 1.5247617e+00],\n", " [-1.9151459e-02, -1.1927395e+00, 1.2259283e-01, 1.8447114e+00],\n", " [-4.3006249e-02, -1.3889813e+00, 1.5948705e-01, 2.1728170e+00],\n", " [-7.0785873e-02, -1.5852582e+00, 2.0294340e-01, 2.5101867e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00],\n", " [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00]],\n", " dtype=float32),\n", " policy: Batch(),\n", " truncated: array([False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False]),\n", " info: Batch(\n", " env_id: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),\n", " ),\n", " rew: array([1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.,\n", " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]),\n", " done: array([False, False, False, False, False, False, False, False, True,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False, False, False, False, False, False, False, False, False,\n", " False]),\n", " obs_next: array([[ 4.13556099e-02, -2.13753864e-01, 3.18686180e-02,\n", " 2.96790898e-01],\n", " [ 3.70805338e-02, -4.09315288e-01, 3.78044359e-02,\n", " 5.99351883e-01],\n", " [ 2.88942270e-02, -6.04945183e-01, 4.97914739e-02,\n", " 9.03698921e-01],\n", " [ 1.67953223e-02, -8.00704896e-01, 6.78654537e-02,\n", " 1.21160722e+00],\n", " [ 7.81224109e-04, -9.96634126e-01, 9.20975953e-02,\n", " 1.52476168e+00],\n", " [-1.91514585e-02, -1.19273949e+00, 1.22592829e-01,\n", " 1.84471142e+00],\n", " [-4.30062488e-02, -1.38898134e+00, 1.59487054e-01,\n", " 2.17281699e+00],\n", " [-7.07858726e-02, -1.58525825e+00, 2.02943400e-01,\n", " 2.51018667e+00],\n", " [-1.02491036e-01, -1.78138947e+00, 2.53147125e-01,\n", " 2.85760236e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", " 0.00000000e+00]], dtype=float32),\n", ")" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "collector.reset()\n", "collector.collect(n_episode=10)\n", "collector.buffer.buffers[0]" ] }, { "cell_type": "markdown", "metadata": { "id": "F_umOZ01Gbb4" }, "source": [ "We see that each element of the transitions (s, a, r, s', done, terminated) is saved in a preallocated array of 1000 entries. The first replay buffer has only saved one short episode, so most of the data is zero.\n", "\n", "Sampling a minibatch of transitions is easy:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "fN5xWap-Gbb4", "outputId": "e7e1fa12-f9d5-4c5b-e527-8f9d1aa00840" }, "outputs": [ { "data": { "text/plain": [ "(Batch(\n", " obs: array([[ 0.02889423, -0.6049452 , 0.04979147, 0.9036989 ],\n", " [ 0.02430101, 0.03974571, 0.01062924, -0.03146407],\n", " [-0.16763754, -1.8004676 , 0.2012587 , 2.7397592 ],\n", " [-0.08759376, -1.3427719 , 0.07030181, 1.9648204 ],\n", " [-0.17991085, -1.930467 , 0.20722213, 2.9385881 ],\n", " [-0.05950754, -0.938497 , 0.05038013, 1.4974161 ],\n", " [-0.04880736, 0.1649252 , 0.01317924, -0.26343435],\n", " [-0.05576029, -0.4212988 , 0.02264059, 0.6336633 ],\n", " [-0.11357517, -1.7669356 , 0.18923528, 2.7024126 ],\n", " [-0.0114096 , -0.9834897 , 0.03757063, 1.4308813 ]],\n", " dtype=float32),\n", " act: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),\n", " rew: array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),\n", " terminated: array([False, False, True, False, True, False, False, False, True,\n", " False]),\n", " truncated: array([False, False, False, False, False, False, False, False, False,\n", " False]),\n", " done: array([False, False, True, False, True, False, False, False, True,\n", " False]),\n", " obs_next: array([[ 0.01679532, -0.8007049 , 0.06786545, 1.2116072 ],\n", " [ 0.02509592, -0.15552704, 0.00999996, 0.26455346],\n", " [-0.20364688, -1.9963619 , 0.2560539 , 3.086441 ],\n", " [-0.1144492 , -1.5385635 , 0.10959822, 2.278434 ],\n", " [-0.2185202 , -2.1261373 , 0.2659939 , 3.2863023 ],\n", " [-0.07827748, -1.1341938 , 0.08032845, 1.8053944 ],\n", " [-0.04550886, -0.03038236, 0.00791055, 0.03337612],\n", " [-0.06418626, -0.61672914, 0.03531386, 0.9333894 ],\n", " [-0.14891388, -1.9628596 , 0.24328354, 3.046356 ],\n", " [-0.03107939, -1.1790547 , 0.06618825, 1.735065 ]],\n", " dtype=float32),\n", " info: Batch(\n", " env_id: array([0, 1, 2, 5, 5, 7, 8, 8, 9, 9]),\n", " ),\n", " policy: Batch(),\n", " ),\n", " array([ 3, 100, 209, 507, 510, 705, 801, 806, 909, 905]))" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "collector.buffer.sample(10)" ] }, { "cell_type": "markdown", "metadata": { "id": "YjmeFv6XNnew" }, "source": [ "Anyway, we will use a method that automatically sample the replay buffer, but it is nice to have such a low-level control over the data." ] }, { "cell_type": "markdown", "metadata": { "id": "kluQClBKGbb4" }, "source": [ "### Interaction loop\n", "\n", "We do not need to sample the buffer in the interaction loop, because `policy.update()` takes the buffer and a batch size as input. The following code implements DQN on Cartpole, with a rather poor choice of hyperparameters (do not expect a nice a stable performance). The main interaction loop consists of:\n", "\n", "1. `collector.collect()`: Collect 100 samples using the 10 workers and store them in the ERM.\n", "2. `policy.update()`: Sample `repeat=10` minibatches of 64 transitions from the buffer and learn from them.\n", "3. `test_collector.collect()`: Test the performance by running 10 episodes without exploration.\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 467 }, "id": "CL2ke1_mGbb5", "outputId": "db473df1-ebf9-4bb7-885c-931ba72b0966" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "reward : 144.2: 100%|██████████| 1000/1000 [00:51<00:00, 19.25it/s]\n" ] }, { "data": { "image/png": "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D38AAAwZMgRbtmzBs88+iylTpqTYuszhP//5D1577TXMnz8fp512GjZs2IA777wTVVVVvM4nMQxjJYCOHTvCYrEEVKwcOnQIFRUVKbIqPZkxYwYWLVqEZcuWoUuXLtLyiooKtLe3o66uTrG9/BpXVFRofgbiOuINUx0+fBhnnHEGrFYrrFYrli9fjqeffhpWqxXl5eW8znGisrISp556qmJZ//79sXfvXgD+axXs/0ZFRQUOHz6sWO9yuXD8+HFeax+//vWv8Zvf/AbXXHMNBg4ciOuvvx4zZ87E3LlzAfA6J4p4XddE/T+h2EkANpsNQ4cOxdKlS6VlHo8HS5cuxYgRI1JoWfogCAJmzJiBt956C5988kmAW3Po0KHIyspSXOPt27dj79690jUeMWIENm/erPjjWrJkCQoLCwNuOicrY8eOxebNm7FhwwbpZ9iwYZg8ebL0nNc5PowcOTKgfcJ3332Hbt26AQB69OiBiooKxbVuaGjA6tWrFde6rq4O69atk7b55JNP4PF4MHz48CSchfFpaWmB2ay8tVksFng8HgC8zokiXtd1xIgRWLFiBZxOp7TNkiVL0Ldv36hDWABYep4oFixYINjtduGll14Stm3bJkybNk0oLi5WVKwQfW677TahqKhI+PTTT4Wamhrpp6WlRdrm1ltvFbp27Sp88sknwtq1a4URI0YII0aMkNaLJdEXXnihsGHDBmHx4sVCp06dWBIdAnk1liDwOseLr776SrBarcIjjzwifP/998Jrr70m5ObmCq+++qq0zaOPPioUFxcLb7/9trBp0ybh8ssv1yzdHTJkiLB69Wrh888/F/r06XPSl0TLmTJlitC5c2ep9PzNN98UOnbsKNx9993SNrzO0dHY2Ch8/fXXwtdffy0AEJ544gnh66+/Fvbs2SMIQnyua11dnVBeXi5cf/31wpYtW4QFCxYIubm5LD03Mn/961+Frl27CjabTTjrrLOEVatWpdqktAGA5s+LL74obdPa2ir84he/EEpKSoTc3FzhyiuvFGpqahT72b17tzBx4kQhJydH6Nixo3DXXXcJTqczyWeTXqjFDq9z/Hj33XeFAQMGCHa7XejXr5/w3HPPKdZ7PB7h/vvvF8rLywW73S6MHTtW2L59u2KbY8eOCddee62Qn58vFBYWCjfeeKPQ2NiYzNMwNA0NDcIdd9whdO3aVcjOzhZ69uwp3HvvvYpSZl7n6Fi2bJnm/+UpU6YIghC/67px40Zh1KhRgt1uFzp37iw8+uijMdtuEgRZW0lCCCGEkAyDOTuEEEIIyWgodgghhBCS0VDsEEIIISSjodghhBBCSEZDsUMIIYSQjIZihxBCCCEZDcUOIYQQQjIaih1CCCGEZDQUO4QQAsBkMmHhwoWpNoMQkgAodgghKeeGG26AyWQK+JkwYUKqTSOEZADWVBtACCEAMGHCBLz44ouKZXa7PUXWEEIyCXp2CCGGwG63o6KiQvFTUlICwBtimjdvHiZOnIicnBz07NkT//3vfxXv37x5My644ALk5OSgQ4cOmDZtGpqamhTbvPDCCzjttNNgt9tRWVmJGTNmKNYfPXoUV155JXJzc9GnTx+888470roTJ05g8uTJ6NSpE3JyctCnT58AcUYIMSYUO4SQtOD+++/HpEmTsHHjRkyePBnXXHMNvvnmGwBAc3Mzxo8fj5KSEqxZswZvvPEGPv74Y4WYmTdvHqZPn45p06Zh8+bNeOedd9C7d2/FMR566CH85Cc/waZNm3DRRRdh8uTJOH78uHT8bdu24YMPPsA333yDefPmoWPHjsm7AISQ6Il5bjohhMTIlClTBIvFIuTl5Sl+HnnkEUEQBAGAcOuttyreM3z4cOG2224TBEEQnnvuOaGkpERoamqS1r/33nuC2WwWamtrBUEQhKqqKuHee+/VtQGAcN9990mvm5qaBADCBx98IAiCIFx66aXCjTfeGJ8TJoQkFebsEEIMwfnnn4958+YplpWWlkrPR4wYoVg3YsQIbNiwAQDwzTffYPDgwcjLy5PWjxw5Eh6PB9u3b4fJZMLBgwcxduzYoDYMGjRIep6Xl4fCwkIcPnwYAHDbbbdh0qRJWL9+PS688EJcccUVOOecc6I6V0JIcqHYIYQYgry8vICwUrzIyckJa7usrCzFa5PJBI/HAwCYOHEi9uzZg/fffx9LlizB2LFjMX36dPz5z3+Ou72EkPjCnB1CSFqwatWqgNf9+/cHAPTv3x8bN25Ec3OztP6LL76A2WxG3759UVBQgO7du2Pp0qUx2dCpUydMmTIFr776Kp566ik899xzMe2PEJIc6NkhhBgCh8OB2tpaxTKr1SolAb/xxhsYNmwYRo0ahddeew1fffUVnn/+eQDA5MmT8cADD2DKlCl48MEHceTIEdx+++24/vrrUV5eDgB48MEHceutt6KsrAwTJ05EY2MjvvjiC9x+++1h2TdnzhwMHToUp512GhwOBxYtWiSJLUKIsaHYIYQYgsWLF6OyslKxrG/fvvj2228BeCulFixYgF/84heorKzE66+/jlNPPRUAkJubiw8//BB33HEHzjzzTOTm5mLSpEl44oknpH1NmTIFbW1tePLJJ/GrX/0KHTt2xNVXXx22fTabDbNnz8bu3buRk5ODc889FwsWLIjDmRNCEo1JEAQh1UYQQkgwTCYT3nrrLVxxxRWpNoUQkoYwZ4cQQgghGQ3FDiGEEEIyGubsEEIMD6PthJBYoGeHEEIIIRkNxQ4hhBBCMhqKHUIIIYRkNBQ7hBBCCMloKHYIIYQQktFQ7BBCCCEko6HYIYQQQkhGQ7FDCCGEkIzm/wOb/hRg6Ba0MgAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Model\n", "net = ts.utils.net.common.Net(\n", " env.observation_space.shape,\n", " env.action_space.n,\n", " hidden_sizes=[64, 64],\n", " device=device,\n", ").to(device)\n", "\n", "optim = torch.optim.Adam(net.parameters(), lr=0.001)\n", "\n", "# Policy\n", "policy = ts.policy.DQNPolicy(\n", " model=net, # value network\n", " optim=optim, # optimizer\n", " discount_factor=0.99, # gamma\n", " estimation_step=1, # n-step returns\n", " is_double=False, # double Q-learning\n", " target_update_freq=120, # how often to update the target network\n", " action_space=env.action_space, # action space\n", ")\n", "policy.set_eps(0.1) # epsilon-greedy action selection\n", "\n", "# Collector for training\n", "collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " buffer=ts.data.VectorReplayBuffer(20000, 10),\n", " exploration_noise=True\n", ")\n", "\n", "# Collector for testing (without exploration). No need for a buffer\n", "test_collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " exploration_noise=False\n", ")\n", "\n", "# Pre-fill the training buffer with random transitions\n", "collector.reset()\n", "collector.collect(n_step=1000, random=True)\n", "\n", "# Interaction\n", "returns = []\n", "for iteration in (pbar := tqdm.tqdm(range(1000))):\n", "\n", " # Training mode. Important!\n", " policy.train()\n", " policy.is_within_training_step = True\n", "\n", " # Collect transitions\n", " result = collector.collect(n_step=100)\n", "\n", " # Train DQN network on 10 minibatches\n", " policy.update(\n", " buffer=collector.buffer,\n", " sample_size=0, # use the whole buffer\n", " batch_size=64,\n", " repeat=10,\n", " )\n", "\n", " # Test 10 episodes\n", " policy.eval()\n", " test_collector.reset()\n", " result = test_collector.collect(n_episode=10)\n", " mean_reward = result.returns.mean()\n", " pbar.set_description(f\"reward : {mean_reward}\")\n", " returns.append(mean_reward)\n", "\n", "plt.figure()\n", "plt.plot(np.array(returns))\n", "plt.xlabel(\"Epochs\")\n", "plt.ylabel(\"Returns\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 457 }, "id": "f0e-7eIFGbb5", "outputId": "7a76477b-adc1-4937-a6b6-3a6ea1ebb5eb" }, "outputs": [], "source": [ "# Evaluation mode\n", "policy.eval()\n", "\n", "# Create a recordable environment\n", "env = gym.make('CartPole-v0', render_mode=\"rgb_array_list\")\n", "recorder = GymRecorder(env)\n", "\n", "# Sample the initial state\n", "state, info = env.reset()\n", "\n", "# One episode:\n", "done = False\n", "return_episode = 0\n", "while not done:\n", "\n", " # Select an action from the learned policy\n", " action = policy.forward(ts.data.Batch(obs=[state], info=None)).act[0]\n", "\n", " # Sample a single transition\n", " next_state, reward, terminal, truncated, info = env.step(action)\n", "\n", " # End of the episode\n", " done = terminal or truncated\n", "\n", " # Update undiscounted return\n", " return_episode += reward\n", "\n", " # Go in the next state\n", " state = next_state\n", "\n", "print(\"Return:\", return_episode)\n", "\n", "recorder.record(env.render())\n", "video = \"videos/cartpole-dqn.gif\"\n", "recorder.make_video(video)\n", "ipython_display(video)" ] }, { "cell_type": "markdown", "metadata": { "id": "26LgTNCkGbb5" }, "source": [ "**Q:** Understand and run the code. Experiment with the hyperparameters and compare them to the previous exercise. In particular, what is `estimation_step=1` in the constructor of the DQN policy? What is its influence?\n", "\n", "**Q:** Implement scheduling of the exploration parameter with the right hyperparameters.\n", "\n", "Note: the goal is not to redo the last exercise on DQN, just to understand how the interaction loop in tianshou works." ] }, { "cell_type": "markdown", "metadata": { "id": "mNSbTy4aGbb5" }, "source": [ "**A:** The main difference is that much more data is collected by the 10 workers before the DQN is updated (10 times in a row instead of 1). Distributed learning can also be used in DQN-like algorithms ans speed up learning. Collecting 1000 transitions instead of 100 at each iteration is even better.\n", "\n", "`estimation_step` allows to use n-step returns instead of the vanilla 1-step return r + gamma * V(s'). Choosing a value of `n=3` (and double Q-learning) stabilizes learning a lot.\n", "\n", "There are many ways to implement exploration scheduling. Here is one that works OK." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "l6cghgCCGbb5", "outputId": "b5affccf-c018-4c7a-87e4-9a87a89202ea" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "reward : 139.5: 100%|██████████| 1000/1000 [01:59<00:00, 8.40it/s]\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Model\n", "net = ts.utils.net.common.Net(\n", " env.observation_space.shape,\n", " env.action_space.n,\n", " hidden_sizes=[128, 128],\n", " device=device,\n", ").to(device)\n", "\n", "optim = torch.optim.Adam(net.parameters(), lr=0.001)\n", "\n", "# Policy\n", "policy = ts.policy.DQNPolicy(\n", " model=net, # value network\n", " optim=optim, # optimizer\n", " discount_factor=0.99, # gamma\n", " estimation_step=3, # n-step returns\n", " is_double=True, # double Q-learning\n", " target_update_freq=120, # how often to update the target network\n", " action_space=env.action_space, # action space\n", ")\n", "policy.set_eps(0.1) # epsilon-greedy action selection\n", "\n", "# Collector for training\n", "collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " buffer=ts.data.VectorReplayBuffer(20000, 10),\n", " exploration_noise=True\n", ")\n", "# Collector for testing (without exploration). No need for a buffer\n", "test_collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " exploration_noise=False\n", ")\n", "\n", "# Pre-fill the training buffer with random transitions\n", "collector.reset()\n", "collector.collect(n_step=1000, random=True,)\n", "\n", "# Interaction\n", "returns = []\n", "for iteration in (pbar := tqdm.tqdm(range(1000))):\n", "\n", " # Training mode\n", " policy.train()\n", " policy.is_within_training_step = True\n", "\n", " # Exploration schedule\n", " if iteration <= 100:\n", " eps = 0.5\n", " elif iteration <= 900:\n", " eps = 0.5 - (iteration - 100) / (900 - 100) * (0.5 - 0.05)\n", " else:\n", " eps = 0.05\n", " policy.set_eps(eps)\n", "\n", " # Collect transitions\n", " result = collector.collect(n_step=1000)\n", "\n", " # Train DQN network on 10 minibatches\n", " policy.update(\n", " buffer=collector.buffer,\n", " sample_size=0, # use the whole buffer\n", " batch_size=128,\n", " repeat=10,\n", " )\n", "\n", " # Test 10 episodes\n", " policy.eval()\n", " test_collector.reset()\n", " result = test_collector.collect(n_episode=10)\n", " mean_reward = result.returns.mean()\n", " pbar.set_description(f\"reward : {mean_reward}\")\n", " returns.append(mean_reward)\n", "\n", "plt.figure()\n", "plt.plot(np.array(returns))\n", "plt.xlabel(\"Epochs\")\n", "plt.ylabel(\"Returns\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "00Vl2AdvM3JC" }, "outputs": [], "source": [ "# Evaluation mode\n", "policy.eval()\n", "\n", "# Create a recordable environment\n", "env = gym.make('CartPole-v0', render_mode=\"rgb_array_list\")\n", "recorder = GymRecorder(env)\n", "\n", "# Sample the initial state\n", "state, info = env.reset()\n", "\n", "# One episode:\n", "done = False\n", "return_episode = 0\n", "while not done:\n", "\n", " # Select an action from the learned policy\n", " action = policy.forward(ts.data.Batch(obs=[state], info=None)).act[0]\n", "\n", " # Sample a single transition\n", " next_state, reward, terminal, truncated, info = env.step(action)\n", "\n", " # End of the episode\n", " done = terminal or truncated\n", "\n", " # Update undiscounted return\n", " return_episode += reward\n", "\n", " # Go in the next state\n", " state = next_state\n", "\n", "print(\"Return:\", return_episode)\n", "\n", "recorder.record(env.render())\n", "video = \"videos/cartpole-dqn2.gif\"\n", "recorder.make_video(video)\n", "ipython_display(video)" ] }, { "cell_type": "markdown", "metadata": { "id": "22o7gPpjGbb5" }, "source": [ "## PPO\n", "\n", "Now that DQN works on Cartpole, let's use PPO and compare its performance to DQN.\n", "\n", "You will need to use the PPO policy, obviously:\n", "\n", "```python\n", "policy = ts.policy.PPOPolicy(\n", " actor=actor,\n", " critic=critic,\n", " optim=optim,\n", " dist_fn=torch.distributions.Categorical,\n", " action_space=env.action_space,\n", " discount_factor=0.99,\n", " max_grad_norm=0.5,\n", " eps_clip=0.2,\n", " gae_lambda=0.95,\n", " deterministic_eval=True,\n", " action_scaling=False,\n", ")\n", "```\n", "\n", "It has many more hyperparameters, which can be let at their default value (or not, depending on the time you have). Check the doc for their meaning. The important thing is that you now need an actor and a critic, not a single network.\n", "\n", "One way to do it is to use the actor/critic specifications provided by tianshou:\n", "\n", "```python\n", "features = ts.utils.net.common.Net(\n", " state_shape=env.observation_space.shape,\n", " hidden_sizes=[64, 64],\n", " device=device)\n", "\n", "actor = ts.utils.net.discrete.Actor(\n", " preprocess_net=features,\n", " action_shape=env.action_space.n,\n", " device=device).to(device)\n", "\n", "critic = ts.utils.net.discrete.Critic(\n", " preprocess_net=features,\n", " device=device).to(device)\n", "\n", "actor_critic = ts.utils.net.common.ActorCritic(actor=actor, critic=critic)\n", "\n", "optim = torch.optim.Adam(actor_critic.parameters(), lr=0.001)\n", "```\n", "\n", "``features`` is the shared feature extractor between the actor and the critic. ``actor`` is the policy head (one neuron per discrete action), ``critic`` is a single output neuron for the value V(s). ``actor_critic`` is the combined two-headed network.\n", "\n", "When defining the PPO policy, `dist_fn=torch.distributions.Categorical` specifies how exploration is performed, here a softmax over the two actions left and right.\n", "\n", "**Q:** Implement PPO on Cartpole. You will need to find the right hyperparameters for the task.\n", "\n", "Remember that learning is **on-policy**, so the transition buffer must be emptied after training the network. Your interaction loop must therefore look like this:\n", "\n", "```python\n", "for iteration in range(N):\n", "\n", " # Collect enough on-policy steps\n", " result = collector.collect(...)\n", "\n", " # Update the PP0 network by learning the on-policy buffer\n", " policy.update(...)\n", "\n", " # Empty the buffer as we are on-policy\n", " collector.reset_buffer(keep_statistics=False)\n", "```\n", "\n", "Do not hesitate to collect many on-policy steps before training the network." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "id": "VIlFUbUvGbb5" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "reward : 200.0: 100%|██████████| 100/100 [00:39<00:00, 2.54it/s]\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAGwCAYAAABPSaTdAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/GU6VOAAAACXBIWXMAAA9hAAAPYQGoP6dpAABD10lEQVR4nO3deXyU5b3///dMJjNJIAsBsklYXEFZiqAx4oJChejBDe1Pi37BjUqDVThtNUelamvD0brUHorHHsXaQnmUVtFSlyIqiAIKGBGrKIiAQkDBZJJAJsvcvz+SuZMhC5PJrHdez8djHo/Mfd+ZueYm5Prk+nyu67IZhmEIAADAouzRbgAAAEA4EewAAABLI9gBAACWRrADAAAsjWAHAABYGsEOAACwNIIdAABgaY5oNyAWeL1e7d27V6mpqbLZbNFuDgAACIBhGKqqqlJeXp7s9o7Hbwh2JO3du1f5+fnRbgYAAAjCnj17NGDAgA7PE+xISk1NldR0s9LS0qLcGgAAEAi32638/HyzH+8IwY5kpq7S0tIIdgAAiDPHKkGhQBkAAFgawQ4AALA0gh0AAGBpBDsAAMDSCHYAAIClEewAAABLI9gBAACWRrADAAAsjWAHAABYGsEOAACwtKgGO6WlpTrjjDOUmpqqrKwsXX755dq2bZvfNbW1tSouLlbfvn3Vu3dvTZ06Vfv37/e7Zvfu3brkkkuUkpKirKws/exnP1NDQ0MkPwoAAIhRUQ12Vq9ereLiYq1fv14rV65UfX29LrroItXU1JjXzJkzR//4xz+0bNkyrV69Wnv37tWVV15pnm9sbNQll1yiuro6vfvuu/rjH/+oZ599VvPmzYvGRwIAADHGZhiGEe1G+HzzzTfKysrS6tWrdd5556myslL9+/fXkiVLdNVVV0mSPv30Uw0bNkzr1q3TWWedpVdeeUX/8R//ob179yo7O1uS9OSTT+rOO+/UN998I6fTecz3dbvdSk9PV2VlJRuBhpCnoVHfVHmi3QwAUZCVmiSno+O/p71eQ3srj0SwRYi27LQkJSaEdowl0P47pnY9r6yslCRlZmZKkjZt2qT6+npNnDjRvGbo0KEaOHCgGeysW7dOI0aMMAMdSZo0aZJmzZqljz/+WKNHj27zPh6PRx5PSyfsdrvD9ZF6rLoGryY+ulp7DvHLDOiJBvdN0cq553fYuc149n2t+eybCLcK0fTGf56v4/v3jsp7x0yw4/V6dccdd2jcuHEaPny4JKm8vFxOp1MZGRl+12ZnZ6u8vNy8pnWg4zvvO9ee0tJS3X///SH+BD3LAXetUpMSlexMaPf8lwdrzEDH1clfdwCsx9Pg1ZcHD+ur745oSL9ebc43NHr1zvZvJUlOh122SDcQUWGzRe9fOmaCneLiYm3dulVr164N+3uVlJRo7ty55nO32638/Pywv69V7HfX6tyH3tTwvDQ9/+Nx7V6z++BhSdLw49K04rZzI9k8AFF20WOr9dn+au0+dLjdYGdfZa0avYacDrs+fWCy7HbCHYRXTPzJPXv2bK1YsUJvvvmmBgwYYB7PyclRXV2dKioq/K7fv3+/cnJyzGuOnp3le+675mgul0tpaWl+DwRu067vVNfg1YdfVaq+0dvuNbsPNQU7AzNTItk0ADEgv0/T//s9zb8HjuY7PiAjmUAHERHVYMcwDM2ePVsvvPCC3njjDQ0ZMsTv/JgxY5SYmKhVq1aZx7Zt26bdu3ersLBQklRYWKiPPvpIBw4cMK9ZuXKl0tLSdOqpp0bmg/Qwn+5rqnFq9Br6+rv2a3J8wU4+wQ7Q4/j+3+/5roNgp/n4AH4/IEKimsYqLi7WkiVL9OKLLyo1NdWssUlPT1dycrLS09N10003ae7cucrMzFRaWppuu+02FRYW6qyzzpIkXXTRRTr11FN1/fXX66GHHlJ5ebnuueceFRcXy+VyRfPjWdYn5VXm118erNHgdoap9zCyA/RYA/okS5K+6mCCgq+eL7/5OiDcohrsLFy4UJI0fvx4v+OLFi3SjBkzJEmPPfaY7Ha7pk6dKo/Ho0mTJun3v/+9eW1CQoJWrFihWbNmqbCwUL169dL06dP1wAMPROpj9DiflrfMXtt1sP2/3EhjAT1XoCM7jPwiUqIa7ASyxE9SUpIWLFigBQsWdHjNoEGD9PLLL4eyaehAVW2933TyLw/WtLnGMAyCHaAHC7Rmx3cdEG4xUaCM+PHZ/iq/5+2N7HxT5ZGnwSu7TcrLYJga6GnyM5v+3393uF7VnrZb9+xprvXzXQeEG8EOuuSTfU3BTq/m9XXaG9nxjerkpieHfLVMALEvNSlRGSmJktqO7tTWt6yszsgOIoWeCF3iq9e5YGiWpKZfZI1e/3SkLx9PCgvouTpKZX3V/Puht8thBkRAuBHsoEu2Nc/EuuCULDkT7KpvNLS3wn/Gxe6DTc8JdoCey5ei2nPU8hS+mr8BfZKjuqIuehaCHQTMMAx92pzGOu24NPOX2dF1O2Zxcl+CHaCn6mhkh5lYiAaCHQTs64ojqvI0KDHBpuP79dbgvk3r6xxdt7OHBQWBHs+3YOBXR00/ZyYWooFgBwHzjeqc0L+3nA67BjUHO7uOCnaYdg7At2DgnkPtp7GYiYVIIthBwHzFycNym/YSG9yvKZj5slUaq7a+UeXuWkkEO0BP5vv/v/vQYb811ZjAgGgg2EHAfNtEDM1JlaR2R3a+ai5G7O1yqA8zLYAe67g+ybLZpCP1jTpYU2ceJ82NaCDYQcB8G4AO9Y3s9G35y83bPP289S8yZloAPZfLkaDs1CRJLb8XKo/Uy13btMjgAPbFQgQR7CAgtfWN2vlt0wiOb2TnuIxkOew21dZ7daB5kbCWeh1+kQE93dHTz31BT7/eTqU4o7pbEXoYgh0E5PP91fIaUp+URGWlNu0m70iwm3+d+WZkUZwMwOfo6ee+mVkDmImFCCPYQUB8xclDc9L80lNH1+0Q7ADwOXr6ectMLH4/ILIIdhCQT33Fybmpfsd9dTu+GVkUHwLwOXr6ubmgIPU6iDCCHQTEnHaek+Z3vPXIjmEYjOwAMPn+6NnzHX8MIboIdnBMhmGYu523GdnxrbXz7WEdrKnT4bpG2WxN004B9Gy+oGZvxRE1eg2zUJnVkxFpBDs4pm+qPTpUUye7TTopyz/YaT2y49sjKzctSS5HQsTbCSC25KQlKTHBpvpGQ/sqj5i1O6yejEgj2MEx+baJGNyvl5Kd/kHMgD7JstukmrpGfbD7O0kMUQNokmC3KS+jKbAp21Oh2nqv7DaZx4BIIdjBMXVUryM1LRzm+8X19uffSqJeB0ALX8rqne0HJUm56clKTKDrQWTxE4dj8o3s+BYTPJpv9/MNO5t+mRHsAPDxpaze3dH0xxArJyMaCHZwTL6ZFEP692r3/KDm6ee19V5J0sC+BDsAmvgWEPTV9JHmRjQQ7OCYqj2NkqTUpPY39vSN7PjwywyAz9G/D5iJhWgg2MEx1XiaNu7r7Wp/htWgo0ZySGMB8Dl6AUFmYiEaCHZwTL5gp5er/Y37BvdrGdlJcSaoby9nRNoFIPYd/ccPfwwhGgh2cEzVvmCng12KW//yGpiZ4rd3FoCeLbOXUymtlqwgzY1oINhBpxoavfI0NBUe9+5gZCcpMUG56UmS+EUGwJ/NZjPrdJwOu/r3dkW5ReiJCHbQqZrm4mSp4zSW1FK3wxA1gKP56nQG9EmW3c7ILyKPYAedqq5rSmE5E+xyOjr+cflefh9J0sgB6RFpF4D44Zt+zkwsRAvBDjrVUpzc+V5Xc79/sv75k3M0ZWReJJoFII6cPqjpj6HRAzOi2xD0WB3nJQC1Kk7uJIUlNeXiT8tjVAdAW1NG5mrUgHRGdhA1BDvoVMsaO/yoAAiOzWbToL7tr8AORAJpLHTKF+ykODtPYwEAEKsIdtAp31YRx0pjAQAQqwh20KnDdaSxAADxjWAHnQq0QBkAgFhFsINOUaAMAIh3BDvoVI1Zs0OBMgAgPkU12FmzZo2mTJmivLw82Ww2LV++3O+8zWZr9/Hwww+b1wwePLjN+fnz50f4k1gXaSwAQLyLarBTU1OjUaNGacGCBe2e37dvn9/jmWeekc1m09SpU/2ue+CBB/yuu+222yLR/B6BNBYAIN5FtQcrKipSUVFRh+dzcnL8nr/44ou64IILdPzxx/sdT01NbXNtZzwejzwej/nc7XYH/L09jTmy4yTYAQDEp7ip2dm/f7/++c9/6qabbmpzbv78+erbt69Gjx6thx9+WA0NDZ2+VmlpqdLT081Hfn5+uJod92pIYwEA4lzc9GB//OMflZqaqiuvvNLv+E9+8hOdfvrpyszM1LvvvquSkhLt27dPjz76aIevVVJSorlz55rP3W43AU8HfAXKpLEAAPEqbnqwZ555RtOmTVNSUpLf8dZBy8iRI+V0OvWjH/1IpaWlcrlc7b6Wy+Xq8Bz8VQe46zkAALEqLtJYb7/9trZt26abb775mNcWFBSooaFBX375Zfgb1gPUsIIyACDOxUWw8/TTT2vMmDEaNWrUMa8tKyuT3W5XVlZWBFpmfdTsAADiXVR7sOrqam3fvt18vnPnTpWVlSkzM1MDBw6U1FRPs2zZMj3yyCNtvn/dunXasGGDLrjgAqWmpmrdunWaM2eOrrvuOvXp0ydin8OqPA2Nqm80JBHsAADiV1R7sI0bN+qCCy4wn/vqb6ZPn65nn31WkrR06VIZhqFrr722zfe7XC4tXbpU9913nzwej4YMGaI5c+b41fEgeL7iZEnq5aRmBwAQn2yGYRjRbkS0ud1upaenq7KyUmlpadFuTszYc+iwzn3oTSUl2vXpLzteDwkAgGgItP+Oi5odREc1qycDACyAYAcd8hUnp7B6MgAgjhHsoEM1db4dzwl2AADxi2AHHWrZBJTiZABA/CLYQYeqWWMHAGABBDvoEAsKAgCsgGAHHTLTWBQoAwDiGMEOOlTtoUAZABD/CHbQIQqUAQBWQLCDDlGzAwCwAoIddIjZWAAAKyDYQYdq6tguAgAQ/wh20CEKlAEAVkCwgw611OxQoAwAiF8EO3Gq8nC9qmrrw/oeNex6DgCwAIKdOORpaNSER1dr8uNvq6HRG7b3oUAZAGAFBDtxaM+hI/q22qOvK47os/3VYXkPwzAY2QEAWALBThzaV3nE/Hrz7u/C8h619V55jaavGdkBAMQzgp04tK+i1vw6XMGOL4UlSSmJFCgDAOIXwU4c2ttqZOeD3RVheQ9fCivFmSC73RaW9wAAIBIIduJQ65Gdnd/W6FBNXcjfw7egICksAEC8I9iJQ61HdiTpgw5SWXP/Wqb/73/XqdFXfNMFNc0LClKcDACIdwQ7cWhfZdPIznEZyZLar9v54ptqPb/5a23YeUhff3ekzfljYUFBAIBVEOzEGcMwtK+iKXi5eESOJGnzroo217328X7z63pv19fiMdfYcTKyAwCIbwQ7ccZd26CauqYU08UjciVJH35V0WZxwVc/Lje/rg9i4UHW2AEAWAXBTpzxrbGTkZKokQMy1Nvl0OG6Rm3bX2Ves7fiiD7cU2E+b2jses0OqycDAKyCYCfO+GZi5aYnK8Fu0/fyMyRJm1tNQf9Xq1EdSaoLamSHHc8BANZAsBNnfDOx8tKTJEmnD8yQJH2wq6VI+dWjgp36hiCCnTpfGosCZQBAfCPYiTPmyE5GU7AzelAfSS0zsg5We/TezkOSmlJdklRPGgsA0IPRk8UZ38hObnrTtPPT85uCnS8PHtbBao9e/2S/vIY0/Lg02WRTxeHKoGZjUaAMALAKRnbijG9kJ695ZCc9JVEn9O8lSSrbU6FXtzalsCadmqPEhKZtHoJKYzGyAwCwCIKdOLPvqJEdSTp9YNPozprPvtE72w9KkiYPz1FiQtM/L2ksAEBPRrATRwzDMFdPzmsd7DTX7fzlvT2qa/Tq+P69dGJW71bBTvCzsShQBgDEO4KdOHKopk6e5pRUdrrLPO4b2fFNMZ98Wo5sNltLGqsbiwqygjIAIN4R7MQR36hOv94uuRwtIy4nZfVWaqt00+ThTdtIkMYCAIBgJ67sbd4Ty1ec7GO32/S95vV28tKTNOK4dElSoqM7aSxmYwEArCGqwc6aNWs0ZcoU5eXlyWazafny5X7nZ8yYIZvN5veYPHmy3zWHDh3StGnTlJaWpoyMDN10002qrq6O4KeIHN/ITm56Uptz553UX5J0+ejjZLM1pa8S7cGlsbxew9x/i5EdAEC8i2pPVlNTo1GjRunGG2/UlVde2e41kydP1qJFi8znLpfL7/y0adO0b98+rVy5UvX19brhhhs0c+ZMLVmyJKxtj4aj19hp7YZxg3VaXprOGJJpHgs2jXW4vtH8mpEdAEC8i2pPVlRUpKKiok6vcblcysnJaffcJ598oldffVXvv/++xo4dK0n63e9+p4svvli/+c1vlJeXF/I2R9PRa+y05kiw6+wT+/kdCzaNdbg5hWW3SUmJZDoBAPEt5nuyt956S1lZWTrllFM0a9YsHTx40Dy3bt06ZWRkmIGOJE2cOFF2u10bNmzo8DU9Ho/cbrffIx60t8ZOZ4JNY1W3monlS4kBABCvYjrYmTx5sp577jmtWrVK//3f/63Vq1erqKhIjY1NaZby8nJlZWX5fY/D4VBmZqbKy8vbe0lJUmlpqdLT081Hfn5+WD9HqOztZGSnPcGmsdjxHABgJTHdm11zzTXm1yNGjNDIkSN1wgkn6K233tKECROCft2SkhLNnTvXfO52u2M+4Gn0Gtrv9hUoBziyE2Qaq2XaOQsKAgDiX0yP7Bzt+OOPV79+/bR9+3ZJUk5Ojg4cOOB3TUNDgw4dOtRhnY/UVAeUlpbm94h131Z71OA1ZLdJWamuY3+DFPQKykw7BwBYSVwFO1999ZUOHjyo3NxcSVJhYaEqKiq0adMm85o33nhDXq9XBQUF0WpmWPjW2MlOS5IjIbB/tmBrdmrqWFAQAGAdUe3NqqurzVEaSdq5c6fKysqUmZmpzMxM3X///Zo6dapycnK0Y8cO/fznP9eJJ56oSZMmSZKGDRumyZMn65ZbbtGTTz6p+vp6zZ49W9dcc431ZmJ1ssZOR1rSWF2r2WH1ZACAlUR1ZGfjxo0aPXq0Ro8eLUmaO3euRo8erXnz5ikhIUFbtmzRpZdeqpNPPlk33XSTxowZo7fffttvrZ3Fixdr6NChmjBhgi6++GKdc845euqpp6L1kcLGN7KTmxFYvY5EGgsAACnKIzvjx4+XYXQ86vDaa68d8zUyMzMtuYDg0Vp2Ow98ZMcZ5Eag1eZsLAqUAQDxL65qdnqyrq6xI8ms7alr6OrUc9JYAADrINiJE11dY0dqSWM1eINMYzkJdgAA8Y9gJ04EM7KTGHQai5EdAIB1EOzEgfpGrw5UeSRJuV0Y2XH6CpSDTGNRoAwAsAKCnTiw310rw2gaqenXK7AFBaVWNTtdno3FdhEAAOsg2IkDvplYOelJstsD35jTl8bqas0O20UAAKyEYCcOmGvsdKFeR+pGGquONBYAwDoIduJAMGvsSMFvBMrUcwCAlRDsxIF9QayeLEmO5pRXV2t2qilQBgBYCMFOHDhYUydJ6tc78OJkqdU6O13YG6vRa6i2vik4SnFSswMAiH8EO3GgqrZppCU1qWsjLc4g0li+eh2JNBYAwBoIduKAL62U1sVgJzGIqee+eh2H3SaXgx8PAED8ozeLA1W19ZKk1KTELn2fr2anSyM7rYqTbbbAp7kDABCrCHbigC+N1dWCYV8aqys1O74dzylOBgBYBcFOHKgOsmanZSNQQ15vYAFPDQsKAgAshmAnxnm9hqrrfMFO19JYvhWUJak+wFWUD9c1jeyksOM5AMAiCHZiXHVdg4zmQZlgR3YkqT7AVJanoSnYoTgZAGAV9GgxzpfCSkzo+uyo1sFOQ4BFyp7mNXZciaSxAADWQLAT41rW2Ens8uyoBLtNvn1DA51+7rvOmcCPBgDAGujRYpxv2nmws6Mcvs1AA01j1TensRL50QAAWAM9Woyr8gQ3E8unZefzro3suBjZAQBYBD1ajAt2qwgf34yshgBnY7XU7PCjAQCwBnq0GBfs6sk+5pYRDYHOxmoOdhwUKAMArIFgJ8aZCwoGWbOTmNC1zUDNAmWmngMALIIeLcaFKo0VaLBjFigT7AAALIIeLcaFKo0V6Gwspp4DAKyGHi3GmZuABj2y07U0FgXKAACroUeLcd2det7lNBYjOwAAi6FHi3GhS2OxXQQAoGci2IlxVSGbjcVGoACAnokeLcZVdzeN5eji1PMGpp4DAKyFHi3Gtd4INBiJ9i7W7LCoIADAYgh2YphhGC0bgXZzNlZdoFPPGdkBAFgMPVoM8zR4zVqb7qaxGgIe2aFmBwBgLfRoMcyXwpKk3s7ITD1nuwgAgNXQo8UwM4XlcsjeXHvTVYn2Ls7G8k09J9gBAFgEPVoM6+5MLElKdDQFSb5anGOhQBkAYDVRDXbWrFmjKVOmKC8vTzabTcuXLzfP1dfX684779SIESPUq1cv5eXl6f/9v/+nvXv3+r3G4MGDZbPZ/B7z58+P8CcJj+5uAiq1FCg3eLs29ZyRHQCAVUS1R6upqdGoUaO0YMGCNucOHz6szZs3695779XmzZv1/PPPa9u2bbr00kvbXPvAAw9o37595uO2226LRPPDrnUaK1hOFhUEAPRwwfeiIVBUVKSioqJ2z6Wnp2vlypV+x/7nf/5HZ555pnbv3q2BAweax1NTU5WTkxPw+3o8Hnk8HvO52+3uYssjo7tr7EiSIyHwNFZDo1fe5piIAmUAgFXEVY9WWVkpm82mjIwMv+Pz589X3759NXr0aD388MNqaGho/wWalZaWKj093Xzk5+eHsdXBC2UaK5DZWJ5WARE1OwAAq4jqyE5X1NbW6s4779S1116rtLQ08/hPfvITnX766crMzNS7776rkpIS7du3T48++miHr1VSUqK5c+eaz91ud0wGPCGt2QkgjdV69IeRHQCAVcRFsFNfX68f/OAHMgxDCxcu9DvXOmgZOXKknE6nfvSjH6m0tFQul6vd13O5XB2eiyXVnu7teC51bZ0d38iOw25TQpBT3QEAiDVB/fl+5MgRHT582Hy+a9cuPf744/rXv/4Vsob5+AKdXbt2aeXKlX6jOu0pKChQQ0ODvvzyy5C3JdK6u+O51Hq7iECCHYqTAQDWE1Svdtlll+m5556TJFVUVKigoECPPPKILrvssjYjL93hC3Q+//xzvf766+rbt+8xv6esrEx2u11ZWVkha0e0RCuNRQoLAGAlQfVqmzdv1rnnnitJ+tvf/qbs7Gzt2rVLzz33nJ544omAX6e6ulplZWUqKyuTJO3cuVNlZWXavXu36uvrddVVV2njxo1avHixGhsbVV5ervLyctXV1UmS1q1bp8cff1wffvihvvjiCy1evFhz5szRddddpz59+gTz0WKK29wENPg0ljOIAmWKkwEAVhLUkMHhw4eVmpoqSfrXv/6lK6+8Una7XWeddZZ27doV8Ots3LhRF1xwgfncV38zffp03XfffXrppZckSd/73vf8vu/NN9/U+PHj5XK5tHTpUt13333yeDwaMmSI5syZ41fHE89CsYKyOfW8C8EOIzsAACsJqhc98cQTtXz5cl1xxRV67bXXNGfOHEnSgQMHjllT09r48eNlGB2nVzo7J0mnn3661q9fH/D7xZvITz2nZgcAYD1B9Wrz5s3TT3/6Uw0ePFgFBQUqLCyU1DTKM3r06JA2sCfzraCc6urObCxqdgAAPVtQQwZXXXWVzjnnHO3bt0+jRo0yj0+YMEFXXHFFyBrX01WHYGTH6ej61HNGdgAAVhJ0L5qTk9Nmi4Yzzzyz2w1Ck0avoZq6prRSt2p27L6p58ce2aFAGQBgRUH1ojU1NZo/f75WrVqlAwcOyHvUjtpffPFFSBrXk/lGdSSpd4RqdkhjAQCsKKhe9Oabb9bq1at1/fXXKzc3VzYbq+2GWlXz6slOh71bIy2+NFYDBcoAgB4qqGDnlVde0T//+U+NGzcu1O1BM99MrLRujOpIrUd2KFAGAPRMQfVqffr0UWZmZqjbglZ8wU7vbmwVIbWu2WFRQQBAzxRUsPPLX/5S8+bN89sfC6EVik1Apa7NxmJkBwBgRUENGzzyyCPasWOHsrOzNXjwYCUm+nfImzdvDknjerJQLCgodW2dHWp2AABWFFRPevnll4e4GTiaO0RprC7tel7fnMZKJNgBAFhHl3vShoYG2Ww23XjjjRowYEA42gS1XlCwe2ks395Y9Y1eGYbR6cw5X0DkSiDYAQBYR5d7NYfDoYcfflgNDQ3HvhhBM7eK6GYay7fruWE0LVTYmZaRHQqUAQDWEdSf8BdeeKFWr14d6raglVDX7EhSwzGCHd/IjpORHQCAhQTVkxYVFemuu+7SRx99pDFjxqhXr15+5y+99NKQNK4nq/aEPtipa/QqqZNRG7NAmZodAICFBNWT/vjHP5YkPfroo23O2Ww2NTY2dq9VaJXG6l7NTmJCS41OfUPnRcrm1HNGdgAAFhJUsHP0XlgIvVDNxrLZbHLYbWrwGsdcRdlcVJCRHQCAhdCrxajqENXsSIFvBmoWKLOCMgDAQoLqSR944IFOz8+bNy+oxqBFVYhWUJaap5/XBxDsUKAMALCgoIKdF154we95fX29du7cKYfDoRNOOIFgJwRCtRGo1BK8HDONVU+BMgDAeoLqST/44IM2x9xut2bMmKErrrii243q6QzDaNkINIJpLKaeAwCsKGS9Wlpamu6//37de++9oXrJHqu23msuABiKNFZigJuBsqggAMCKQvonfGVlpSorK0P5kj2Sb9q5zSb1cnY/8Ei0B5bGMreLYCNQAICFBJUjeeKJJ/yeG4ahffv26U9/+pOKiopC0rCerPW08872sgpU4LOxmmp2nAQ7AAALCSrYeeyxx/ye2+129e/fX9OnT1dJSUlIGtaT+VZPTgtBCktqSWMda+dzc50dgh0AgIUEFezs3Lkz1O1AK6HaBNTHN7LT0EkayzCMlgJlgh0AgIUE1avdeOONqqqqanO8pqZGN954Y7cb1dNVhWj1ZJ+Wmp2OR3bqGw0ZzbEQiwoCAKwkqGDnj3/8o44cOdLm+JEjR/Tcc891u1E9XShXT5YCm43VOsVFGgsAYCVd6k3dbrcMw2haB6aqSklJSea5xsZGvfzyy8rKygp5I3sad4g2AfXxpbHqOtkI1FecLLHODgDAWroU7GRkZMhms8lms+nkk09uc95ms+n+++8PWeN6qlAuKCi1qtnxdlyz03pBQbu9+zPAAACIFV3qTd98800ZhqELL7xQf//735WZmWmeczqdGjRokPLy8kLeyJ7GNxsrdAXKx05j+RYUpDgZAGA1XepNzz//fElNs7EGDhwYkjVg0JZvNlbIpp4HksZi2jkAwKKC6tkGDRqktWvX6rrrrtPZZ5+tr7/+WpL0pz/9SWvXrg1pA3uikM/GCmAjUF8gxMgOAMBqgurZ/v73v2vSpElKTk7W5s2b5fF4JDVtF/HrX/86pA3siUKfxvKts9PZyE7zjucEOwAAiwmqZ/vVr36lJ598Un/4wx+UmNiSahk3bpw2b94cssb1VG5z6nmo0lgBTD1nZAcAYFFB9Wzbtm3Teeed1+Z4enq6KioqutumHs9XsxPqNFZdJ2mslpodFhQEAFhLUMFOTk6Otm/f3ub42rVrdfzxx3e7UT1dyBcVDGAjUAqUAQBWFVTPdsstt+j222/Xhg0bZLPZtHfvXi1evFj/+Z//qVmzZgX8OmvWrNGUKVOUl5cnm82m5cuX+503DEPz5s1Tbm6ukpOTNXHiRH3++ed+1xw6dEjTpk1TWlqaMjIydNNNN6m6ujqYjxUzfAXKoZqN5WxOYwVSs0MaCwBgNUH1bHfddZd++MMfasKECaqurtZ5552nm2++WbNmzdLNN98c8OvU1NRo1KhRWrBgQbvnH3roIT3xxBN68skntWHDBvXq1UuTJk1SbW2tec20adP08ccfa+XKlVqxYoXWrFmjmTNnBvOxYkJ9o1dHmlczDtWigo4upbEIdgAA1hJUz2az2XT33Xfr0KFD2rp1q9avX69vvvlG6enpGjJkSMCvU1RUpF/96le64oor2pwzDEOPP/647rnnHl122WUaOXKknnvuOe3du9ccAfrkk0/06quv6v/+7/9UUFCgc845R7/73e+0dOlS7d27N5iPFnW+FJYU2TQWBcoAAKvqUs/m8XhUUlKisWPHaty4cXr55Zd16qmn6uOPP9Ypp5yi3/72t5ozZ05IGrZz506Vl5dr4sSJ5rH09HQVFBRo3bp1kqR169YpIyNDY8eONa+ZOHGi7Ha7NmzY0OnncLvdfo9Y4Zt2npRoN4OU7gpoBWUKlAEAFtWloYN58+bpf//3fzVx4kS9++67uvrqq3XDDTdo/fr1euSRR3T11VcrISE0nWV5ebkkKTs72+94dna2ea68vLzNxqMOh0OZmZnmNe0pLS2N2T28WhYUDE29jtQyWtPAooIAgB6oSz3bsmXL9Nxzz+lvf/ub/vWvf6mxsVENDQ368MMPdc0114Qs0Am3kpISVVZWmo89e/ZEu0km38hOb1fo7qXD7qvZYVFBAEDP06We7auvvtKYMWMkScOHD5fL5dKcOXPCskdWTk6OJGn//v1+x/fv32+ey8nJ0YEDB/zONzQ06NChQ+Y17XG5XEpLS/N7xIqauqZgp1eI1tiRuraoIGksAIDVdCnYaWxslNPpNJ87HA717t075I2SpCFDhignJ0erVq0yj7ndbm3YsEGFhYWSpMLCQlVUVGjTpk3mNW+88Ya8Xq8KCgrC0q5wq/GEPtjxpaYCqdkhjQUAsJou9aiGYWjGjBlyuVySpNraWt16663q1auX33XPP/98QK9XXV3ttzjhzp07VVZWpszMTA0cOFB33HGHfvWrX+mkk07SkCFDdO+99yovL0+XX365JGnYsGGaPHmybrnlFj355JOqr6/X7Nmzdc011ygvL68rHy1m1HhCuwmo1JLG6mwjUNJYAACr6lKPOn36dL/n1113XbfefOPGjbrgggvM53PnzjXf59lnn9XPf/5z1dTUaObMmaqoqNA555yjV199VUlJSeb3LF68WLNnz9aECRNkt9s1depUPfHEE91qVzRVe5qCjmilsRjZAQBYTZd61EWLFoX0zcePHy/D6Hi0wWaz6YEHHtADDzzQ4TWZmZlasmRJSNsVTWYayxm62pnELqSxGNkBAFgNPVuMCUeBsjMh8KnnBDsAAKuhZ4sx4ShQdtib0lidTz1nNhYAwJoIdmJMTXPNTijX2QkkjWWO7CTyIwEAsBZ6thhTHY6p5769sRqOPRvLGaItKgAAiBX0bDGmpUA5lLOxmmt2vAGksRjZAQBYDD1bjKmpC/3Uc0fz1HNfqqo95tTzONnyAwCAQBHsxJiWAuXQBR1mGqvTRQUZ2QEAWBM9W4wJxwrKiQmBFyhTswMAsBp6thgTjgJl3wrKDV6jw0Ucze0iGNkBAFgMPVsMMQwjPHtjtRqt6SiVxTo7AACrItiJIZ4Gr7zNsUhKCLeLcPoFO+2nstj1HABgVfRsMcSXwpJCPfXcZn7dXrBjGAbbRQAALIueLYb4UlgpzgTZ7bZjXB24BLtNtuaXay+N1XobCUZ2AABWQ88WQ8JRnCw17R6faO94Rpan1fo7jOwAAKyGni2GtOyLFdpgR2pJZbUX7LRebJCp5wAAq6FniyE1dS1prFDrbDPQ1sXJNlvo0mcAAMQCgp0YUhOmNJbUemHBdmp2KE4GAFgYvVsMCccaOz6J9o7TWOaCggQ7AAALoneLIdWe0G8C6tNpGqueBQUBANZFsBNDWkZ2wlCz05zGqmvoeOo5084BAFZE7xZDWgqUQz+y47D79sfqbGSHHwcAgPXQu8WQcBYoOztJY9U1NvpdAwCAldC7xZCWdXYim8ZiZAcAYGX0bjEkXCsoS8dYVLCRAmUAgHUR7MSQsE49bx7Z6axmhzQWAMCK6N1iSE1d89TzMBQom4sKtpfGYp0dAICF0bvFEHPX87DU7DSlseqOsV0EAABWQ+8WQyKRxupsbyxGdgAAVkTvFkPCW6DcXLPTyd5YjOwAAKyI3i1GGIYR5pGdY6exmI0FALAigp0Y4Wnwyts86BLeXc/bmXpOGgsAYGH0bjHCl8KSpJTE8C0q2Nmu56SxAABWRO8WI8yZWM4E2Zv3sQolXxqrvZod0lgAACsj2IkR4SxOllptF9FJGouRHQCAFdG7xYiWfbHCG+x0lsaiZgcAYEX0bjGips43shOeVJK563k7KygzsgMAsLKY790GDx4sm83W5lFcXCxJGj9+fJtzt956a5Rb3XUtNTvhGdlxNNcB1be3NxazsQAAFhaenjWE3n//fTU2NprPt27dqu9///u6+uqrzWO33HKLHnjgAfN5SkpKRNsYCuFcY0dqncbqeGSHAmUAgBXFfLDTv39/v+fz58/XCSecoPPPP988lpKSopycnEg3LaSqm2t2wlagbKaxGNkBAPQscdW71dXV6c9//rNuvPFG2Wwt07MXL16sfv36afjw4SopKdHhw4c7fR2PxyO32+33iLaWkZ0w1ew0Tz2nQBkA0NPE/MhOa8uXL1dFRYVmzJhhHvvhD3+oQYMGKS8vT1u2bNGdd96pbdu26fnnn+/wdUpLS3X//fdHoMWBMwuUw1az0zyy46VAGQDQs8RVsPP000+rqKhIeXl55rGZM2eaX48YMUK5ubmaMGGCduzYoRNOOKHd1ykpKdHcuXPN5263W/n5+eFreADMAuWoprGo2QEAWE/cBDu7du3S66+/3umIjSQVFBRIkrZv395hsONyueRyuULexu5oWWcn8mkss0A5kZEdAID1xE3vtmjRImVlZemSSy7p9LqysjJJUm5ubgRaFTqRWkG5/Zqd5jRWQtz8OAAAELC4GNnxer1atGiRpk+fLoejpck7duzQkiVLdPHFF6tv377asmWL5syZo/POO08jR46MYou7LtxTzx2BTD1nZAcAYEFxEey8/vrr2r17t2688Ua/406nU6+//roef/xx1dTUKD8/X1OnTtU999wTpZYGr6aueep5mAqUEztIY3m9hrlfFiM7AAAriotg56KLLpJhtB2RyM/P1+rVq6PQotCrCXMay9lBGqv1xqCuRAqUAQDWw5/yMaIl2AlPwNFRGsvTanYWIzsAACuid4sR4S9Qbj+N5VtQ0GZruQYAACsh2IkBhmGEvUC5wzRWq60iWq9KDQCAVRDsxABPg1e+hY3DP/W8/TQWKSwAgFXRw8UAXwpLklLCVCTs6CCN1TLtnOJkAIA1EezEAHOrCGeC7PbwpJI6SmMxsgMAsDp6uBgQ7uJkqSWN5TWkxlabgXrqm3c8Z0FBAIBF0cPFgJZ9scIY7LTa0bz16A4LCgIArI4eLgbU1IV3jR1JcrRKj7UOdjz11OwAAKyNYCcGmAsKhmmrCKkljSX5z8jyjey4HPwoAACsiR4uBoR7qwhJSrDblGBvOyPLt6ggwQ4AwKro4WJAdXPNTjiDHallheS6VltEtF5UEAAAK6KHiwEtqyeHt24m0d70z93QejaWb+o5wQ4AwKLo4WKAWaAcxpodqWVGVrsFyg4KlAEA1kSwEwMiUbMjdZDGYuo5AMDi6OFiQCTW2ZFa74/VemSHRQUBANZGDxcDfCsop4S7ZiehnZodpp4DACyOHi4GtBQoRyaNVd/QtmaHAmUAgFXRw8WAmrrmqefhLlBuHtmpa2e7CAqUAQBWRbATAyJXoOyr2Wm9ESgjOwAAa6OHiwGRTmM1sIIyAKAHoYeLAZEuUPZLY7GoIADA4ujhoswwjAiO7LSTxmqgZgcAYG0EO1HmafDKNxM8UosK1rczskMaCwBgVfRwUeZLYUlSSmKE1tlpp2aHNBYAwKro4aLMnInlTJDdbgvre7XU7LSksepYVBAAYHH0cFHWUpwc3hSW1NF2ERQoAwCsjR4uyiK1L5bUdgXlPYcOa+e3NZKkrFRX2N8fAIBoINiJspo634KC4Z8NZY7sNFdEP7HqczV4DZ17Uj+dmJUa9vcHACAaCHairKVmJ7JprJ3f1uj5D76WJM35/slhf28AAKKFYCfKIrXGjiQlOlrSWE+s+lyNXkMXnNJfpw/sE/b3BgAgWsLfw6JT1c01O+FeY0eSEu1Nse0n5W69u+OgJGnu908J+/sCABBNBDtR1rIJaORqdt7Z3hToXHRqtkYMSA/7+wIAEE2ksaLMLFCORM2Ow38dH2p1AAA9AcFOlLWM7IQ/2HEmtPxzXzIyV8Ny08L+ngAARBvBTpRFcp0dR/MKzXabNGfiSWF/PwAAYgHBTpRVR3BkZ2jzSM61Zw5kXR0AQI8R08HOfffdJ5vN5vcYOnSoeb62tlbFxcXq27evevfuralTp2r//v1RbHHX7HfXavOu7yRJmb0Sw/5+Zx3fVxv+a4J+ednwsL8XAACxIqaDHUk67bTTtG/fPvOxdu1a89ycOXP0j3/8Q8uWLdPq1au1d+9eXXnllVFsbeDqG70qXrxZB2vqNDQnVeNPyYrI+2anJYV9w1EAAGJJzE89dzgcysnJaXO8srJSTz/9tJYsWaILL7xQkrRo0SINGzZM69ev11lnndXha3o8Hnk8HvO52+0OfcOPofTlT7Vx13dKTXLoyevGKCkx/FPPAQDoiWJ+ZOfzzz9XXl6ejj/+eE2bNk27d++WJG3atEn19fWaOHGiee3QoUM1cOBArVu3rtPXLC0tVXp6uvnIz88P62c42oote/XMOzslSY9cPUqD+/WK6PsDANCTxHSwU1BQoGeffVavvvqqFi5cqJ07d+rcc89VVVWVysvL5XQ6lZGR4fc92dnZKi8v7/R1S0pKVFlZaT727NkTxk/hb/uBKv38b1skSbPGn6CLTms7agUAAEInptNYRUVF5tcjR45UQUGBBg0apL/+9a9KTk4O+nVdLpdcLlcomtgltfWN+tGfNulwXaPOPqGv/pNF/QAACLuYHtk5WkZGhk4++WRt375dOTk5qqurU0VFhd81+/fvb7fGJxa8s/1b7fimRv16O/XEtaPlSIir2w8AQFyKq962urpaO3bsUG5ursaMGaPExEStWrXKPL9t2zbt3r1bhYWFUWxlx8rdtZKk7+X3Ub/ekR9ZAgCgJ4rpNNZPf/pTTZkyRYMGDdLevXv1i1/8QgkJCbr22muVnp6um266SXPnzlVmZqbS0tJ02223qbCwsNOZWNH0TVXTDLD+qQQ6AABESkwHO1999ZWuvfZaHTx4UP3799c555yj9evXq3///pKkxx57THa7XVOnTpXH49GkSZP0+9//Psqt7hjBDgAAkRfTwc7SpUs7PZ+UlKQFCxZowYIFEWpR9xDsAAAQeXFVsxPvvqluDnao1wEAIGIIdiKIkR0AACKPYCdCDMMwg50sgh0AACKGYCdCqjwN8jR4JYlp5wAARBDBToT4RnVSXQ4lO9n0EwCASCHYiRDqdQAAiA6CnQjxBTv9CHYAAIgogp0IYWQHAIDoINiJENbYAQAgOgh2IoSRHQAAooNgJ0IIdgAAiA6CnQgh2AEAIDoIdiKEmh0AAKKDYCcCGr2GDlazVQQAANFAsBMBh2rq5DUkm03K7OWMdnMAAOhRCHYiwFev07eXU44EbjkAAJFEzxsBvnodNgAFACDyCHYigJlYAABED8FOBBDsAAAQPQQ7EUCwAwBA9BDsRABr7AAAED0EOxHwTVWtJEZ2AACIBoKdCPClsbJSk6LcEgAAeh6CnQigZgcAgOgh2Amz2vpGuWsbJBHsAAAQDQQ7YfZtc3Gy02FXWpIjyq0BAKDnIdgJMzOF1dslm80W5dYAANDzEOyEGfU6AABEF8FOmJlr7BDsAAAQFQQ7YcbIDgAA0UWwE2ata3YAAEDkEeyE2QFGdgAAiCqCnTAjjQUAQHQR7IQZwQ4AANFFsBNGhmGw4zkAAFFGsBNG7toG1TV4JTGyAwBAtMR0sFNaWqozzjhDqampysrK0uWXX65t27b5XTN+/HjZbDa/x6233hqlFvvzpbBSkxxKSkyIcmsAAOiZYjrYWb16tYqLi7V+/XqtXLlS9fX1uuiii1RTU+N33S233KJ9+/aZj4ceeihKLfZHvQ4AANEX0ztTvvrqq37Pn332WWVlZWnTpk0677zzzOMpKSnKycmJdPOOiXodAACiL6ZHdo5WWVkpScrMzPQ7vnjxYvXr10/Dhw9XSUmJDh8+3OnreDweud1uv0c4MLIDAED0xfTITmter1d33HGHxo0bp+HDh5vHf/jDH2rQoEHKy8vTli1bdOedd2rbtm16/vnnO3yt0tJS3X///WFvM8EOAADRFzfBTnFxsbZu3aq1a9f6HZ85c6b59YgRI5Sbm6sJEyZox44dOuGEE9p9rZKSEs2dO9d87na7lZ+fH/I2E+wAABB9cRHszJ49WytWrNCaNWs0YMCATq8tKCiQJG3fvr3DYMflcsnlCn8AQs0OAADRF9PBjmEYuu222/TCCy/orbfe0pAhQ475PWVlZZKk3NzcMLfu2BjZAQAg+mI62CkuLtaSJUv04osvKjU1VeXl5ZKk9PR0JScna8eOHVqyZIkuvvhi9e3bV1u2bNGcOXN03nnnaeTIkVFufVOwZrcR7AAAEE02wzCMaDeiIzabrd3jixYt0owZM7Rnzx5dd9112rp1q2pqapSfn68rrrhC99xzj9LS0gJ+H7fbrfT0dFVWVnbp+wLR6DVkk2S3t/9ZAABAcALtv2N6ZOdYcVh+fr5Wr14dodYEJ4EgBwCAqIqrdXYAAAC6imAHAABYGsEOAACwNIIdAABgaQQ7AADA0gh2AACApRHsAAAASyPYAQAAlkawAwAALI1gBwAAWBrBDgAAsDSCHQAAYGkEOwAAwNJietfzSPHtru52u6PcEgAAEChfv+3rxztCsCOpqqpKkpSfnx/llgAAgK6qqqpSenp6h+dtxrHCoR7A6/Vq7969Sk1Nlc1mC9nrut1u5efna8+ePUpLSwvZ66It7nXkcK8jh3sdWdzvyAnVvTYMQ1VVVcrLy5Pd3nFlDiM7kux2uwYMGBC2109LS+M/ToRwryOHex053OvI4n5HTijudWcjOj4UKAMAAEsj2AEAAJZGsBNGLpdLv/jFL+RyuaLdFMvjXkcO9zpyuNeRxf2OnEjfawqUAQCApTGyAwAALI1gBwAAWBrBDgAAsDSCHQAAYGkEO2G0YMECDR48WElJSSooKNB7770X7SbFvdLSUp1xxhlKTU1VVlaWLr/8cm3bts3vmtraWhUXF6tv377q3bu3pk6dqv3790epxdYwf/582Ww23XHHHeYx7nNoff3117ruuuvUt29fJScna8SIEdq4caN53jAMzZs3T7m5uUpOTtbEiRP1+eefR7HF8amxsVH33nuvhgwZouTkZJ1wwgn65S9/6be3Evc6OGvWrNGUKVOUl5cnm82m5cuX+50P5L4eOnRI06ZNU1pamjIyMnTTTTepurq6+40zEBZLly41nE6n8cwzzxgff/yxccsttxgZGRnG/v37o920uDZp0iRj0aJFxtatW42ysjLj4osvNgYOHGhUV1eb19x6661Gfn6+sWrVKmPjxo3GWWedZZx99tlRbHV8e++994zBgwcbI0eONG6//XbzOPc5dA4dOmQMGjTImDFjhrFhwwbjiy++MF577TVj+/bt5jXz58830tPTjeXLlxsffvihcemllxpDhgwxjhw5EsWWx58HH3zQ6Nu3r7FixQpj586dxrJly4zevXsbv/3tb81ruNfBefnll427777beP755w1JxgsvvOB3PpD7OnnyZGPUqFHG+vXrjbfffts48cQTjWuvvbbbbSPYCZMzzzzTKC4uNp83NjYaeXl5RmlpaRRbZT0HDhwwJBmrV682DMMwKioqjMTERGPZsmXmNZ988okhyVi3bl20mhm3qqqqjJNOOslYuXKlcf7555vBDvc5tO68807jnHPO6fC81+s1cnJyjIcfftg8VlFRYbhcLuMvf/lLJJpoGZdccolx4403+h278sorjWnTphmGwb0OlaODnUDu67///W9DkvH++++b17zyyiuGzWYzvv766261hzRWGNTV1WnTpk2aOHGiecxut2vixIlat25dFFtmPZWVlZKkzMxMSdKmTZtUX1/vd++HDh2qgQMHcu+DUFxcrEsuucTvfkrc51B76aWXNHbsWF199dXKysrS6NGj9Yc//ME8v3PnTpWXl/vd7/T0dBUUFHC/u+jss8/WqlWr9Nlnn0mSPvzwQ61du1ZFRUWSuNfhEsh9XbdunTIyMjR27FjzmokTJ8put2vDhg3den82Ag2Db7/9Vo2NjcrOzvY7np2drU8//TRKrbIer9erO+64Q+PGjdPw4cMlSeXl5XI6ncrIyPC7Njs7W+Xl5VFoZfxaunSpNm/erPfff7/NOe5zaH3xxRdauHCh5s6dq//6r//S+++/r5/85CdyOp2aPn26eU/b+53C/e6au+66S263W0OHDlVCQoIaGxv14IMPatq0aZLEvQ6TQO5reXm5srKy/M47HA5lZmZ2+94T7CBuFRcXa+vWrVq7dm20m2I5e/bs0e23366VK1cqKSkp2s2xPK/Xq7Fjx+rXv/61JGn06NHaunWrnnzySU2fPj3KrbOWv/71r1q8eLGWLFmi0047TWVlZbrjjjuUl5fHvbYw0lhh0K9fPyUkJLSZmbJ//37l5OREqVXWMnv2bK1YsUJvvvmmBgwYYB7PyclRXV2dKioq/K7n3nfNpk2bdODAAZ1++ulyOBxyOBxavXq1nnjiCTkcDmVnZ3OfQyg3N1ennnqq37Fhw4Zp9+7dkmTeU36ndN/PfvYz3XXXXbrmmms0YsQIXX/99ZozZ45KS0slca/DJZD7mpOTowMHDvidb2ho0KFDh7p97wl2wsDpdGrMmDFatWqVeczr9WrVqlUqLCyMYsvin2EYmj17tl544QW98cYbGjJkiN/5MWPGKDEx0e/eb9u2Tbt37+bed8GECRP00UcfqayszHyMHTtW06ZNM7/mPofOuHHj2iyh8Nlnn2nQoEGSpCFDhignJ8fvfrvdbm3YsIH73UWHDx+W3e7f9SUkJMjr9UriXodLIPe1sLBQFRUV2rRpk3nNG2+8Ia/Xq4KCgu41oFvlzejQ0qVLDZfLZTz77LPGv//9b2PmzJlGRkaGUV5eHu2mxbVZs2YZ6enpxltvvWXs27fPfBw+fNi85tZbbzUGDhxovPHGG8bGjRuNwsJCo7CwMIqttobWs7EMg/scSu+9957hcDiMBx980Pj888+NxYsXGykpKcaf//xn85r58+cbGRkZxosvvmhs2bLFuOyyy5gOHYTp06cbxx13nDn1/Pnnnzf69etn/PznPzev4V4Hp6qqyvjggw+MDz74wJBkPProo8YHH3xg7Nq1yzCMwO7r5MmTjdGjRxsbNmww1q5da5x00klMPY91v/vd74yBAwcaTqfTOPPMM43169dHu0lxT1K7j0WLFpnXHDlyxPjxj39s9OnTx0hJSTGuuOIKY9++fdFrtEUcHexwn0PrH//4hzF8+HDD5XIZQ4cONZ566im/816v17j33nuN7Oxsw+VyGRMmTDC2bdsWpdbGL7fbbdx+++3GwIEDjaSkJOP444837r77bsPj8ZjXcK+D8+abb7b7+3n69OmGYQR2Xw8ePGhce+21Ru/evY20tDTjhhtuMKqqqrrdNpthtFo2EgAAwGKo2QEAAJZGsAMAACyNYAcAAFgawQ4AALA0gh0AAGBpBDsAAMDSCHYAAIClEewAAABLI9gBAEk2m03Lly+PdjMAhAHBDoComzFjhmw2W5vH5MmTo900ABbgiHYDAECSJk+erEWLFvkdc7lcUWoNACthZAdATHC5XMrJyfF79OnTR1JTimnhwoUqKipScnKyjj/+eP3tb3/z+/6PPvpIF154oZKTk9W3b1/NnDlT1dXVftc888wzOu200+RyuZSbm6vZs2f7nf/22291xRVXKCUlRSeddJJeeukl89x3332nadOmqX///kpOTtZJJ53UJjgDEJsIdgDEhXvvvVdTp07Vhx9+qGnTpumaa67RJ598IkmqqanRpEmT1KdPH73//vtatmyZXn/9db9gZuHChSouLtbMmTP10Ucf6aWXXtKJJ57o9x7333+/fvCDH2jLli26+OKLNW3aNB06dMh8/3//+9965ZVX9Mknn2jhwoXq169f5G4AgOB1e990AOim6dOnGwkJCUavXr38Hg8++KBhGIYhybj11lv9vqegoMCYNWuWYRiG8dRTTxl9+vQxqqurzfP//Oc/DbvdbpSXlxuGYRh5eXnG3Xff3WEbJBn33HOP+by6utqQZLzyyiuGYRjGlClTjBtuuCE0HxhARFGzAyAmXHDBBVq4cKHfsczMTPPrwsJCv3OFhYUqKyuTJH3yyScaNWqUevXqZZ4fN26cvF6vtm3bJpvNpr1792rChAmdtmHkyJHm17169VJaWpoOHDggSZo1a5amTp2qzZs366KLLtLll1+us88+O6jPCiCyCHYAxIRevXq1SSuFSnJyckDXJSYm+j232Wzyer2SpKKiIu3atUsvv/yyVq5cqQkTJqi4uFi/+c1vQt5eAKFFzQ6AuLB+/fo2z4cNGyZJGjZsmD788EPV1NSY59955x3Z7XadcsopSk1N1eDBg7Vq1aputaF///6aPn26/vznP+vxxx/XU0891a3XAxAZjOwAiAkej0fl5eV+xxwOh1kEvGzZMo0dO1bnnHOOFi9erPfee09PP/20JGnatGn6xS9+oenTp+u+++7TN998o9tuu03XX3+9srOzJUn33Xefbr31VmVlZamoqEhVVVV65513dNtttwXUvnnz5mnMmDE67bTT5PF4tGLFCjPYAhDbCHYAxIRXX31Vubm5fsdOOeUUffrpp5KaZkotXbpUP/7xj5Wbm6u//OUvOvXUUyVJKSkpeu2113T77bfrjDPOUEpKiqZOnapHH33UfK3p06ertrZWjz32mH7605+qX79+uuqqqwJun9PpVElJib788kslJyfr3HPP1dKlS0PwyQGEm80wDCPajQCAzthsNr3wwgu6/PLLo90UAHGImh0AAGBpBDsAAMDSqNkBEPPItgPoDkZ2AACApRHsAAAASyPYAQAAlkawAwAALI1gBwAAWBrBDgAAsDSCHQAAYGkEOwAAwNL+f3+5PFTq0hp2AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Model\n", "features = ts.utils.net.common.Net(\n", " state_shape=env.observation_space.shape,\n", " hidden_sizes=[64, 64],\n", " device=device)\n", "\n", "actor = ts.utils.net.discrete.Actor(\n", " preprocess_net=features,\n", " action_shape=env.action_space.n,\n", " device=device).to(device)\n", "\n", "critic = ts.utils.net.discrete.Critic(\n", " preprocess_net=features,\n", " device=device).to(device)\n", "\n", "actor_critic = ts.utils.net.common.ActorCritic(actor=actor, critic=critic)\n", "\n", "optim = torch.optim.Adam(actor_critic.parameters(), lr=0.003)\n", "\n", "# Policy\n", "policy = ts.policy.PPOPolicy(\n", " actor=actor,\n", " critic=critic,\n", " optim=optim,\n", " dist_fn=torch.distributions.Categorical,\n", " action_space=env.action_space,\n", " deterministic_eval=True,\n", " action_scaling=False,\n", " discount_factor=0.99,\n", " max_grad_norm=0.5,\n", " eps_clip=0.2,\n", " gae_lambda=0.95,\n", ")\n", "\n", "# Collector\n", "collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " buffer=ts.data.VectorReplayBuffer(20000, 10),\n", " exploration_noise=True\n", ")\n", "collector.reset()\n", "\n", "test_collector = ts.data.Collector(\n", " policy=policy,\n", " env=ts.env.DummyVectorEnv([lambda: gym.make('CartPole-v0') for _ in range(10)]),\n", " exploration_noise=False\n", ")\n", "\n", "# On-policy trainer\n", "returns = []\n", "for iteration in (pbar := tqdm.tqdm(range(100))):\n", "\n", " # Training phase\n", " policy.train()\n", " policy.is_within_training_step = True\n", "\n", " # Collect enough on-policy steps\n", " result = collector.collect(n_step=3000)\n", "\n", " # Update the PP0 network by learning the on-policy buffer 10 times\n", " policy.update(\n", " buffer=collector.buffer,\n", " sample_size=0, # use the whole buffer\n", " batch_size=256,\n", " repeat=10,\n", " )\n", "\n", " # Empty the buffer as we are on-policy\n", " collector.reset_buffer(keep_statistics=False)\n", "\n", " # Test 10 episodes\n", " policy.eval()\n", " test_collector.reset()\n", " result = test_collector.collect(n_episode=10)\n", " mean_reward = result.returns.mean()\n", " pbar.set_description(f\"reward : {mean_reward}\")\n", " returns.append(mean_reward)\n", "\n", "plt.figure()\n", "plt.plot(np.array(returns))\n", "plt.xlabel(\"Epochs\")\n", "plt.ylabel(\"Returns\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "KnqAWBLTGbb9" }, "outputs": [], "source": [ "# Evaluation mode\n", "policy.eval()\n", "\n", "# Create a recordable environment\n", "env = gym.make('CartPole-v0', render_mode=\"rgb_array_list\")\n", "recorder = GymRecorder(env)\n", "\n", "# Sample the initial state\n", "state, info = env.reset()\n", "\n", "# One episode:\n", "done = False\n", "return_episode = 0\n", "while not done:\n", " # Select an action from the learned policy\n", " action = policy.forward(ts.data.Batch(obs=[state], info=None)).act[0].numpy()\n", " # Sample a single transition\n", " next_state, reward, terminal, truncated, info = env.step(action)\n", " # End of the episode\n", " done = terminal or truncated\n", " # Update undiscounted return\n", " return_episode += reward\n", " # Go in the next state\n", " state = next_state\n", "\n", "print(\"Return:\", return_episode)\n", "\n", "recorder.record(env.render())\n", "video = \"videos/cartpole-ppo.gif\"\n", "recorder.make_video(video)\n", "ipython_display(video)" ] }, { "cell_type": "markdown", "metadata": { "id": "i78ymsX_Gbb9" }, "source": [ "**Q:** How does it compare to DQN once the right hyperparameters are found? What is their influence? Play especially with `eps_clip`, the $\\epsilon$ threshold used to clip the IS weight in the PPO loss.\n", "\n", "**Q:** Apply PPO to more complex environments available in gymnasium. Beware that for continuous action spaces, you will need to use continuous actor/critic networks, i.e.:\n", "\n", "```python\n", "actor = ts.utils.net.continuous.Actor(...)\n", "critic = ts.utils.net.continuous.Critic(...)\n", "```\n", "\n", "instead of:\n", "\n", "```python\n", "actor = ts.utils.net.discrete.Actor(...)\n", "critic = ts.utils.net.discrete.Critic(...)\n", "```\n", "\n", "The `dist_fn` argument of `PPOPolicy` must also be set accordingly. Check the doc!" ] } ], "metadata": { "accelerator": "GPU", "colab": { "gpuType": "T4", "provenance": [] }, "kernelspec": { "display_name": "deeprl", "language": "python", "name": "deeprl" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.8" } }, "nbformat": 4, "nbformat_minor": 0 }