{ "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": [ "# 07. N-Step Learning\n", "\n", "[R. S. Sutton, \"Learning to predict by the methods of temporal differences.\" Machine learning, 3(1):9–44, 1988.](http://incompleteideas.net/papers/sutton-88-with-erratum.pdf)\n", "\n", "Q-learning accumulates a single reward and then uses the greedy action at the next step to bootstrap. Alternatively, forward-view multi-step targets can be used (Sutton 1988). We call it Truncated N-Step Return\n", "from a given state $S_t$. It is defined as,\n", "\n", "$$\n", "R^{(n)}_t = \\sum_{k=0}^{n-1} \\gamma_t^{(k)} R_{t+k+1}.\n", "$$\n", "\n", "A multi-step variant of DQN is then defined by minimizing the alternative loss,\n", "\n", "$$\n", "(R^{(n)}_t + \\gamma^{(n)}_t \\max_{a'} q_{\\theta}^{-}\n", "(S_{t+n}, a')\n", "- q_{\\theta}(S_t, A_t))^2.\n", "$$\n", "\n", "Multi-step targets with suitably tuned $n$ often lead to faster learning (Sutton and Barto 1998)." ] }, { "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 collections import deque\n", "from typing import Deque, 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 for N-step learning\n", "\n", "There are a little bit changes in Replay buffer for N-step learning. First, we use `deque` to store the most recent n-step transitions.\n", "\n", "```python\n", " self.n_step_buffer = deque(maxlen=n_step)\n", "```\n", "\n", "You can see it doesn't actually store a transition in the buffer, unless `n_step_buffer` is full.\n", "\n", "```\n", " # in store method\n", " if len(self.n_step_buffer) < self.n_step:\n", " return ()\n", "```\n", "\n", "When the length of `n_step_buffer` becomes equal to N, it eventually stores the N-step transition, which is calculated by `_get_n_step_info` method.\n", "\n", "(Please see *01.dqn.ipynb* for detailed description of the basic replay buffer.)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "class ReplayBuffer:\n", " \"\"\"A simple numpy replay buffer.\"\"\"\n", "\n", " def __init__(\n", " self, \n", " obs_dim: int, \n", " size: int, \n", " batch_size: int = 32, \n", " n_step: int = 3, \n", " gamma: float = 0.99,\n", " ):\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", " # for N-step Learning\n", " self.n_step_buffer = deque(maxlen=n_step)\n", " self.n_step = n_step\n", " self.gamma = gamma\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", " ) -> Tuple[np.ndarray, np.ndarray, float, np.ndarray, bool]:\n", " transition = (obs, act, rew, next_obs, done)\n", " self.n_step_buffer.append(transition)\n", "\n", " # single step transition is not ready\n", " if len(self.n_step_buffer) < self.n_step:\n", " return ()\n", " \n", " # make a n-step transition\n", " rew, next_obs, done = self._get_n_step_info(\n", " self.n_step_buffer, self.gamma\n", " )\n", " obs, act = self.n_step_buffer[0][:2]\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", " return self.n_step_buffer[0]\n", "\n", " def sample_batch(self) -> Dict[str, np.ndarray]:\n", " indices = np.random.choice(\n", " self.size, size=self.batch_size, replace=False\n", " )\n", "\n", " return dict(\n", " obs=self.obs_buf[indices],\n", " next_obs=self.next_obs_buf[indices],\n", " acts=self.acts_buf[indices],\n", " rews=self.rews_buf[indices],\n", " done=self.done_buf[indices],\n", " # for N-step Learning\n", " indices=indices,\n", " )\n", " \n", " def sample_batch_from_idxs(\n", " self, indices: np.ndarray\n", " ) -> Dict[str, np.ndarray]:\n", " # for N-step Learning\n", " return dict(\n", " obs=self.obs_buf[indices],\n", " next_obs=self.next_obs_buf[indices],\n", " acts=self.acts_buf[indices],\n", " rews=self.rews_buf[indices],\n", " done=self.done_buf[indices],\n", " )\n", " \n", " def _get_n_step_info(\n", " self, n_step_buffer: Deque, gamma: float\n", " ) -> Tuple[np.int64, np.ndarray, bool]:\n", " \"\"\"Return n step rew, next_obs, and done.\"\"\"\n", " # info of the last transition\n", " rew, next_obs, done = n_step_buffer[-1][-3:]\n", "\n", " for transition in reversed(list(n_step_buffer)[:-1]):\n", " r, n_o, d = transition[-3:]\n", "\n", " rew = r + gamma * rew * (1 - d)\n", " next_obs, done = (n_o, d) if d else (next_obs, done)\n", "\n", " return rew, next_obs, done\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-step learning 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", "\n", "We use two buffers: `memory` and `memory_n` for 1-step transitions and n-step transitions respectively. It guarantees that any paired 1-step and n-step transitions have the same indices (See `step` method for more details). Due to the reason, we can sample pairs of transitions from the two buffers once we have indices for samples.\n", "\n", "```python\n", " def update_model(self) -> torch.Tensor:\n", " ...\n", " samples = self.memory.sample_batch()\n", " indices = samples[\"indices\"]\n", " ...\n", " \n", " # N-step Learning loss\n", " if self.use_n_step:\n", " samples = self.memory_n.sample_batch_from_idxs(indices)\n", " ...\n", "```\n", "\n", "One thing to note that we are gonna combine 1-step loss and n-step loss so as to control high-variance / high-bias trade-off.\n", "\n", "(Search the comments with *N-step Leaning* to see any difference from DQN.)" ] }, { "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", " use_n_step (bool): whether to use n_step memory\n", " n_step (int): step number to calculate n-step td error\n", " memory_n (ReplayBuffer): n-step replay buffer\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-step Learning\n", " n_step: int = 3,\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_step (int): step number to calculate n-step td error\n", " \"\"\"\n", " obs_dim = env.observation_space.shape[0]\n", " action_dim = env.action_space.n\n", " \n", " self.env = env\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", " # memory for 1-step Learning\n", " self.memory = ReplayBuffer(\n", " obs_dim, memory_size, batch_size, n_step=1, gamma=gamma\n", " )\n", " \n", " # memory for N-step Learning\n", " self.use_n_step = True if n_step > 1 else False\n", " if self.use_n_step:\n", " self.n_step = n_step\n", " self.memory_n = ReplayBuffer(\n", " obs_dim, memory_size, batch_size, n_step=n_step, gamma=gamma\n", " )\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", " \n", " # N-step transition\n", " if self.use_n_step:\n", " one_step_transition = self.memory_n.store(*self.transition)\n", " # 1-step transition\n", " else:\n", " one_step_transition = self.transition\n", "\n", " # add a single step transition\n", " if one_step_transition:\n", " self.memory.store(*one_step_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", " indices = samples[\"indices\"]\n", " loss = self._compute_dqn_loss(samples, self.gamma)\n", " \n", " # N-step Learning loss\n", " # we are gonna combine 1-step loss and n-step loss so as to\n", " # prevent high-variance.\n", " if self.use_n_step:\n", " samples = self.memory_n.sample_batch_from_idxs(indices)\n", " gamma = self.gamma ** self.n_step\n", " n_loss = self._compute_dqn_loss(samples, gamma)\n", " loss += n_loss\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(\n", " self, \n", " samples: Dict[str, np.ndarray], \n", " gamma: float\n", " ) -> 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(next_state).max(\n", " dim=1, keepdim=True\n", " )[0].detach()\n", " mask = 1 - done\n", " target = (reward + 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 = 2000\n", "batch_size = 32\n", "target_update = 100\n", "epsilon_decay = 1 / 2000\n", "\n", "# train\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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", "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/n_step_learning/rl-video-episode-0.mp4.\n", "Moviepy - Writing video /Users/jinwoo.park/Repositories/rainbow-is-all-you-need/videos/n_step_learning/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/n_step_learning/rl-video-episode-0.mp4\n", "score: 200.0\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r" ] } ], "source": [ "video_folder=\"videos/n_step_learning\"\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/n_step_learning/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": 4 }