{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Rainbow with Quantile Regression" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import gym\n", "import numpy as np\n", "\n", "import torch\n", "import torch.optim as optim\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "\n", "from IPython.display import clear_output\n", "from matplotlib import pyplot as plt\n", "%matplotlib inline\n", "\n", "from timeit import default_timer as timer\n", "from datetime import timedelta\n", "import math\n", "\n", "from utils.wrappers import *\n", "from agents.DQN import Model as DQN_Agent\n", "from utils.ReplayMemory import PrioritizedReplayMemory\n", "from networks.layers import NoisyLinear\n", "\n", "from utils.hyperparameters import Config" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hyperparameters" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "config = Config()\n", "\n", "config.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", "\n", "#Multi-step returns\n", "config.N_STEPS = 3\n", "\n", "#misc agent variables\n", "config.GAMMA=0.99\n", "config.LR=1e-4\n", "\n", "#memory\n", "config.TARGET_NET_UPDATE_FREQ = 1000\n", "config.EXP_REPLAY_SIZE = 100000\n", "config.BATCH_SIZE = 32\n", "config.PRIORITY_ALPHA=0.3\n", "config.PRIORITY_BETA_START=0.4\n", "config.PRIORITY_BETA_FRAMES = 100000\n", "\n", "#epsilon variables\n", "config.SIGMA_INIT=0.5\n", "\n", "#Learning control variables\n", "config.LEARN_START = 10000\n", "config.MAX_FRAMES=1000000\n", "\n", "#Quantile Regression Parameters\n", "config.QUANTILES=51" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Network" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "class DuelingQRDQN(nn.Module):\n", " def __init__(self, input_shape, num_actions, sigma_init=0.5, quantiles=51):\n", " super(DuelingQRDQN, self).__init__()\n", " \n", " self.input_shape = input_shape\n", " self.num_actions = num_actions\n", " self.quantiles=quantiles\n", "\n", " self.conv1 = nn.Conv2d(self.input_shape[0], 32, kernel_size=8, stride=4)\n", " self.conv2 = nn.Conv2d(32, 64, kernel_size=4, stride=2)\n", " self.conv3 = nn.Conv2d(64, 64, kernel_size=3, stride=1)\n", "\n", " self.adv1 = NoisyLinear(self.feature_size(), 512, sigma_init)\n", " self.adv2 = NoisyLinear(512, self.num_actions*self.quantiles, sigma_init)\n", "\n", " self.val1 = NoisyLinear(self.feature_size(), 512, sigma_init)\n", " self.val2 = NoisyLinear(512, 1*self.quantiles, sigma_init)\n", " \n", " def forward(self, x):\n", " x = F.relu(self.conv1(x))\n", " x = F.relu(self.conv2(x))\n", " x = F.relu(self.conv3(x))\n", " x = x.view(x.size(0), -1)\n", " adv = F.relu(self.adv1(x))\n", " adv = self.adv2(adv).view(-1, self.num_actions, self.quantiles)\n", "\n", " val = F.relu(self.val1(x))\n", " val = self.val2(val).view(-1, 1, self.quantiles)\n", "\n", " return val + adv - adv.mean(dim=1).view(-1, 1, self.quantiles)\n", " \n", " def feature_size(self):\n", " return self.conv3(self.conv2(self.conv1(torch.zeros(1, *self.input_shape)))).view(1, -1).size(1)\n", " \n", " def sample_noise(self):\n", " self.adv1.sample_noise()\n", " self.adv2.sample_noise()\n", " self.val1.sample_noise()\n", " self.val2.sample_noise()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Agent" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class Model(DQN_Agent):\n", " def __init__(self, static_policy=False, env=None, config=None):\n", " self.num_quantiles = config.QUANTILES\n", " self.cumulative_density = torch.tensor((2 * np.arange(self.num_quantiles) + 1) / (2.0 * self.num_quantiles), device=config.device, dtype=torch.float) \n", " self.quantile_weight = 1.0 / self.num_quantiles\n", "\n", " super(Model, self).__init__(static_policy, env, config)\n", "\n", " self.nsteps=max(self.nsteps, 3)\n", " \n", " def declare_networks(self):\n", " self.model = DuelingQRDQN(self.num_feats, self.num_actions, sigma_init=self.sigma_init, quantiles=self.num_quantiles)\n", " self.target_model = DuelingQRDQN(self.num_feats, self.num_actions, sigma_init=self.sigma_init, quantiles=self.num_quantiles)\n", " \n", " def declare_memory(self):\n", " self.memory = PrioritizedReplayMemory(self.experience_replay_size, self.priority_alpha, self.priority_beta_start, self.priority_beta_frames)\n", " \n", " def next_distribution(self, batch_vars):\n", " batch_state, batch_action, batch_reward, non_final_next_states, non_final_mask, empty_next_state_values, indices, weights = batch_vars\n", "\n", " with torch.no_grad():\n", " quantiles_next = torch.zeros((self.batch_size, self.num_quantiles), device=self.device, dtype=torch.float)\n", " if not empty_next_state_values:\n", " self.target_model.sample_noise()\n", " max_next_action = self.get_max_next_state_action(non_final_next_states)\n", " quantiles_next[non_final_mask] = self.target_model(non_final_next_states).gather(1, max_next_action).squeeze(dim=1)\n", "\n", " quantiles_next = batch_reward + (self.gamma*quantiles_next)\n", "\n", " return quantiles_next\n", " \n", " def compute_loss(self, batch_vars):\n", " batch_state, batch_action, batch_reward, non_final_next_states, non_final_mask, empty_next_state_values, indices, weights = batch_vars\n", "\n", " batch_action = batch_action.unsqueeze(dim=-1).expand(-1, -1, self.num_quantiles)\n", "\n", " self.model.sample_noise()\n", " quantiles = self.model(batch_state)\n", " quantiles = quantiles.gather(1, batch_action).squeeze(1)\n", "\n", " quantiles_next = self.next_distribution(batch_vars)\n", " \n", " diff = quantiles_next.t().unsqueeze(-1) - quantiles.unsqueeze(0)\n", "\n", " loss = self.huber(diff) * torch.abs(self.cumulative_density.view(1, -1) - (diff < 0).to(torch.float))\n", " loss = loss.transpose(0,1)\n", " self.memory.update_priorities(indices, loss.detach().mean(1).sum(-1).abs().cpu().numpy().tolist())\n", " loss = loss * weights.view(self.batch_size, 1, 1)\n", " loss = loss.mean(1).sum(-1).mean()\n", "\n", " return loss\n", "\n", " def get_action(self, s):\n", " with torch.no_grad():\n", " X = torch.tensor([s], device=self.device, dtype=torch.float) \n", " self.model.sample_noise()\n", " a = (self.model(X) * self.quantile_weight).sum(dim=2).max(dim=1)[1]\n", " return a.item()\n", "\n", " def get_max_next_state_action(self, next_states):\n", " next_dist = self.model(next_states) * self.quantile_weight\n", " return next_dist.sum(dim=2).max(1)[1].view(next_states.size(0), 1, 1).expand(-1, -1, self.num_quantiles)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot Results" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def plot(frame_idx, rewards, losses, sigma, elapsed_time):\n", " clear_output(True)\n", " plt.figure(figsize=(20,5))\n", " plt.subplot(131)\n", " plt.title('frame %s. reward: %s. time: %s' % (frame_idx, np.mean(rewards[-10:]), elapsed_time))\n", " plt.plot(rewards)\n", " if losses:\n", " plt.subplot(132)\n", " plt.title('loss')\n", " plt.plot(losses)\n", " if sigma:\n", " plt.subplot(133)\n", " plt.title('noisy param magnitude')\n", " plt.plot(sigma)\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Training Loop" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "start=timer()\n", "\n", "env_id = \"PongNoFrameskip-v4\"\n", "env = make_atari(env_id)\n", "env = wrap_deepmind(env, frame_stack=False)\n", "env = wrap_pytorch(env)\n", "model = Model(env=env, config=config)\n", "\n", "episode_reward = 0\n", "\n", "observation = env.reset()\n", "for frame_idx in range(1, config.MAX_FRAMES + 1):\n", " action = model.get_action(observation)\n", " prev_observation=observation\n", " observation, reward, done, _ = env.step(action)\n", " observation = None if done else observation\n", "\n", " model.update(prev_observation, action, reward, observation, frame_idx)\n", " episode_reward += reward\n", "\n", " if done:\n", " model.finish_nstep()\n", " model.reset_hx()\n", " observation = env.reset()\n", " model.save_reward(episode_reward)\n", " episode_reward = 0\n", " \n", " if np.mean(model.rewards[-10:]) > 19:\n", " plot(frame_idx, all_rewards, losses, timedelta(seconds=int(timer()-start)))\n", " break\n", "\n", " if frame_idx % 10000 == 0:\n", " plot(frame_idx, model.rewards, model.losses, model.sigma_parameter_mag, timedelta(seconds=int(timer()-start)))\n", "\n", "model.save_w()\n", "env.close()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.6.3" } }, "nbformat": 4, "nbformat_minor": 2 }