{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Configurations for Colab" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import sys\n", "IN_COLAB = \"google.colab\" in sys.modules\n", "\n", "if IN_COLAB:\n", " !apt install python-opengl\n", " !apt install ffmpeg\n", " !apt install xvfb\n", " !pip install PyVirtualDisplay==3.0\n", " !pip install gymnasium==0.28.1\n", " from pyvirtualdisplay import Display\n", " \n", " # Start virtual display\n", " dis = Display(visible=0, size=(400, 400))\n", " dis.start()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 01. DQN\n", "\n", "[V. Mnih et al., \"Human-level control through deep reinforcement learning.\" Nature, 518\n", "(7540):529–533, 2015.](https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf)\n", "\n", "Reinforcement learning is known to be unstable or even to diverge when a nonlinear function approximator such as a neural network is used to represent the action-value (also known as $Q$) function. This instability has several causes: the correlations present in the sequence of observations, the fact that small updates to $Q$ may significantly change the policy and therefore change the data distribution, and the correlations between the action-values ($Q$) and the target values $r + \\gamma \\max_{a'} Q(s', a')$.\n", "\n", "The authors suggest two key ideas to address these instabilities with a novel variant of Q-learning: Replay buffer and Fixed Q-target.\n", "\n", "#### Uniformly random sampling from Experience Replay Memory\n", "\n", "Reinforcement learning agent stores the experiences consecutively in the buffer, so adjacent ($s, a, r, s'$) transitions stored are highly likely to have correlation. To remove this, the agent samples experiences uniformly at random from the pool of stored samples $\\big( (s, a, r, s') \\sim U(D) \\big)$. See sample_batch method of ReplayBuffer class for more details.\n", "\n", "#### Fixed Q-target\n", "\n", "DQN uses an iterative update that adjusts the action-values ($Q$) towards target values that are only periodically updated, thereby reducing correlations with the target; if not, it is easily divergy because the target continuously moves. The Q-learning update at iteration $i$ uses the following loss function:\n", "\n", "$$\n", "L_i(\\theta_i) = \\mathbb{E}_{(s,a,r,s') \\sim U(D)} \\big[ \\big( r + \\gamma \\max_{a'} Q(s',a';\\theta_i^-) - Q(s, a; \\theta_i) \\big)^2 \\big]\n", "$$\n", "\n", "in which $\\gamma$ is the discount factor determining the agent’s horizon, $\\theta_i$ are the parameters of the Q-network at iteration $i$ and $\\theta_i^-$ are the network parameters used to compute the target at iteration $i$. The target network parameters $\\theta_i^-$ are only updated with the Q-network parameters ($\\theta_i$) every C steps and are held fixed between individual updates. ($C = 200$ in CartPole-v0)\n", "\n", "#### For more stability: Gradient clipping\n", "\n", "The authors also found it helpful to clip the error term from the update $r + \\gamma \\max_{a'} Q(s', a'; \\theta_i^-) - Q(s,a,;\\theta_i)$ to be between -1 and 1. Because the absolute value loss function $|x|$ has a derivative of -1 for all negative values of x and a derivative of 1 for all positive values of x, clipping the squared error to be between -1 and 1 corresponds to using an absolute value loss function for errors outside of the (-1,1) interval. This form of error clipping further improved the stability of the algorithm." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/jinwoo.park/miniforge3/envs/rainbow-is-all-you-need/lib/python3.8/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] } ], "source": [ "import os\n", "from typing import Dict, List, Tuple\n", "\n", "import gymnasium as gym\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "import torch.optim as optim\n", "from IPython.display import clear_output" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Replay buffer\n", "\n", "Typically, people implement replay buffers with one of the following three data structures:\n", "\n", " - collections.deque\n", " - list\n", " - numpy.ndarray\n", " \n", "**deque** is very easy to handle once you initialize its maximum length (e.g. deque(maxlen=buffer_size)). However, the indexing operation of deque gets terribly slow as it grows up because it is [internally doubly linked list](https://wiki.python.org/moin/TimeComplexity#collections.deque). On the other hands, **list** is an array, so it is relatively faster than deque when you sample batches at every step. Its amortized cost of *Get item* is [O(1)](https://wiki.python.org/moin/TimeComplexity#list).\n", "\n", "Last but not least, let's see **numpy.ndarray**. numpy.ndarray is even faster than list due to the fact that it is [a homogeneous array of fixed-size items](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html#numpy.ndarray), so you can get the benefits of [locality of reference](https://en.wikipedia.org/wiki/Locality_of_reference). Whereas list is an array of pointers to objects, even when all of them are of the same type.\n", "\n", "Here, we are going to implement a replay buffer using numpy.ndarray.\n", "\n", "\n", "Reference: [OpenAI spinning-up](https://github.com/openai/spinningup/blob/master/spinup/algos/sac/sac.py#L10)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "class ReplayBuffer:\n", " \"\"\"A simple numpy replay buffer.\"\"\"\n", "\n", " def __init__(self, obs_dim: int, size: int, batch_size: int = 32):\n", " self.obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n", " self.next_obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n", " self.acts_buf = np.zeros([size], dtype=np.float32)\n", " self.rews_buf = np.zeros([size], dtype=np.float32)\n", " self.done_buf = np.zeros(size, dtype=np.float32)\n", " self.max_size, self.batch_size = size, batch_size\n", " self.ptr, self.size, = 0, 0\n", "\n", " def store(\n", " self,\n", " obs: np.ndarray,\n", " act: np.ndarray, \n", " rew: float, \n", " next_obs: np.ndarray, \n", " done: bool,\n", " ):\n", " self.obs_buf[self.ptr] = obs\n", " self.next_obs_buf[self.ptr] = next_obs\n", " self.acts_buf[self.ptr] = act\n", " self.rews_buf[self.ptr] = rew\n", " self.done_buf[self.ptr] = done\n", " self.ptr = (self.ptr + 1) % self.max_size\n", " self.size = min(self.size + 1, self.max_size)\n", "\n", " def sample_batch(self) -> Dict[str, np.ndarray]:\n", " idxs = np.random.choice(self.size, size=self.batch_size, replace=False)\n", " return dict(obs=self.obs_buf[idxs],\n", " next_obs=self.next_obs_buf[idxs],\n", " acts=self.acts_buf[idxs],\n", " rews=self.rews_buf[idxs],\n", " done=self.done_buf[idxs])\n", "\n", " def __len__(self) -> int:\n", " return self.size" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Network\n", "\n", "We are going to use a simple network architecture with three fully connected layers and two non-linearity functions (ReLU)." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class Network(nn.Module):\n", " def __init__(self, in_dim: int, out_dim: int):\n", " \"\"\"Initialization.\"\"\"\n", " super(Network, self).__init__()\n", "\n", " self.layers = nn.Sequential(\n", " nn.Linear(in_dim, 128), \n", " nn.ReLU(),\n", " nn.Linear(128, 128), \n", " nn.ReLU(), \n", " nn.Linear(128, out_dim)\n", " )\n", "\n", " def forward(self, x: torch.Tensor) -> torch.Tensor:\n", " \"\"\"Forward method implementation.\"\"\"\n", " return self.layers(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## DQN Agent\n", "\n", "Here is a summary of DQNAgent class.\n", "\n", "| Method | Note |\n", "| --- | --- |\n", "|select_action | select an action from the input state. |\n", "|step | take an action and return the response of the env. |\n", "|compute_dqn_loss | return dqn loss. |\n", "|update_model | update the model by gradient descent. |\n", "|target_hard_update| hard update from the local model to the target model.|\n", "|train | train the agent during num_frames. |\n", "|test | test the agent (1 episode). |\n", "|plot | plot the training progresses. |\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "class DQNAgent:\n", " \"\"\"DQN Agent interacting with environment.\n", " \n", " Attribute:\n", " env (gym.Env): openAI Gym environment\n", " memory (ReplayBuffer): replay memory to store transitions\n", " batch_size (int): batch size for sampling\n", " epsilon (float): parameter for epsilon greedy policy\n", " epsilon_decay (float): step size to decrease epsilon\n", " max_epsilon (float): max value of epsilon\n", " min_epsilon (float): min value of epsilon\n", " target_update (int): period for target model's hard update\n", " gamma (float): discount factor\n", " dqn (Network): model to train and select actions\n", " dqn_target (Network): target model to update\n", " optimizer (torch.optim): optimizer for training dqn\n", " transition (list): transition information including \n", " state, action, reward, next_state, done\n", " \"\"\"\n", "\n", " def __init__(\n", " self, \n", " env: gym.Env,\n", " memory_size: int,\n", " batch_size: int,\n", " target_update: int,\n", " epsilon_decay: float,\n", " seed: int,\n", " max_epsilon: float = 1.0,\n", " min_epsilon: float = 0.1,\n", " gamma: float = 0.99,\n", " ):\n", " \"\"\"Initialization.\n", " \n", " Args:\n", " env (gym.Env): openAI Gym environment\n", " memory_size (int): length of memory\n", " batch_size (int): batch size for sampling\n", " target_update (int): period for target model's hard update\n", " epsilon_decay (float): step size to decrease epsilon\n", " lr (float): learning rate\n", " max_epsilon (float): max value of epsilon\n", " min_epsilon (float): min value of epsilon\n", " gamma (float): discount factor\n", " \"\"\"\n", " obs_dim = env.observation_space.shape[0]\n", " action_dim = env.action_space.n\n", " \n", " self.env = env\n", " self.memory = ReplayBuffer(obs_dim, memory_size, batch_size)\n", " self.batch_size = batch_size\n", " self.epsilon = max_epsilon\n", " self.epsilon_decay = epsilon_decay\n", " self.seed = seed\n", " self.max_epsilon = max_epsilon\n", " self.min_epsilon = min_epsilon\n", " self.target_update = target_update\n", " self.gamma = gamma\n", " \n", " # device: cpu / gpu\n", " self.device = torch.device(\n", " \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", " )\n", " print(self.device)\n", "\n", " # networks: dqn, dqn_target\n", " self.dqn = Network(obs_dim, action_dim).to(self.device)\n", " self.dqn_target = Network(obs_dim, action_dim).to(self.device)\n", " self.dqn_target.load_state_dict(self.dqn.state_dict())\n", " self.dqn_target.eval()\n", " \n", " # optimizer\n", " self.optimizer = optim.Adam(self.dqn.parameters())\n", "\n", " # transition to store in memory\n", " self.transition = list()\n", " \n", " # mode: train / test\n", " self.is_test = False\n", "\n", " def select_action(self, state: np.ndarray) -> np.ndarray:\n", " \"\"\"Select an action from the input state.\"\"\"\n", " # epsilon greedy policy\n", " if self.epsilon > np.random.random():\n", " selected_action = self.env.action_space.sample()\n", " else:\n", " selected_action = self.dqn(\n", " torch.FloatTensor(state).to(self.device)\n", " ).argmax()\n", " selected_action = selected_action.detach().cpu().numpy()\n", " \n", " if not self.is_test:\n", " self.transition = [state, selected_action]\n", " \n", " return selected_action\n", "\n", " def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool]:\n", " \"\"\"Take an action and return the response of the env.\"\"\"\n", " next_state, reward, terminated, truncated, _ = self.env.step(action)\n", " done = terminated or truncated\n", "\n", " if not self.is_test:\n", " self.transition += [reward, next_state, done]\n", " self.memory.store(*self.transition)\n", " \n", " return next_state, reward, done\n", "\n", " def update_model(self) -> torch.Tensor:\n", " \"\"\"Update the model by gradient descent.\"\"\"\n", " samples = self.memory.sample_batch()\n", "\n", " loss = self._compute_dqn_loss(samples)\n", "\n", " self.optimizer.zero_grad()\n", " loss.backward()\n", " self.optimizer.step()\n", "\n", " return loss.item()\n", " \n", " def train(self, num_frames: int, plotting_interval: int = 200):\n", " \"\"\"Train the agent.\"\"\"\n", " self.is_test = False\n", " \n", " state, _ = self.env.reset(seed=self.seed)\n", " update_cnt = 0\n", " epsilons = []\n", " losses = []\n", " scores = []\n", " score = 0\n", "\n", " for frame_idx in range(1, num_frames + 1):\n", " action = self.select_action(state)\n", " next_state, reward, done = self.step(action)\n", "\n", " state = next_state\n", " score += reward\n", "\n", " # if episode ends\n", " if done:\n", " state, _ = self.env.reset(seed=self.seed)\n", " scores.append(score)\n", " score = 0\n", "\n", " # if training is ready\n", " if len(self.memory) >= self.batch_size:\n", " loss = self.update_model()\n", " losses.append(loss)\n", " update_cnt += 1\n", " \n", " # linearly decrease epsilon\n", " self.epsilon = max(\n", " self.min_epsilon, self.epsilon - (\n", " self.max_epsilon - self.min_epsilon\n", " ) * self.epsilon_decay\n", " )\n", " epsilons.append(self.epsilon)\n", " \n", " # if hard update is needed\n", " if update_cnt % self.target_update == 0:\n", " self._target_hard_update()\n", "\n", " # plotting\n", " if frame_idx % plotting_interval == 0:\n", " self._plot(frame_idx, scores, losses, epsilons)\n", " \n", " self.env.close()\n", " \n", " def test(self, video_folder: str) -> None:\n", " \"\"\"Test the agent.\"\"\"\n", " self.is_test = True\n", " \n", " # for recording a video\n", " naive_env = self.env\n", " self.env = gym.wrappers.RecordVideo(self.env, video_folder=video_folder)\n", " \n", " state, _ = self.env.reset(seed=self.seed)\n", " done = False\n", " score = 0\n", " \n", " while not done:\n", " action = self.select_action(state)\n", " next_state, reward, done = self.step(action)\n", "\n", " state = next_state\n", " score += reward\n", " \n", " print(\"score: \", score)\n", " self.env.close()\n", " \n", " # reset\n", " self.env = naive_env\n", "\n", " def _compute_dqn_loss(self, samples: Dict[str, np.ndarray]) -> torch.Tensor:\n", " \"\"\"Return dqn loss.\"\"\"\n", " device = self.device # for shortening the following lines\n", " state = torch.FloatTensor(samples[\"obs\"]).to(device)\n", " next_state = torch.FloatTensor(samples[\"next_obs\"]).to(device)\n", " action = torch.LongTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n", " reward = torch.FloatTensor(samples[\"rews\"].reshape(-1, 1)).to(device)\n", " done = torch.FloatTensor(samples[\"done\"].reshape(-1, 1)).to(device)\n", "\n", " # G_t = r + gamma * v(s_{t+1}) if state != Terminal\n", " # = r otherwise\n", " curr_q_value = self.dqn(state).gather(1, action)\n", " next_q_value = self.dqn_target(\n", " next_state\n", " ).max(dim=1, keepdim=True)[0].detach()\n", " mask = 1 - done\n", " target = (reward + self.gamma * next_q_value * mask).to(self.device)\n", "\n", " # calculate dqn loss\n", " loss = F.smooth_l1_loss(curr_q_value, target)\n", "\n", " return loss\n", "\n", " def _target_hard_update(self):\n", " \"\"\"Hard update: target <- local.\"\"\"\n", " self.dqn_target.load_state_dict(self.dqn.state_dict())\n", " \n", " def _plot(\n", " self, \n", " frame_idx: int, \n", " scores: List[float], \n", " losses: List[float], \n", " epsilons: List[float],\n", " ):\n", " \"\"\"Plot the training progresses.\"\"\"\n", " clear_output(True)\n", " plt.figure(figsize=(20, 5))\n", " plt.subplot(131)\n", " plt.title('frame %s. score: %s' % (frame_idx, np.mean(scores[-10:])))\n", " plt.plot(scores)\n", " plt.subplot(132)\n", " plt.title('loss')\n", " plt.plot(losses)\n", " plt.subplot(133)\n", " plt.title('epsilons')\n", " plt.plot(epsilons)\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Environment\n", "\n", "You can see the [code](https://github.com/Farama-Foundation/Gymnasium/blob/main/gymnasium/envs/classic_control/cartpole.py) and [configurations](https://github.com/Farama-Foundation/Gymnasium/blob/main/gymnasium/envs/classic_control/cartpole.py#L91) of CartPole-v1 from Farama Gymnasium's repository." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# environment\n", "env = gym.make(\"CartPole-v1\", max_episode_steps=200, render_mode=\"rgb_array\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set random seed" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "seed = 777\n", "\n", "def seed_torch(seed):\n", " torch.manual_seed(seed)\n", " if torch.backends.cudnn.enabled:\n", " torch.cuda.manual_seed(seed)\n", " torch.backends.cudnn.benchmark = False\n", " torch.backends.cudnn.deterministic = True\n", "\n", "np.random.seed(seed)\n", "seed_torch(seed)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Initialize" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cpu\n" ] } ], "source": [ "# parameters\n", "num_frames = 10000\n", "memory_size = 1000\n", "batch_size = 32\n", "target_update = 100\n", "epsilon_decay = 1 / 2000\n", "\n", "agent = DQNAgent(env, memory_size, batch_size, target_update, epsilon_decay, seed)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Train" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "agent.train(num_frames)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test\n", "\n", "Run the trained agent (1 episode)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Moviepy - Building video /Users/jinwoo.park/Repositories/rainbow-is-all-you-need/videos/dqn/rl-video-episode-0.mp4.\n", "Moviepy - Writing video /Users/jinwoo.park/Repositories/rainbow-is-all-you-need/videos/dqn/rl-video-episode-0.mp4\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " " ] }, { "name": "stdout", "output_type": "stream", "text": [ "Moviepy - Done !\n", "Moviepy - video ready /Users/jinwoo.park/Repositories/rainbow-is-all-you-need/videos/dqn/rl-video-episode-0.mp4\n", "score: 179.0\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r" ] } ], "source": [ "video_folder=\"videos/dqn\"\n", "agent.test(video_folder=video_folder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Render" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Played: videos/dqn/rl-video-episode-0.mp4\n" ] } ], "source": [ "import base64\n", "import glob\n", "import io\n", "import os\n", "\n", "from IPython.display import HTML, display\n", "\n", "\n", "def ipython_show_video(path: str) -> None:\n", " \"\"\"Show a video at `path` within IPython Notebook.\"\"\"\n", " if not os.path.isfile(path):\n", " raise NameError(\"Cannot access: {}\".format(path))\n", "\n", " video = io.open(path, \"r+b\").read()\n", " encoded = base64.b64encode(video)\n", "\n", " display(HTML(\n", " data=\"\"\"\n", " \n", " \"\"\".format(encoded.decode(\"ascii\"))\n", " ))\n", "\n", "\n", "def show_latest_video(video_folder: str) -> str:\n", " \"\"\"Show the most recently recorded video from video folder.\"\"\"\n", " list_of_files = glob.glob(os.path.join(video_folder, \"*.mp4\"))\n", " latest_file = max(list_of_files, key=os.path.getctime)\n", " ipython_show_video(latest_file)\n", " return latest_file\n", "\n", "\n", "latest_file = show_latest_video(video_folder=video_folder)\n", "print(\"Played:\", latest_file)" ] } ], "metadata": { "kernelspec": { "display_name": "rainbow-is-all-you-need", "language": "python", "name": "rainbow-is-all-you-need" }, "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.8.12" } }, "nbformat": 4, "nbformat_minor": 1 }