diff --git a/lessons/6-Other/22-DeepRL/CartPole-RL-Pytorch.ipynb b/lessons/6-Other/22-DeepRL/CartPole-RL-Pytorch.ipynb index c6e59995..5cdf7305 100644 --- a/lessons/6-Other/22-DeepRL/CartPole-RL-Pytorch.ipynb +++ b/lessons/6-Other/22-DeepRL/CartPole-RL-Pytorch.ipynb @@ -6,7 +6,7 @@ "source": [ "# Training RL to do Cartpole Balancing\n", "\n", - "This notebooks is part of [AI for Beginners Curriculum](http://aka.ms/ai-beginners). It has been inspired by [this blog post](https://medium.com/swlh/policy-gradient-reinforcement-learning-with-keras-57ca6ed32555), [official TensorFlow documentation](https://www.tensorflow.org/tutorials/reinforcement_learning/actor_critic) and [this Keras RL example](https://keras.io/examples/rl/actor_critic_cartpole/).\n", + "This notebooks is part of [AI for Beginners Curriculum](http://aka.ms/ai-beginners). It has been inspired by [official PyTorch tutorial](https://pytorch.org/tutorials/intermediate/reinforcement_q_learning.html) and [this Cartpole Pytorch implementation](https://github.com/yc930401/Actor-Critic-pytorch).\n", "\n", "In this example, we will use RL to train a model to balance a pole on a cart that can move left and right on horizontal scale. We will use [OpenAI Gym](https://www.gymlibrary.ml/) environment to simulate the pole.\n", "\n", @@ -26,20 +26,15 @@ "text": [ "Defaulting to user installation because normal site-packages is not writeable\n", "Requirement already satisfied: gym in /home/leo/.local/lib/python3.10/site-packages (0.25.0)\n", - "Collecting pygame\n", - " Downloading pygame-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (21.9 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.9/21.9 MB\u001b[0m \u001b[31m3.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: cloudpickle>=1.2.0 in /home/leo/.local/lib/python3.10/site-packages (from gym) (2.1.0)\n", - "Requirement already satisfied: numpy>=1.18.0 in /usr/lib/python3/dist-packages (from gym) (1.21.5)\n", "Requirement already satisfied: gym-notices>=0.0.4 in /home/leo/.local/lib/python3.10/site-packages (from gym) (0.0.7)\n", - "Installing collected packages: pygame\n", - "Successfully installed pygame-2.1.2\n" + "Requirement already satisfied: numpy>=1.18.0 in /usr/lib/python3/dist-packages (from gym) (1.21.5)\n", + "Requirement already satisfied: cloudpickle>=1.2.0 in /home/leo/.local/lib/python3.10/site-packages (from gym) (2.1.0)\n" ] } ], "source": [ "import sys\n", - "!{sys.executable} -m pip install gym pygame" + "!{sys.executable} -m pip install gym" ] }, { @@ -54,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -78,8 +73,6 @@ ], "source": [ "import gym\n", - "import pygame\n", - "import tqdm\n", "\n", "env = gym.make(\"CartPole-v1\")\n", "\n", @@ -98,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -115,17 +108,37 @@ "name": "stdout", "output_type": "stream", "text": [ - "[-0.01024284 0.23410203 -0.02896851 -0.2558368 ] -> 1.0\n", - "[-0.0055608 0.42962533 -0.03408524 -0.5575143 ] -> 1.0\n", - "[ 0.00303171 0.6252088 -0.04523553 -0.86073816] -> 1.0\n", - "[ 0.01553589 0.82091665 -0.06245029 -1.1672944 ] -> 1.0\n", - "[ 0.03195422 1.0167931 -0.08579618 -1.4788847 ] -> 1.0\n", - "[ 0.05229008 1.2128513 -0.11537387 -1.7970835 ] -> 1.0\n", - "[ 0.07654711 1.0191944 -0.15131554 -1.542374 ] -> 1.0\n", - "[ 0.096931 0.82618064 -0.18216303 -1.3004787 ] -> 1.0\n", - "[ 0.11345461 0.63377684 -0.2081726 -1.0699085 ] -> 1.0\n", - "[ 0.12613015 0.83095175 -0.22957078 -1.420047 ] -> 1.0\n", - "Total reward: 10.0\n" + "[-0.03742469 0.21191828 -0.01393784 -0.2686444 ] -> 1.0\n", + "[-0.03318632 0.40723634 -0.01931073 -0.56569064] -> 1.0\n", + "[-0.02504159 0.21239054 -0.03062454 -0.2791534 ] -> 1.0\n", + "[-0.02079378 0.01771855 -0.03620761 0.00371545] -> 1.0\n", + "[-0.02043941 -0.17686592 -0.0361333 0.28475815] -> 1.0\n", + "[-0.02397673 -0.3714544 -0.03043814 0.56582946] -> 1.0\n", + "[-0.03140582 -0.17591895 -0.01912155 0.2637147 ] -> 1.0\n", + "[-0.0349242 0.01947064 -0.01384726 -0.03493749] -> 1.0\n", + "[-0.03453479 0.2147884 -0.01454601 -0.331957 ] -> 1.0\n", + "[-0.03023902 0.01987648 -0.02118515 -0.04389644] -> 1.0\n", + "[-0.02984149 0.21529572 -0.02206307 -0.34318748] -> 1.0\n", + "[-0.02553557 0.4107245 -0.02892683 -0.6427453 ] -> 1.0\n", + "[-0.01732108 0.21601741 -0.04178173 -0.35931018] -> 1.0\n", + "[-0.01300073 0.41170764 -0.04896794 -0.6648696 ] -> 1.0\n", + "[-0.00476658 0.2172998 -0.06226533 -0.38799822] -> 1.0\n", + "[-4.2058565e-04 4.1324776e-01 -7.0025288e-02 -6.9964474e-01] -> 1.0\n", + "[ 0.00784437 0.21916293 -0.08401819 -0.42980158] -> 1.0\n", + "[ 0.01222763 0.41536793 -0.09261422 -0.74774325] -> 1.0\n", + "[ 0.02053499 0.22163741 -0.10756908 -0.4855825 ] -> 1.0\n", + "[ 0.02496774 0.02818474 -0.11728073 -0.2286451 ] -> 1.0\n", + "[ 0.02553143 -0.16508296 -0.12185363 0.02486342] -> 1.0\n", + "[ 0.02222977 0.03155665 -0.12135637 -0.30364525] -> 1.0\n", + "[ 0.0228609 0.22818024 -0.12742928 -0.6320028 ] -> 1.0\n", + "[ 0.02742451 0.03504482 -0.14006932 -0.38201147] -> 1.0\n", + "[ 0.02812541 -0.1578393 -0.14770955 -0.13656472] -> 1.0\n", + "[ 0.02496862 0.03905562 -0.15044086 -0.47195992] -> 1.0\n", + "[ 0.02574973 0.23594654 -0.15988004 -0.80802345] -> 1.0\n", + "[ 0.03046866 0.43285596 -0.17604052 -1.1464254 ] -> 1.0\n", + "[ 0.03912578 0.24041417 -0.19896902 -0.913713 ] -> 1.0\n", + "[ 0.04393407 0.43759024 -0.21724328 -1.2617537 ] -> 1.0\n", + "Total reward: 30.0\n" ] } ], @@ -139,9 +152,7 @@ " obs, rew, done, info = env.step(env.action_space.sample())\n", " total_reward += rew\n", " print(f\"{obs} -> {rew}\")\n", - "print(f\"Total reward: {total_reward}\")\n", - "\n", - "env.close()" + "print(f\"Total reward: {total_reward}\")" ] }, { @@ -167,35 +178,23 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", - "import tensorflow as tf\n", - "from tensorflow import keras\n", "import matplotlib.pyplot as plt\n", "import torch\n", "\n", "num_inputs = 4\n", "num_actions = 2\n", "\n", - "# model = torch.nn.Sequential(\n", - "# torch.nn.Linear(num_inputs, 2),\n", - "# torch.nn.ReLU(),\n", - "# torch.nn.Linear(2, num_actions)\n", - "# )\n", - "\n", "model = torch.nn.Sequential(\n", " torch.nn.Linear(num_inputs, 128, bias=False, dtype=torch.float32),\n", " torch.nn.ReLU(),\n", " torch.nn.Linear(128, num_actions, bias = False, dtype=torch.float32),\n", " torch.nn.Softmax(dim=1)\n", - ")\n", - "\n", - "optimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n", - "# optimizer = torch.optim.SGD(model.parameters(), lr=0.01)\n", - "# optimizer = keras.optimizers.Adam(learning_rate=0.01)" + ")" ] }, { @@ -207,14 +206,13 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def run_episode(max_steps_per_episode = 10000,render=False): \n", " states, actions, probs, rewards = [],[],[],[]\n", " state = env.reset()\n", - " # print(state.dtype)\n", " for _ in range(max_steps_per_episode):\n", " if render:\n", " env.render()\n", @@ -240,19 +238,19 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Total reward: 24.0\n" + "Total reward: 35.0\n" ] } ], "source": [ - "s,a,p,r = run_episode()\n", + "s, a, p, r = run_episode()\n", "print(f\"Total reward: {np.sum(r)}\")" ] }, @@ -265,7 +263,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -297,78 +295,50 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ - "def train_on_batch4(states,actions,probs,rewards):\n", - " rewards = discounted_rewards(rewards)\n", - " probs = probs[np.arange(len(probs)),actions]\n", - " # probs = probs.reshape(-1,1)\n", - " rewards = rewards.reshape(-1,1)\n", - " probs = torch.from_numpy(probs)\n", - " rewards = torch.from_numpy(rewards)\n", - " loss = -torch.mean(torch.log(probs) * rewards)\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - " return loss.item()\n", - "\n", - "def train_on_batch2(states,target):\n", - " states = torch.from_numpy(states)\n", - " # target = target.reshape(-1,1)\n", - " target = torch.from_numpy(target)\n", - " y = model(states)\n", - " print(y)\n", - " loss = -torch.mean(torch.log(y) * target)\n", - " optimizer.zero_grad()\n", - " loss.backward()\n", - " optimizer.step()\n", - " return loss.item()\n", + "optimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n", "\n", "def train_on_batch(x, y):\n", " x = torch.from_numpy(x)\n", " y = torch.from_numpy(y)\n", " optimizer.zero_grad()\n", " predictions = model(x)\n", - " loss = torch.nn.CrossEntropyLoss()(predictions, y) # (y, predictions)\n", + " loss = -torch.mean(torch.log(predictions) * y)\n", " loss.backward()\n", " optimizer.step()\n", - " return loss.item()\n", - " w.data.sub_(learning_rate * w.grad)\n", - " b.data.sub_(learning_rate * b.grad)\n", - " w.grad.zero_()\n", - " b.grad.zero_()\n", " return loss" ] }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "0 -> 25.0\n", - "100 -> 21.0\n", - "200 -> 7.0\n" + "0 -> 12.0\n", + "100 -> 117.0\n", + "200 -> 499.0\n" ] }, { "data": { "text/plain": [ - "[]" + "[]" ] }, - "execution_count": 88, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -390,7 +360,6 @@ " dr = discounted_rewards(rewards)\n", " gradients *= dr\n", " target = alpha*np.vstack([gradients])+probs\n", - " # loss = train_on_batch4(states,actions,probs,rewards)\n", " train_on_batch(states,target)\n", " history.append(np.sum(rewards))\n", " if epoch%100==0:\n", @@ -408,7 +377,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -420,29 +389,6 @@ "See here for more information: https://www.gymlibrary.ml/content/api/\u001b[0m\n", " deprecation(\n" ] - }, - { - "ename": "error", - "evalue": "display Surface quit", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31merror\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_41886/1459719159.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrun_episode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrender\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/tmp/ipykernel_41886/4189192208.py\u001b[0m in \u001b[0;36mrun_episode\u001b[0;34m(max_steps_per_episode, render)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmax_steps_per_episode\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0menv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0maction_probs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_numpy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexpand_dims\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0maction\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchoice\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_actions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msqueeze\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maction_probs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdetach\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m )\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrender_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 429\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 430\u001b[0m \u001b[0;34m\"\"\"Renders the environment.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 431\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 432\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 433\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mclose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m )\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrender_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/wrappers/order_enforcing.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 49\u001b[0m \u001b[0;34m\"set `disable_render_order_enforcing=True` on the OrderEnforcer wrapper.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 50\u001b[0m )\n\u001b[0;32m---> 51\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 52\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m )\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrender_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 429\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 430\u001b[0m \u001b[0;34m\"\"\"Renders the environment.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 431\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 432\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 433\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mclose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m )\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrender_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/wrappers/env_checker.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0menv_render_passive_checker\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 54\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 55\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/core.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m )\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrender_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mrender\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/envs/classic_control/cartpole.py\u001b[0m in \u001b[0;36mrender\u001b[0;34m(self, mode)\u001b[0m\n\u001b[1;32m 215\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrenderer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_renders\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 216\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 217\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_render\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 218\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 219\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_render\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"human\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/.local/lib/python3.10/site-packages/gym/envs/classic_control/cartpole.py\u001b[0m in \u001b[0;36m_render\u001b[0;34m(self, mode)\u001b[0m\n\u001b[1;32m 296\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 297\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msurf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpygame\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransform\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msurf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 298\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscreen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msurf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 299\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmode\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"human\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 300\u001b[0m \u001b[0mpygame\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mevent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpump\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31merror\u001b[0m: display Surface quit" - ] } ], "source": [ @@ -466,53 +412,146 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ - "num_inputs = 4\n", - "num_actions = 2\n", - "num_hidden = 128\n", + "from itertools import count\n", + "import torch.nn.functional as F" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/leo/.local/lib/python3.10/site-packages/gym/core.py:329: DeprecationWarning: \u001b[33mWARN: Initializing wrapper in old step API which returns one bool instead of two. It is recommended to set `new_step_api=True` to use new step API. This will be the default behaviour in future.\u001b[0m\n", + " deprecation(\n", + "/home/leo/.local/lib/python3.10/site-packages/gym/wrappers/step_api_compatibility.py:39: DeprecationWarning: \u001b[33mWARN: Initializing environment in old step API which returns one bool instead of two. It is recommended to set `new_step_api=True` to use new step API. This will be the default behaviour in future.\u001b[0m\n", + " deprecation(\n" + ] + } + ], + "source": [ + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "env = gym.make(\"CartPole-v1\")\n", "\n", - "inputs = keras.layers.Input(shape=(num_inputs,))\n", - "common = keras.layers.Dense(num_hidden, activation=\"relu\")(inputs)\n", - "action = keras.layers.Dense(num_actions, activation=\"softmax\")(common)\n", - "critic = keras.layers.Dense(1)(common)\n", + "state_size = env.observation_space.shape[0]\n", + "action_size = env.action_space.n\n", + "lr = 0.0001\n", "\n", - "model = keras.Model(inputs=inputs, outputs=[action, critic])" + "class Actor(torch.nn.Module):\n", + " def __init__(self, state_size, action_size):\n", + " super(Actor, self).__init__()\n", + " self.state_size = state_size\n", + " self.action_size = action_size\n", + " self.linear1 = torch.nn.Linear(self.state_size, 128)\n", + " self.linear2 = torch.nn.Linear(128, 256)\n", + " self.linear3 = torch.nn.Linear(256, self.action_size)\n", + "\n", + " def forward(self, state):\n", + " output = F.relu(self.linear1(state))\n", + " output = F.relu(self.linear2(output))\n", + " output = self.linear3(output)\n", + " distribution = torch.distributions.Categorical(F.softmax(output, dim=-1))\n", + " return distribution\n", + "\n", + "\n", + "class Critic(torch.nn.Module):\n", + " def __init__(self, state_size, action_size):\n", + " super(Critic, self).__init__()\n", + " self.state_size = state_size\n", + " self.action_size = action_size\n", + " self.linear1 = torch.nn.Linear(self.state_size, 128)\n", + " self.linear2 = torch.nn.Linear(128, 256)\n", + " self.linear3 = torch.nn.Linear(256, 1)\n", + "\n", + " def forward(self, state):\n", + " output = F.relu(self.linear1(state))\n", + " output = F.relu(self.linear2(output))\n", + " value = self.linear3(output)\n", + " return value" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We would need to slightly modify our `run_episode` function to return also critic results:" + "We would need to slightly modify our `discounted_rewards` and `run_episode` functions:" ] }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ - "def run_episode(max_steps_per_episode = 10000,render=False): \n", - " states, actions, probs, rewards, critic = [],[],[],[],[]\n", - " state = env.reset()\n", - " for _ in range(max_steps_per_episode):\n", - " if render:\n", + "def discounted_rewards(next_value, rewards, masks, gamma=0.99):\n", + " R = next_value\n", + " returns = []\n", + " for step in reversed(range(len(rewards))):\n", + " R = rewards[step] + gamma * R * masks[step]\n", + " returns.insert(0, R)\n", + " return returns\n", + "\n", + "def run_episode(actor, critic, n_iters):\n", + " optimizerA = torch.optim.Adam(actor.parameters())\n", + " optimizerC = torch.optim.Adam(critic.parameters())\n", + " for iter in range(n_iters):\n", + " state = env.reset()\n", + " log_probs = []\n", + " values = []\n", + " rewards = []\n", + " masks = []\n", + " entropy = 0\n", + " env.reset()\n", + "\n", + " for i in count():\n", " env.render()\n", - " action_probs, est_rew = model(np.expand_dims(state,0))\n", - " action = np.random.choice(num_actions, p=np.squeeze(action_probs[0]))\n", - " nstate, reward, done, info = env.step(action)\n", - " if done:\n", - " break\n", - " states.append(state)\n", - " actions.append(action)\n", - " probs.append(tf.math.log(action_probs[0,action]))\n", - " rewards.append(reward)\n", - " critic.append(est_rew[0,0])\n", - " state = nstate\n", - " return states, actions, probs, rewards, critic" + " state = torch.FloatTensor(state).to(device)\n", + " dist, value = actor(state), critic(state)\n", + "\n", + " action = dist.sample()\n", + " next_state, reward, done, _ = env.step(action.cpu().numpy())\n", + "\n", + " log_prob = dist.log_prob(action).unsqueeze(0)\n", + " entropy += dist.entropy().mean()\n", + "\n", + " log_probs.append(log_prob)\n", + " values.append(value)\n", + " rewards.append(torch.tensor([reward], dtype=torch.float, device=device))\n", + " masks.append(torch.tensor([1-done], dtype=torch.float, device=device))\n", + "\n", + " state = next_state\n", + "\n", + " if done:\n", + " print('Iteration: {}, Score: {}'.format(iter, i))\n", + " break\n", + "\n", + "\n", + " next_state = torch.FloatTensor(next_state).to(device)\n", + " next_value = critic(next_state)\n", + " returns = discounted_rewards(next_value, rewards, masks)\n", + "\n", + " log_probs = torch.cat(log_probs)\n", + " returns = torch.cat(returns).detach()\n", + " values = torch.cat(values)\n", + "\n", + " advantage = returns - values\n", + "\n", + " actor_loss = -(log_probs * advantage.detach()).mean()\n", + " critic_loss = advantage.pow(2).mean()\n", + "\n", + " optimizerA.zero_grad()\n", + " optimizerC.zero_grad()\n", + " actor_loss.backward()\n", + " critic_loss.backward()\n", + " optimizerA.step()\n", + " optimizerC.step()\n" ] }, { @@ -524,93 +563,101 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "running reward: 5.82 at episode 10\n", - "running reward: 9.43 at episode 20\n", - "running reward: 10.30 at episode 30\n", - "running reward: 10.28 at episode 40\n", - "running reward: 11.00 at episode 50\n", - "running reward: 13.01 at episode 60\n", - "running reward: 21.78 at episode 70\n", - "running reward: 40.54 at episode 80\n", - "running reward: 73.70 at episode 90\n", - "running reward: 100.19 at episode 100\n", - "running reward: 159.20 at episode 110\n", - "Solved at episode 114!\n" + "Iteration: 0, Score: 31\n", + "Iteration: 1, Score: 17\n", + "Iteration: 2, Score: 11\n", + "Iteration: 3, Score: 11\n", + "Iteration: 4, Score: 13\n", + "Iteration: 5, Score: 23\n", + "Iteration: 6, Score: 13\n", + "Iteration: 7, Score: 16\n", + "Iteration: 8, Score: 17\n", + "Iteration: 9, Score: 10\n", + "Iteration: 10, Score: 34\n", + "Iteration: 11, Score: 16\n", + "Iteration: 12, Score: 17\n", + "Iteration: 13, Score: 26\n", + "Iteration: 14, Score: 15\n", + "Iteration: 15, Score: 15\n", + "Iteration: 16, Score: 16\n", + "Iteration: 17, Score: 14\n", + "Iteration: 18, Score: 29\n", + "Iteration: 19, Score: 16\n", + "Iteration: 20, Score: 19\n", + "Iteration: 21, Score: 20\n", + "Iteration: 22, Score: 20\n", + "Iteration: 23, Score: 26\n", + "Iteration: 24, Score: 10\n", + "Iteration: 25, Score: 16\n", + "Iteration: 26, Score: 39\n", + "Iteration: 27, Score: 16\n", + "Iteration: 28, Score: 36\n", + "Iteration: 29, Score: 15\n", + "Iteration: 30, Score: 9\n", + "Iteration: 31, Score: 24\n", + "Iteration: 32, Score: 11\n", + "Iteration: 33, Score: 26\n", + "Iteration: 34, Score: 12\n", + "Iteration: 35, Score: 20\n", + "Iteration: 36, Score: 14\n", + "Iteration: 37, Score: 36\n", + "Iteration: 38, Score: 19\n", + "Iteration: 39, Score: 27\n", + "Iteration: 40, Score: 27\n", + "Iteration: 41, Score: 19\n", + "Iteration: 42, Score: 14\n", + "Iteration: 43, Score: 23\n", + "Iteration: 44, Score: 14\n", + "Iteration: 45, Score: 39\n", + "Iteration: 46, Score: 25\n", + "Iteration: 47, Score: 24\n", + "Iteration: 48, Score: 62\n", + "Iteration: 49, Score: 144\n", + "Iteration: 50, Score: 60\n", + "Iteration: 51, Score: 11\n", + "Iteration: 52, Score: 21\n", + "Iteration: 53, Score: 33\n", + "Iteration: 54, Score: 30\n", + "Iteration: 55, Score: 64\n", + "Iteration: 56, Score: 30\n", + "Iteration: 57, Score: 14\n", + "Iteration: 58, Score: 50\n", + "Iteration: 59, Score: 42\n", + "Iteration: 60, Score: 15\n", + "Iteration: 61, Score: 56\n", + "Iteration: 62, Score: 24\n", + "Iteration: 63, Score: 31\n", + "Iteration: 64, Score: 60\n", + "Iteration: 65, Score: 38\n", + "Iteration: 66, Score: 43\n", + "Iteration: 67, Score: 31\n", + "Iteration: 68, Score: 68\n", + "Iteration: 69, Score: 26\n", + "Iteration: 70, Score: 110\n", + "Iteration: 71, Score: 14\n", + "Iteration: 72, Score: 57\n", + "Iteration: 73, Score: 45\n", + "Iteration: 74, Score: 17\n", + "Iteration: 75, Score: 22\n", + "Iteration: 76, Score: 71\n", + "Iteration: 77, Score: 54\n", + "Iteration: 78, Score: 54\n", + "Iteration: 79, Score: 46\n" ] } ], "source": [ - "optimizer = keras.optimizers.Adam(learning_rate=0.01)\n", - "huber_loss = keras.losses.Huber()\n", - "episode_count = 0\n", - "running_reward = 0\n", "\n", - "while True: # Run until solved\n", - " state = env.reset()\n", - " episode_reward = 0\n", - " with tf.GradientTape() as tape:\n", - " _,_,action_probs, rewards, critic_values = run_episode()\n", - " episode_reward = np.sum(rewards)\n", - " \n", - " # Update running reward to check condition for solving\n", - " running_reward = 0.05 * episode_reward + (1 - 0.05) * running_reward\n", - "\n", - " # Calculate discounted rewards that will be labels for our critic\n", - " dr = discounted_rewards(rewards)\n", - "\n", - " # Calculating loss values to update our network\n", - " actor_losses = []\n", - " critic_losses = []\n", - " for log_prob, value, rew in zip(action_probs, critic_values, dr):\n", - " # When we took the action with probability `log_prob`, we received discounted reward of `rew`,\n", - " # while critic predicted it to be `value` \n", - " # First we calculate actor loss, to make actor predict actions that lead to higher rewards\n", - " diff = rew - value\n", - " actor_losses.append(-log_prob * diff)\n", - "\n", - " # The critic loss is to minimize the difference between predicted reward `value` and actual\n", - " # discounted reward `rew`\n", - " critic_losses.append(\n", - " huber_loss(tf.expand_dims(value, 0), tf.expand_dims(rew, 0))\n", - " )\n", - "\n", - " # Backpropagation\n", - " loss_value = sum(actor_losses) + sum(critic_losses)\n", - " grads = tape.gradient(loss_value, model.trainable_variables)\n", - " optimizer.apply_gradients(zip(grads, model.trainable_variables))\n", - "\n", - " # Log details\n", - " episode_count += 1\n", - " if episode_count % 10 == 0:\n", - " template = \"running reward: {:.2f} at episode {}\"\n", - " print(template.format(running_reward, episode_count))\n", - "\n", - " if running_reward > 195: # Condition to consider the task solved\n", - " print(\"Solved at episode {}!\".format(episode_count))\n", - " break\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's run the episode and see how good our model is:" - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "metadata": {}, - "outputs": [], - "source": [ - "_ = run_episode(render=True)" + "actor = Actor(state_size, action_size).to(device)\n", + "critic = Critic(state_size, action_size).to(device)\n", + "run_episode(actor, critic, n_iters=100)" ] }, { @@ -622,7 +669,7 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ diff --git a/lessons/6-Other/22-DeepRL/README.md b/lessons/6-Other/22-DeepRL/README.md index f5c631d0..26e3f691 100644 --- a/lessons/6-Other/22-DeepRL/README.md +++ b/lessons/6-Other/22-DeepRL/README.md @@ -83,6 +83,7 @@ After running one of those algorithms, we can expect our CartPole to behave like Continue your learning in the following notebooks: * [RL in TensorFlow](CartPole-RL-TF.ipynb) +* [RL in PyTorch](CartPole-RL-PyTorch.ipynb) ## Other RL Tasks