diff --git a/README.md b/README.md index 2c23686f5d0e3af5fbe0f8da734358b6a4b4107a..c727b10519cf8cfb5910a7ccb92d12e82988fbcc 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ Assignments for [Berkeley CS 285: Deep Reinforcement Learning, Decision Making, [对应CSDN博客地址 点击此处](https://blog.csdn.net/qq_39537898/article/details/117064479) +## hw3 +2021/6/9 完成了第三次次作业的solution.md +[详情请点击此处见solution.md](hw3/solution.md) + +[对应CSDN博客地址 点击此处](https://blog.csdn.net/qq_39537898/article/details/117673108) diff --git a/hw1/solution.md b/hw1/solution.md index 49532a1073228b62b3a337c8fd691522591ca466..30f327517be0df51bc2111bd1564442f1795e051 100644 --- a/hw1/solution.md +++ b/hw1/solution.md @@ -23,11 +23,19 @@ A. (Recommended) Install with conda: ``` conda create -n cs285 python=3.6 ``` +温馨提示 建议装3.7,详情见hw3的[solution](../hw3/solution.md) +``` +conda create -n py37 python=3.7 +``` + 3. activate the environment (do this every time you open a new terminal and want to run code): ``` source activate cs285 ``` +``` +conda activate py37 +``` 4. Install the requirements into this conda environment ``` diff --git a/hw2/README.md b/hw2/README.md index 0e481c044bcc27fc807bf44a259817c60428721f..383e4456dee6f8a235ab87f31b7e390c18a5860e 100644 --- a/hw2/README.md +++ b/hw2/README.md @@ -1,3 +1,6 @@ +# Solution File +直接跳过看结果请点击[solution.md](solution.md) + ## Setup You can run this code on your own machine or on Google Colab. diff --git a/hw2/solution.md b/hw2/solution.md index eded00f868269ee2f8cd735a4a419c8fd8b99fad..ea091ea9d9e56d3211f41b17159174e2e2de627f 100644 --- a/hw2/solution.md +++ b/hw2/solution.md @@ -7,7 +7,7 @@ ## 编译运行前 使得cs285用在 ``` -cd +cd $ pip install -e . ``` diff --git a/hw3/README.md b/hw3/README.md index b6a7c9ce11e2de6f7d6e437745a4897f46d6ef4f..64f1be8440b7a73111c43b4f41efeee2ac7f7dd8 100644 --- a/hw3/README.md +++ b/hw3/README.md @@ -1,3 +1,6 @@ +# Solution File +直接跳过看结果请点击[solution.md](solution.md) + ## Setup You can run this code on your own machine or on Google Colab. diff --git a/hw3/cs285/DataViz.ipynb b/hw3/cs285/DataViz.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..7158ecbc0205f55ab7602c4ac416d2d4619224f2 --- /dev/null +++ b/hw3/cs285/DataViz.ipynb @@ -0,0 +1,1489 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/udi/anaconda3/envs/cs285/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:458: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", + " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", + "/home/udi/anaconda3/envs/cs285/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:459: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", + " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", + "/home/udi/anaconda3/envs/cs285/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:460: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", + " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", + "/home/udi/anaconda3/envs/cs285/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:461: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", + " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", + "/home/udi/anaconda3/envs/cs285/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:462: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", + " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", + "/home/udi/anaconda3/envs/cs285/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:465: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", + " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n" + ] + } + ], + "source": [ + "import os\n", + "import tensorflow as tf\n", + "import glob\n", + "import pandas as pd\n", + "import seaborn as sns\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "%matplotlib inline\n", + "\n", + "figsize=(5.7, 3)\n", + "export_dir = os.path.join('../../image')\n", + "\n", + "sns.set_theme()\n", + "sns.set_context(\"paper\")\n", + "\n", + "\n", + "# From read_results.py\n", + "def get_section_results(file):\n", + " \"\"\"\n", + " requires tensorflow\n", + " \"\"\"\n", + " X = []\n", + " Y = []\n", + " for e in tf.train.summary_iterator(file):\n", + " for v in e.summary.value:\n", + " if v.tag == 'Train_EnvstepsSoFar':\n", + " X.append(v.simple_value)\n", + " elif v.tag == 'Train_AverageReturn':\n", + " Y.append(v.simple_value)\n", + " return X, Y\n", + "\n", + "data_dir = os.path.join('data')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 1" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Train_EnvstepsSoFarConfigvalue
01.0Train_AverageReturn480.655731
110001.0Train_AverageReturn402.399994
220001.0Train_AverageReturn379.799988
330001.0Train_AverageReturn430.100006
440001.0Train_AverageReturn407.200012
............
93930001.0Train_BestReturn1833.900024
94940001.0Train_BestReturn1833.900024
95950001.0Train_BestReturn1833.900024
96960001.0Train_BestReturn1833.900024
97970001.0Train_BestReturn1833.900024
\n", + "

197 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " Train_EnvstepsSoFar Config value\n", + "0 1.0 Train_AverageReturn 480.655731\n", + "1 10001.0 Train_AverageReturn 402.399994\n", + "2 20001.0 Train_AverageReturn 379.799988\n", + "3 30001.0 Train_AverageReturn 430.100006\n", + "4 40001.0 Train_AverageReturn 407.200012\n", + ".. ... ... ...\n", + "93 930001.0 Train_BestReturn 1833.900024\n", + "94 940001.0 Train_BestReturn 1833.900024\n", + "95 950001.0 Train_BestReturn 1833.900024\n", + "96 960001.0 Train_BestReturn 1833.900024\n", + "97 970001.0 Train_BestReturn 1833.900024\n", + "\n", + "[197 rows x 3 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def get_section_results_(file):\n", + " \"\"\"\n", + " requires tensorflow\n", + " \"\"\"\n", + " X = []\n", + " Y = []\n", + " Z = []\n", + " for e in tf.train.summary_iterator(file):\n", + " for v in e.summary.value:\n", + " if v.tag == 'Train_EnvstepsSoFar':\n", + " X.append(v.simple_value)\n", + " elif v.tag == 'Train_AverageReturn':\n", + " Y.append(v.simple_value)\n", + " elif v.tag == 'Train_BestReturn':\n", + " Z.append(v.simple_value)\n", + " return X, Y, Z\n", + "\n", + "def read_q1_data(question):\n", + " full_data = pd.DataFrame()\n", + " for folder in os.listdir(data_dir):\n", + " split = [s.strip() for s in folder.split('_')]\n", + " if 'MsPacman-v0' in split and question in split:\n", + " \n", + " logdir = os.path.join(data_dir, folder, 'events*')\n", + " eventfile = glob.glob(logdir)[0]\n", + " \n", + " X, Y, Z = get_section_results_(eventfile) # Y is Train_AverageReturn\n", + " X.pop()\n", + " full_data = pd.DataFrame({'Train_EnvstepsSoFar': X, \n", + " 'Config': 'Train_AverageReturn',\n", + " 'value': Y})\n", + " X.pop()\n", + " data = pd.DataFrame({'Train_EnvstepsSoFar': X, \n", + " 'Config': 'Train_BestReturn',\n", + " 'value': Z})\n", + " full_data = full_data.append(data)\n", + " \n", + " return full_data\n", + "\n", + "full_q1_data = read_q1_data('q1')\n", + "full_q1_data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=figsize)\n", + "ax = sns.lineplot(data=full_q1_data, x='Train_EnvstepsSoFar', y='value', hue='Config')\n", + "ax.set(xlabel='Training Steps', ylabel='Reward')\n", + "plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))\n", + "plt.savefig(os.path.join(export_dir, 'hw3_q1.png'), dpi=200, bbox_inches='tight')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 2" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ConfigTrain_EnvstepsSoFarTrain_AverageReturn
0dqn1.0-225.694712
1dqn10001.0-195.819229
2dqn20001.0-175.776810
3dqn30001.0-158.668772
4dqn40001.0-145.344304
............
44doubledqn440001.080.762199
45doubledqn450001.069.649890
46doubledqn460001.079.524618
47doubledqn470001.073.411114
48doubledqn480001.068.117202
\n", + "

98 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " Config Train_EnvstepsSoFar Train_AverageReturn\n", + "0 dqn 1.0 -225.694712\n", + "1 dqn 10001.0 -195.819229\n", + "2 dqn 20001.0 -175.776810\n", + "3 dqn 30001.0 -158.668772\n", + "4 dqn 40001.0 -145.344304\n", + ".. ... ... ...\n", + "44 doubledqn 440001.0 80.762199\n", + "45 doubledqn 450001.0 69.649890\n", + "46 doubledqn 460001.0 79.524618\n", + "47 doubledqn 470001.0 73.411114\n", + "48 doubledqn 480001.0 68.117202\n", + "\n", + "[98 rows x 3 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def read_q2_data(question):\n", + " full_data = pd.DataFrame()\n", + " for folder in os.listdir(data_dir):\n", + " split = [s.strip() for s in folder.split('_')]\n", + " if 'LunarLander-v3' in split and question in split:\n", + " config_list = split[split.index(question)+1] # get dqn/ddqn after q2\n", + " logdir = os.path.join(data_dir, folder, 'events*')\n", + " eventfile = glob.glob(logdir)[0]\n", + "\n", + " X, Y = get_section_results(eventfile) # Y is Train_AverageReturn\n", + " X.pop()\n", + " data = pd.DataFrame({'Config':config_list,\n", + " 'Train_EnvstepsSoFar': X, \n", + " 'Train_AverageReturn': Y})\n", + " \n", + " if full_data.empty:\n", + " full_data = data\n", + " elif not (full_data['Config'].str.contains(config_list)).any():\n", + " full_data = full_data.append(data)\n", + " else:\n", + " full_data['Temp_Return'] = data.loc[:,'Train_AverageReturn']\n", + " \n", + " # for another config set temp to zero\n", + " full_data.loc[full_data['Config']!=config_list,'Temp_Return'] = 0\n", + " \n", + " # add temp adn return together\n", + " full_data['Train_AverageReturn'] = full_data.drop('Train_EnvstepsSoFar', axis=1).sum(axis=1)\n", + "\n", + " del full_data['Temp_Return']\n", + " full_data.loc[:, 'Train_AverageReturn'] /= 3\n", + "\n", + " return full_data\n", + "\n", + "full_q2_data = read_q2_data('q2')\n", + "full_q2_data" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAADWCAYAAADPRcUoAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzt3Xd4VFX6wPHv1PQCSegllHDoVREQRAVRFEVX/dm7rr3supa1ly2u7q664uq66rr2FXtXikgXlN4OgRBqKElITyZT7u+PO8GAIZkkM5lJ5v08Tx4md+7ce84dMu/ce895X4thGAghhBBHYw13A4QQQkQ2CRRCCCHqJYFCCCFEvSRQCCGEqJcECiGEEPWSQCGEEKJeEiiEEELUSwKFEEKIekmgEEIIUS8JFEIIIeolgUIIIUS97OHasVLKAcwDBgHXaq3fV0o9ApwPHAD2aq0v9K87DbgfMIDbtdbLA9yNJLISQkQjSzA3FrZAAXiA84Drj1j+sNb6/ZpflFI24HHgBCAZ+B8wPtCdHDhQ2uiGpabGU1RU0ejXtVbS37Yv2voczf3NyEgK+vbDdulJa21orfPqeOoBpdQCpdRF/t+zgM1a61Kt9W7AoZSKbbmWCiFEdAvnGUVdntNaP6KUSgHmKqUWAu2Bg7XWKfIv2xPIBlNT4xvdCJvN2qTXtVbS37Yv2vos/Q2uiAoUWusC/7/FSqk5wGAgF0ittVoKUBjoNmuffvp8PoqLC/B6PfW+xm634vH4Am94K1dff202OykpaVitbWfcQ7RdloDo63M09zcUl54iKlAopVL8QcIOjAVeBnKAfkqpBCAJ8Gitq5qy/eLiAmJj44mLS6h3PZvNitcbPYGivv5WVpZTXFxAu3YZLdwqIUSkCGugUEq9BxwDlCmlRgPtlVIDARvwttZ6s3+9R4DZmKOYftPU/Xm9ngaDhDhcXFwC5eUl4W6GaCSvz8eu/eVs2V1M7t4SendLpX+3FDqnyf9/0XiWNl4K1ag96ik/P4/09M4NvkjOKA4X6HFrLdriZYmKKjfZu4rZsruYrbuLyckrwe3x0S0jkZ4dk9hTWEHO7mI6p8UzPCudEVkZ9O6SjNViweP1UVxWzcEyFwdLXRSVuUhNjKFHx0QyUuOwWoI60rJFtMX3uD51XHpqM8Nj26SCgnz+8Y+/sXHjBhITk2jfvj233XYnPXr0bNR2Vq9eyVNP/Rm73c5TTz3Ds8/+lT/84ckQtVq0NmWVbjbvLELvKELvPMjOfWXExdjp2y2FAT3bcea4TDI7JxMXY/6Jp6bGk7OjkJXZ+azKPsC3y3YSH2vHarVQUlaNAdisFlITY0hJdFJYUkVRWTVxMTa6d0iiR0cz4Izsl3FomyJ6yBlFHZp6RmEYBjfccDVTp57B2WefB0B29mYqKsoZNmxEo7b11FN/YujQ4Zx66umNbkdjyRlF67H7QBmvfbWJrXtKSIxz0K97Kqp7KqpHKt0yErFa6/4ieWSfK6o8bNxeiNVqoV1SDO2SYkmKdxx29lBSXs2OfaVs31fK9n1lbN1djNUCV50+gIGZ7UPe16MxDB/ePI178yJsnbJw9p/4i3Va83vcFHJG0YqsWPEjdrv9UJAAyMrqh2EYPP/8syxdugiLxcIVV1zDpElTWLHiR1599SVSU1PJydmKUgN46KHH+fzzT5g7dzbLli1l6dLF/PrXN3H33XfwxhvvUVVVxR//+Ajbtm2le/ee5Ocf4M4776F//4Fh7LkINcMwWLAmj7dnbeaY/h24Ymp/uqQnNPmyUHysnVGqQ73rJCc4Gdw7jcG90wDweH18snAbT7+3mhOHd+W8k/oQ47A1af9N4asowq0X4tbzMcoLsXcfimvhG+Cpxjn4lBZrRzSSQBFE5od9/18s//77uWRna1577R2Ki4u49trLGTZsJADZ2Zo33niP9PQMbrzxGtasWc2ZZ57NmjWrGDduPCedNJm8vJ+njHz44UySkpJ4882Z5ORs4aqrLmmx/onwqHR5eP0bzarsfC4/TTFucHjO7uw2K+dO7MPwvum8/MVG1r1awDXTBtK3a0pI9+vdm0316i/x7FiNtV0XnINPwdF3LJbYRDy5K6mcPQMsFpyDJoe0HdGs7QyOj2Br1qxi8uRTsdlstG+fxogRI9m0aT0AAwYMokOHjlitVrKy+rF3b/3zCNeuNbcF0Lt3X/r06Rvy9ovw2b63lEdfW87uA+U8dOUxYQsStfXpmsIjVx3LkN5pPPHmCt6ftxV3iOYdeXaspuKLv0BMAvHTHyD+3MdxDj4FS2wiAPbMEcROvgnXkneo3jA3JG0QckYRVL169WbevDmNeo3T6Tz02Gq14vV6g90s0cr4DIN9hRWszM7n4wU5TBjahQtO7ouzBS/zNCTGYePiU/oxIiudV7/cyPrcQm6cPogO7YI3O9izYzWVs54j5tjzcQ499ajrOTJHwck3UDX3RbBYcQ44MWhtECY5owiiUaOOpbq6mk8++fDQsi1bsklMTGLu3Fl4vV4OHjzIqlUrGTBgUJP2MWTIMObOnQXAtm05bN26JShtF+FTXObiJ32A9+dt5al3VnLrM/O5/98/MH/VHn595iAuO1VFVJCobUBmex69ejTpybE88p/lLNu4LyjbDTRI1HD0PpbYk6/HtegNqjd9H5Q2iJ/JGUUQWSwW/vznv/Lss3/jrbf+i9MZQ+fOnbnttjuprKzkyisvwmKxcNNNt5GWls727bmN3sc555zPH//4MJdeej49emTSq1cfEhISg98ZEXKGYTBr+U5mzttKfKydXp2TUd1TOe24HmR2SiIp3tnwRiJAfKyDm84ZzNwVu3n58w1s2n6QCydlNTm4NTZI1HD0Hg2GQdXclyhPToIuI5u0f/FLMjy2DpE84c7r9eLxeIiJiWH37l3cccdNvP32BzgcjiZvU4bHtryySjevfrERvbOIq6b2Z5TKwBKCiW2Gx4UndwXt+g2jzBf6JHnb95bywifrcNqt3Hj24EbPBG9qkKitesNcqpfNJP68P2BNTGvSNlqbUA+PlUBRh0gOFBUV5dx66w14PB7A4IYbbmXs2OObtU0JFC1ry+5iXvxkHSkJTm6YPpiM1Lig78OorqR6w3e4136N4anGYrHgPO4CHP0nhiQg1VZ7lNY1ZwzgmP71D8M1fF6Mkv148jSuxW82K0iAeabmmf0s7mo3caf/LuT9jQQSKJqnzQWKUJBA0TJ8hsE3y3bw4fc5TBrVjfNO7IPdZsXwecFiDegDzXCV4yvehyUmHktCeyz2wy9PGdUVVK+bTfXab7A443GOmIYj63ice1ZQOOc/2DJ6EXvCVViTQpvk0TAMvlu5m3dmZ3PhpCwmjep26Dlv/na8u9fjLdyNr3AXvqLd4PVgSWiHc9gZOAc3f5hroq2SvFd+S8zo83EOPLnZ24t0bXbC3VFKoaYDb2BmiZ2ttX7Ev25TS6EKEXZllW425BayYPUecveWcvM5QxielY5hGFRvmItr6btgsWJNSseSmI41yfyxxKdiVBTjK8rDV5yHrygPo7IE8zPA/IJniUvGkpiGNTENS0w87pzlWOJSiB17Mfa+Y7BYzfsECUNOxNU+i6oFr1E+8wFixlyAY8CJWCyhGc9isVg4eWQ32iXG8OKn6zlY6uJXEzJxr/qc6hWfYu3QC1v77jj6n4C1fTds7boeGvIaDPakNGLHXUrVwtexdxuMNbn+sxpRv0grhXoP8KrWeqZS6gt/JllNM0qhCtHSfIbBjn2lrNlawNqcAnL2lJAU72RI7/Y8MnUAaSmx+CqKqJr/H7x5m4kddymWxDR8ZfkYpfn4SvPxFOzAV16IJT4VW2pn7D2GYR16GtbUzliSMsBdha+sAKOsAF9ZAb7SAoyKImLHX4G992gsddQPsSa0I+7UO/BkL6Zq8Vt4ti7DkTUOS3IG1uQOWOLb1fm65hjRL4PfXTic1z5Ywojc1+hgLSZu6m+wdxsc1P3UxZ41Dvu2H6n6/hXipt0TsqAYDcIWKLTWBpCnlKq9eDzwkP/x55jBwYe/FCpQqpRyKKVim1qTQohQKC5zsT63kPXbzJ/SSjd9uqYwtE86l56i6N4x8VC6DXfuClzz/4O1XRcSznsca1J643cYk4AtJgHSejTqZRaLBUe/47F1G4Rr2Uyq136Dr+QAeKvBasOSlI41KQNrSkesKZ3Mn9ROWBLSmhxEenlzuTvlc7ZVpfJtygVc1aF/i3zwWCwWYiZcQfnM+3Gvm41zyJQW2GvbFGnDYxO01pX+x0VAL4JYCrWoyIrNFth/9kDXa6xLLjmft96aGZJtN0d9/bXb21ZZyWCUjTQMgw3bCvlp0z5WZeeTm1dCWkosw7MyuO7sIQzrm07iEcNbfdVVFM15jaoN80kZfyFJx04L+jf4o/lFn1Pj4ezbD/XFV16Mp3gfniL/z8E8PDlLqSrcg1FdCTYH9nadcKR3x9mhJ44OmTgzemJNbHfUeyuGx03R929RufIb2k24kAQ1mU9e+5G/vbeaq6cNoluHxJANAT7U39R4YqdcR+FX/6TdoNE42ncJyf7CLapKoQIVtc4WakqeHiRIpVA9Hl9AN6lDeTPbMIyIu1HeUH89Hl/Yh5MGU3NvZu8trOCtWZvRO4oY0LMdYwd25NopmWS49+Dbuxrv2hyKV1ZT7POB8fOPUVGMJS6Z+OkP4kvvSXFJy50UN9xnJyR0N3+6mpXDbIDTMDCqSv33SfbiKdxFdfYKvEs/hupKLLFJWNO6g80JHheGxwXuagyPC8NVjiUmnviz7sPXoQ924K4Lh/PSZxt46KUleH0GSfEOOqcl0Dktns5pCQzPSqdDEEaBHdbfzsOx9RjG/s9mEH/mfS0WnFtSVJVCBRYApwMfAlOB+4BsglQKNRx8Ph9/+MPD7N+/D6UGAOaM6j/96VFSUlKIjY1j4MDBXHzxZVxwwdmMGDGK7OzNTJo0hYsvvizMrY9uhs+De8N3VK+fjcXuxIhNYVeZnQ37vAxN68DVU3oQV74e787N+FZtp8oeg61TFrZOCktMPFgsYLGaI5qsNvNbeebIX4xUimQWiwVLXDLWuGTo/PNlYsMwzPsjBTvxFu4AnxfsMVjsMVgcMeZjRwy2Tv2wOH/+4I+PdXDH+cPweH3kF1eRV1DO3oIK8goqWLJ+LzO/28JJI7ty5rjMoJ5txIy/nIqZ91O9+gscw6ex50A52buLyd5VxJZdxfTv0Y4rT+/fKos0tYRIK4X6JPC6Uuq3wFyt9Xr/eo8QhFKotVVUuXG56/4W3ZgzihiHlfjYo092W7Dge5KSknjoocdZufInli1bwr/+NYM777yX/v0H8Kc/PXpo3cLCQm666Tbi4uK57LILJFCEiWEYeLevouqH/0F1Bc7h09hZ6GLjxlySLBWM62YhyZKDsWENRloPHFljsZ1wJdb23Q+NMmrrLBaL/35GOvbMxtVaATMTbaf28XRqHw9ZPy/fkFvIe99t4d5/LeWMsT2ZPKpbUNKXlPli2NTlbNTyN3lxQRmrKzrSNSOBrK4pnD62Jx9+n8NH83M4d2KfZu+rLQproNBa/18di6fWsd6nwKfB2q/X5+OuFxZT6Wp+Ar64GBv/uH0CtqOczu7cuZ1Bg4YAMHCgOdIjL28P/fsP8C8bREWFeVumY8dOJCebKZsdjkg72YsO3vztuJa+i3ffFpxDT8PT/1Re/CaHddsKmTZ2GuPG9MBhj45gEA4DM9vz0JXH8sP6fXw4fytzV+ziVyf0ZszATkctynQ0Hq+PdTmFLFybx+ot+aSnxHFe+kSuKJ6P/aIHScz4+X5Fl7QE/vruKjq0i2PC0LZ5H6M5ovLTyGa18tSN44J2RnG0IAHQvXsPVq5cwZQpU9m40Uwt3qlTZzZv3kS/fv3ZsGE9mZm9AfNKhQgPw1ONa9GbuDcvxN53DAkXPIHLkcIz763C4zH4w7Wjg5oZVRyd1WJh7OBOHNM/g9k/7eKtWdm8NSub3l2S6dMlmb5dU+jdJfmwM3nDMKhweSguq6aozMXm3bnMW7GLareX0QM6cPfFI/x1M8ZQNasE3/cvYEx/wLxMBvTrnsrVp/fnlS82kp4cS/+uCbgWv4WvLB97n+Nw9DoGS0zj0pG0JVEZKMC8VhofW/dzwbyZPX78RL77bg633PLrQ2cW119/M3/+82MkJ6eSkhLaoi+iYYbPS9WcF/AW5RF/9oPYMnrhqvby7HurqHb7uOuiESTGNT2Xlmgah93G1ON6MnFYV7bsLmLL7hKydxXz7fKdVFV76ZwWT6zTTkm5i+LyajxecxJijMNGVvdU/u+kPozq14EY5+FngLEnXkvFx49TNf8/xJ58/aFRW2MGdWL/wUr+9/Ei7ui0GIfNgq37UKp/+gTXojew9xhuzs3oPhSLLbo+OiWFRx1aMoXHl19+RlFRUVjvR0RzCg/DMHAt+A+eHWuIn/4A1qR0XG4vz85cTWmlm7svGtFqsrjWJ9z5rYLJ5zPYk1/O1j3FeLwGKQlOkhOcpCQ6SUlwEuu0N9hfX9Feyj96lJhR03EOPe3QcnfOckrn/Bvt7c6gi24nOSX5UI1uT/YS3DnLwWrFOWgyzpFnYrE2HDAMdxWGuwprfGqD6zZVm03hIUQkqP7pI9w5y4k/6z6sSelUu70898EaisuruefikW0iSLQ1VquFbh0S6dah6Sk/rKmdiDv5eiq/fQ5rWg9snRWuZTNxr5tF3Oj/4/u16Xz3aTZ3XTQch92GvcsA7F0GEHP8pXhyV+D64X94dq0j7uQbsCYfPW+We9tPuBa9gVFRjK37EBwDTsTeY1irG/QgZxR1kKSAh2urZxTV6+fgWvoOcaffhb2zwu3x8dyHazhQVMU9F48gNTEm3E0NmrZ0RhGIQPvr+ukT3OtmYW3XBV/JfmIn34y9UxZllW7+8PqP9O2awjVnDPjFpEJfVSlV817Bm6eJPeEqHH1Gs3TDXlzVXiYO74qvogjXojfx7FiFc9TZ2LsOxq3n485ejMUZh0OdYOa5ClIadDmjECIE3DnLcS1+m9hTbsLeWeHx+njh43XsL6zknktGtqkgIY7OOfJMfAd3Y7jKif/Vo1jjzXuGiXEObj13KI//dzn9e7Rj/NDDvyhZY5OIO/V23OtnU/XdSxzcvJI31vbC6oxhdMwWPMvew9auKwnnPo411XytLSOTmOP+D/fWH3BvnEf1yk+xdRuMo88Yc36NM/jp5oMloDMKpVRn4NdAJuaETQC01peHrGXBIWcUAYi2M4rYkm0cmPlHYsZdinPAiRiGwX+/3sTanELuu3QUaSlHGeXQiskZRdMsXJPHm7M0D15xLF3T6x71VLo7h/zPnyXGYWefK4Zeznzix17YYHZeb34u7s2L8GxdhlFdgb3HMOx9jjMvTTVyUmaknFF8CswE3sZM0idEq2B4qs30E4W78B3cjffgbsryNuEcPg3ngBMB+PqHHSzbuJ/ft9EgIZru+CGd2Lj9IC9+vI4HrjiGmCMm//kMg1cWl+KKvZBbe2nKd+bxNqdx08ATGty2LT0TW3omxpiL8OZtwrN1KVULXgOfl5jR5+Ec1Py6HMESaKCwaq2fDGlLhAgiz/aVuH54D1/xXjDAkpyBrV1XbO27kzrqFFzpgwD4cdN+Ppyfw63nDqV7M26OirbJYrFw2an9ePy/P/L2rM1cdfqAw57/aul2tu4u5pGrRhOfMpb4A2X89MoyDhRVBly50GK1Yu86EHvXgcQcfzneXeuCWpsjGALNjvWtUuoepdQApVTvmp+QtqyNuuyyuiajH90tt/yaoqKiw5bl5e3h7rvvCOj1jVm3LTA81VQtepPKWTOw9zmO+HMeJvHqF0m88EniTr2dmNHnEZ81GovFQs6eEv79+QYumpzF0D7RUVtZNF6s084N0wezdMM+lqzfe2j5pu0H+XjBNq47c9ChM9GuGYn07pLMgjV5TdqXxWbH3nM4to59g9L2YAn0jKKmUNC0WssMzHoRQkQE78HdVM15EcNdRfxZ92PrcPTvMvnFlfzjgzWcOLwrJ4/sdtT1hADo3iGRiyZn8frXmsxOScTH2Hnx0/VMHdPjF18yJgzrwicLt3H2+F6NTjsSqRoMFEopK/C01vrDFmhPizFc5Rie6jqfs9is+AK8mW2xO+ud2l9X9tjt23N56qk/4fP56Nkzk7vvvp+VK39i3rw5/Pa391BUVMQDD9zNjBkvAfDqq/8iN3cb7dq146GH/nDY9rOzNzNjxtN4vV569OjJXXfdR2VlJY88ch/V1dV07frzh+CqVSt49tm/kpHRETCYOnUa/fsP5JFH7qNz565s27aVyy67ismTm17YPhwMw8C9cR6uJe9g7zWK2PGX1zuCpLzKzbMz19C7czIXnBxZ39xE5Jo4rAubth/khY/Xkxhnp0taPNPH9/rFesf278A7s7NZt62wzZypNhgotNY+pdTvMVN/twilVDlQUxf7CeB74DWgC7AOuFlr3eSb6obPS9nbvwN3ZcMrN8QRR+IVM446gaau7LEvvPAPbrnlN/TvP4C//vUJFi78noSEo1+THDVqNL/97T0888xfWbjwe/r163/ouX/842888sgfSUtL57nnnmbZsqXk5uYwYsQxXHTRpXz11ed8991sAJ5//lmefPIZ0tMzuP32Gw9to7CwkBkz/k15eTl33nlrqwgUNWmuvQXb8WxehGf3BmJPuBJH1rh6X+fx+vjHWyuw2Sz8+qyBbeYbnwg9i8XCFaf159HXlpNXUM0jVx1bZ563uBg7xw7owILVe6InUPjNV0o9ijny6dCYM611TkhaBdu01ifW/KKUuhn4UWv9lFLqeeA04MumbtxitZF48V+PekbRmOGxFruz3lmWDWWPHTJkKDt2bD/0HJgfgrUNHDjo0L87d+44LFBs27aVhx++D4DKykp69+7Dzp07mDJl6qF91gQKl6uKjAyzyPyAAYMObaNXr944HA5SU1OprnYF1O+WZBgGRsl+vPu34i3YgS9/O96CHeAqxxKXjK1DHxLOfQxrcod6t+PzGbz8+QZ27S/l95eOItYp04hE48TF2Ln7ohG4vT5S6plrc8KwLvzlrRWUlFeTnND6Z/cH+pcy2v/vybWWhfIeRXel1HxgJ3AbMAGoKdzwOTCRZgQKAEtMwlEvGVltVowgzaM4WvbYTZs20r//ANauXcPo0WNISkrmwIH9AGRn68O2sWnTBjIyOrBp0waGDh1+2HO9e/flsceeIDXVzCPj8XgoLS1h48b1DB06nA0b1h1aNyYmhvz8fNLS0g7tPxIZ1ZV4D2zDu28L3v1b8e3biuEqw5KYZg4p7NIf59BTsab1xBKfetRSnLX5DIPXvt6E3lHEH28cR7y97VU5Ey2jfXLDQ6j7dEmmQ7s4Fq/by2nHNa6ueSQKKFBorSeEuiFH6KO1zldKXQ38kcPrZtfUzA5IuGtmT5x4EvPmzeXWW69n8OAhWCwWbr75dv7yF/NeQ/fuPZk48UQsFgtWq5Xbb7+BQYPM9Ww2KxaLhVWrVjBz5rukprZj4sSTDgUUm83KHXf8jkcfvR+v14vFYuG3v72bs88+lwcfvJclSxbRq1fvQ+vecssd3HXX7WRkZJCYmIDV+vPxqPm3Zr+1tWTN7PL1Cyj86p9YbHacnfoS3yWLmFGn4uzSF1tC05KqGYbBK5+tZ/WWfB779Vi6d0yOqgmVEPqaypEmEvp76phMZi3bwQVTVEBfZpoj1P0NdGb2Y3Ut11o/FPQWHb7feOA7IBd4WGu9SSl1GnCi1vreADYhM7OP4pVX/kXv3n046aTJETMz27NrHZVfP03M8ZfhUBOCljjtg+/NAjh3XTSCzE7JUTdLGWRmdjiUVFRz54xF3H3xCLK6hS5zLIR+ZnagX5u31/rZC4wCOgazITWUUglKqZpPiImYNbPnY9bSxv/vglDsW4SPNz+XylkzcI46B+eAE4MWJD5bnMusH3fym/OHk9kpOSjbFCIQyfFORmSls2D1L+dUeLw+VmXnM2/lbnbtL8MX4clZA7309Ert35VSLxK6D+v+wMtKqRLABVwL5AOv+e9bbAS+CtG+o8Y111wf7iYc4ivZT+VXf8eRdTzO4WcEbbvfLt/JZ4tyueP8ofTtJgWiRMubMKwLz3+0losmZxEXY2fHvlIWrd3L0g17cXt8tE+O5fVvNPExdvp2SyGrWwpZ3VLp1TkZRwTdRwsoUPjnUtSwAsOB+oeYNJHW+iegrmrtjZvSLFoFX2UJFV/9DVunfsSMuyQo13KLy1y8990Wlm3cz82/GsLAzIBvaQkRVIMy25MY5+C1rzaRV1DB7gNlDMxsx4WTshjZL4MYh42ySjdbdxeTvauY1VsL+GThNiYM7cJlp6pwN/+QQEc9bccc5QTg9f9+49FXj0w2m53KynLi4qK39m1jVVaWYwtR2UfD7aLy62ewxqUQe9KvsdRTezwQXp+PuT/t5uOFOXTNSOTBK46hR8ekILVWiMazWi1MOaY7C9bmMWZgR8YOGvqLUVOJcQ6G9U1nWN90ANweb8hvfjdWoJ8AWVrrqtoLlFKtLmF/SkoaxcUFlJeX1Lue3W7F42nbN7Nrq6+/NpudlJTgTxoyfB4q5/wTPC7iTr+z0WmVj7R5ZxFvfqspKa/m4sn9GDe4U8T9sYnoNGV0D6aMDnyIrMMeedXvAg0Ui4GRRyxbUseyiGa1WmnX7uhlC2tEwoiJltTS/TU8Lipn/xNfwU7ip99fbwqUhlRVe3jz280sXb+Pk0Z25ZwJvYiPdQSxtUKIegOFUioT6AMkKqVqT7ZLBiRxv2g0X1UplV8/A+5K4qff36xSkG6Pl+c+WEtJeTUPXSmXmYQIlYbOKEYAvwLSgKtqLS8FImfYjGgVfKX5VH75VyxxycSdeV+zcu6bpUvXU1hSxb2XjKw3nYIQonnqDRRa64+Aj5RSY7XWS1qoTaIN8hbspPKrv2HL6EXspBubdU/CZxi8+sVGduwv5feXjJIgIUSIBTrMxK2UWqaU2gaglBqqlPpbCNsl2hDPnk1UfPYn7D2GE3vKLc0KEoZh8Oa3m9mQW8jvLhwhpUuFaAGBBooZwLmYeZYbqVmKAAAeqElEQVTQWq8BIj8XtQgrw12Fa8UnVH71V5xDTiVmwhXNmnFtGAbvz9vKsg37+O0Fw+nUPnpyFwkRToGOerJorXcqddgEEG8I2iPaAMPrwb1pHtUrPgVHHLEn34Cj1zHN3u4XS7Yzd8Vu7rxwuNy4FqIFBRoospVSpwMopdKBW4CVIWuVaJUMw4dn6w+4ln8Inmqco87G0f8ELNbmTdirdHl4d042S9bv4/bzh9K3q6TjEKIlBfoXfAPwMGZGwtn+n1tC1SjR+nj2bsa16E18JQdwDj8d5+ApWBzNv8m8IbeQ/3y5kbgYO/dfNoqeneRMQoiWFmhSwDLgrtrLlFIdgbJQNEq0HkZ1Ba5l7+PeOA/HoEnEn3F3s4a91qiq9jBz3lbmr9rD1DE9OOv4XtiDVCNECNE4DQYKpdRooCuwUGt9QCk1GPgdZrW7FivdpJS6DnMuRzVwdQjLsIoAeXJXUrXodSwxCcRPfwBbh95B2e7mnUW88sUG7DYr9102il6dJT24EOHU0Mzsp4DpwGrgQaXULOBy4AlaMCmgUqo9Zrrx4zEnAT6BZJMNG19FEa7Fb+HJXYlz5Fk4h52OJQiJAwtLqvhoQQ5L1u1jyrHdOeeEXhGZ90aIaNPQX/c0YKjWukop1Q7YAQzUWu8MfdMOMxqYp7X2AMvVEcOvRMvx7s2m4uunsbXvRvx5j2FL7dLsbVZUefhy6XZm/biT3p2Tuf9yOYsQIpI0FCgqa7LGaq0PKqWywxAk4PCa2RD4/I8m1ZGNhHq7LSnQ/nory9j33YskDplI6slXYLE0756B2+Pjm6W5zJybTWpiDHddOopRqkOrry8ciaKtz9Lf4GooUGT5q8qBOeKp5ncLYGitTwhZyw53EBha6/eA53A0JSuqZI/9JcMwqJr1PEZsMgw/l+LiqnrXb8j6bYW8/s0mqj0+zp3Yh+OHdMJmtVJcXNms7QYi2t5fiL4+R3N//TWzg6qhQDE86Htsmh+Ah/y1tIdh1tEWLci98Ts8u9eTcO5jzbof4XJ7eX/eVuat3M3UMT04Y0wmMU65DyFEJGsoKeDWmsdKqWFAX631B0qpVCAu1I2r1Y5CpdR/Met0u4FrWmrfAryFu3AteYfYiVdjTW56BdzcvSX8+7MNeH0G914ykj4ycU6IViHQmtn3YY44ygI+ABKBd4HxoWva4bTWLwIvttT+hMnwVFM15wXsfUbj6Du2Sdvw+nx8uWQ7ny7KZcKwLlxwUl85ixCiFQn0GsL5mNXsVgBorXcppWRYShRwLX0Xw+chdtyljX5tSUU1m7YfZNbynRworuLWc4cwtE96CFophAilQAOFW2ttKKUMAH+QiJ6i0lHKve0n3Ju+J376g1icDV9prKr2sHlnERtyD7Ih9yC7DpSRkuBkWN80bjtvKEnxzauLLYQIj0ADxUtKqbeBNKXU74CLgb+Hrlki3HxlBVTNf5WY0edjy8hscP15K3fz1qzNOOxW+vdox4RhnRnYsx1d0hNCPtxVCBFageZ6elkp9QMwCXNo7FVa69UhbZkIG8PnoXLOC9g69MExZEqD63+3Yhdvz87m6jMGMHpAB2xWyckkRFsS0F+0UqoLUAC8B/wPOKCUan7mNxGRXMvexygrJPak6xqcVFcTJG6YPoixgzpJkBCiDQr00tNXwCDM+QsWoC+wWSnlBW7UWi8MUftEC3PnrsC9bhbx0+7FGlv/xJ25K3bxzuxsbpg+mFEqo4VaKIRoaYF+/dsMHKu1HqC17g8cA6zFLI/6j1A1TrQsX8kBqua9bN6X6JRV77oSJISIHoEGioFa60MV7bTWq4DBWuvNjdiGiGCG103lnH9i76xwDKm/HLoECSGiS6CXnn5QSr2FeY8CzHkVy5RS8UD0JFRpw1xL38WoKiX29N8dNkrJ4/Wx+0A52/eVkptXQu7eUnbuL+PGswczsp8ECSGiQaCB4jrM+g+TMe9RfAn8T2vtBcaFqG2ihVRsWox74/fET78fS0wCAGu2FvDJwm3s3F+G1+ujU1o8mZ2SGTuoE1ef3o5uHWQsgxDRItDhsV7gHf+PaEO8hbso/PpfxIy9EFtGLwDm/LSLd+dkc+roHlxwcl96dEwk1tn8wkRCiNYp0FxPYzAn2A3AvCcRCxRorZtftUaEjWfXOipnP09C/7FYBk7C5zP439wtfL9qt9x/EEIcEujXxBnAOcCnWusRSqkLgWND0SCl1GvAEKAUWKW1vsO/XGpmB1H1+tm4Fr+D85hzaHfi+ew7UMpLn24gJ6+Eey4ZKRXmhBCHBHw9QWu9018PAq31u0qpe0PXLK7XWv9Y84vUzA4ew+fFtfht3HoBsZNuwNH7WA6WunjirRV4fQYPXD6K9JQWyyAvhGgFAg0UJf4RTouVUi8A+zG/2YfK80qpSuBxrfUcpGZ2UBjVFVTO/ie+wl3ET78PW3omO/aV8tyHa+nUPp4bpw8mPlbuRQghDhfop8KvMAPDbcDlQDIwLURt+p3WOt+fNmS2UmoUUjO72TxF+zjw2RNY7TF0uOIJ7EntWb5hH0+/u4KJI7txzZmDsNuiY0pMW3x/GxJtfZb+BleDgUIpZQXe01rXZId7ubk79V9K+rKOpx7XWn8BoLXeo5RaB2QiNbObxZOnqfr2OWxd+hNz0nWUepzM+nYTM+dt5fwT+3D+KapFalVHirb2/gYi2voczf0NR81stNY+pZRPKZWmtS4Ixk611oXAmLqeU0qlaK2LlVIJwEBgF7APqZndJG69gKoF/8U5bCrOY87B64O3v9EsWb+Pm88ZwvCsdEkDLoSoV6CXnizARqXUfGrNxNZaXx6CNr2jlErxt+1xrXUpgNTMbhzD58O1bCbu9bOInXg1jqxxVFS5eeHjdewpqOD3l46kR8fgf/MQQrQ9gQaKJ0Pailq01qcfZbnUzA6Q4a6iau6/8O7fSvy0e7F17EtBcRV/f28VToeNB684htTEmHA3UwjRSgR099I/8igfSPU/XgFsCGXDRNP4yg9S8ekf8ZUcIP7sh7B17Iur2suz768hLSWWey8eKUFCCNEogc7Mvg9zDkMW8AGQALwLjA9d00RjGZ5qKr95BktsMnGn3ILFGYdhGLz29Sa8Ph83Th9MjNMW7mYKIVqZQMdDno85HLYcQGu9C3OIrIgQhmFQtfC/GO4q4ibfhMVpTpr7dvlO1mzN55ZfDSEuRuZICCEaL9BA4dZaG4ABoJRKBnwha5VoNPfG7/Dk/EjcKbceygC7IbeQ9+dt5bppg+iclhDmFgohWqtAA8VLSqm3gTSl1O+AeZhJAkUE8O7NxrX4LWInXoOtfTcA8osqefGT9Uwbl8nwrPQwt1AI0ZoFmmb8ZaXUD8AkzKGyV2mtV4e0ZSIgvooiKmc/j2PwFBx9RgPgcnuZ8eFa+nZN4czjM8PbQCFEqxfozex7gfe11s+EuD2iEQyvh6pZz2Nt14WY0eeZywyD/369iWqPj+vOHIhVJtMJIZop0Lub5cArSqlE4CPMoLEpdM0SgXAtfQdfeSHx5zyMxWrDMAw+WbiNVdn5PHjFMXLzWggRFIHOo3hOaz0ROAMoBF5QSq0JactEvdw5y3Fv+p64U27FGpeMYRi8P28r3yzbyW3nDpWb10KIoGnsV85+QH+gC7Aq+M0RgTAMH9U/foRz+DRsGZn4DIN3ZmWzeP1e7rxwOH27poS7iUKINiTQexQvYt7IXo454e4erXX0pBuNMJ5tP+ErL8Q5+BR8PnNC3arsfO6+aAQ9O0n+JiFEcAV6RvENcIfWuqpmgVLKqrVu8lwK/2zv64G1WutptZY/AkzGLIV6mb82RTrwBpAEzNZaP9LU/bZ2hmFQvfJznANPxmuP4+XP1qN3FHHPxSPompEY7uYJIdqgQO9RfKS1rlJKWZVSk5VSLwE7mrnvV4GTay9QSg0CjtVaj/c/f7f/qXuAV/3Lj1VKDWzmvlst7841+IrysAycwgsfr2PL7mLuvWSkBAkhRMg0GCj8wWGSPzjkYI56mg0MaM6OtdZ7+WUBognA5/7Hn/t/BzOnVO3lJzRn362VYRi4Vn4GWRN4+tMcdh0o495LRtKxffRU8hJCtLx6Lz35702cAvwAvA/cAazXWr8Xova0xwxGaK0r/cNxARJq3RMpAnoFusG2VAq1asd6yg5sY8a+MdiSLPzllglByQQbqf0NlWjrL0Rfn6W/wdXQPYrjMO8VrAB+0lpXKKWMQDceSMnTIxwEUv2vjQXK/MsrlFKx/nskKZhDdAPSlkqh7v/2bda6+pDeowtXTu0PHm9Q2hmp/Q2VaOsvRF+fo7m/LV4KVWs9QinVB/g/4EOllBdIUUr11VpvaWjj9ZU8PYr5wJ8wCxSdDiz0L1/g//1DYCpwXyO22SYsnb+UAQVbYNAtXDtxgJQvFUK0mAbvUWitt2qt/6y1HgVcDPwVeE8ptb45O1ZKXQO8CRynlJqtlErXWq8HViulFgLX8XNlvSeB6/zLV/vXiwpen4+3vt0Ma7+grMMwJp04SoKEEKJFWQwj4CtJh6l9VqGUelxr/WBQWxYcxoEDpY1+UaScthqGwcufb6Bgx1ZucnxEwnmPH8oOG0yR0t+WEm39hejrczT313/pKajfJgNNM/4LR1x6OiMIbRFH+GThNtZsLeDXvbbjyBwRkiAhhBANaXKgOIJcCwmyJev28uXS7dw2pROO3Stwjjgz3E0SQkSpYKUXbdr1K1EnveMg//lqI1dP6kaXDf/F0n0YtoyARwQLIURQyRlFhNlXWMGMD9cyfWQ7hmx5FUtMInGTbgh3s4QQUSxYZxRRN1w1FMoq3Tw9czWje9iYeOBtLMkdiJtyKxZ78yfVCSFEUwWaPfYk4GGgJ2DDPIMwtNY9ALTWX4WshVHC7fEx44M1dIut5OzKz7Gm9SDulJux2BzhbpoQIsoFekbxL+BSYCXQ5Iyxom4+w+DVLzdiKd3H5YnfYu+YRexJ12OxSYU6IUT4BfpJtF9rvSykLYlShmHw3twt5Odu4daU2Ti6DSF24jVYrLZwN00IIYDAA8U6pdTnwBeAq2ah1vrVkLQqinyzbCfb167gluR5OHsdR8yEy7FYgjXGQAghmi/QQHHA/9MlhG2JOovX5aEXf8cNSQuIHTIV5zG/kvQcQoiIE1CgiND0HK3a2pwCNsz+lKsSfyB2zEU4B58S7iYJIUSdGqpH8bjW+kGl1BvUMalOa315yFrWhm3bU8ymL97i/ITVxJ18PY4+x4W7SUIIcVQNnVF85v/3tWDvuK6a2UqpTOAnYK1/tTu01qvaUs3svQVlZH/8LybHbiF+6m9wdBsc7iYJIUS9GqpHscz/75wQ7PtV4H/As0csX1ITOGqpqZk9Uyn1hVJqoNZ6QwjaFFI523ZS+PW/GOEsJPGs3+PoIGk5hBCRL9AJd2OAv2PWybYCsUCB1rrJN7e11nv9ZxBHOlYptQDzrOJOfwnU8cBD/udrama3qkChF39P8pp3yEjIoN3Zj2JPzgh3k4QQIiCBjnqaAZwDfOqvenchcGwI2pMH9NValyqlHgNuB56gFdfM9rldrHnneTrkLSO/1xSOOf9KLNbIGv4q9YXbvmjrs/Q3uAKe+qu13qmUsvkfv6uUureh1zS2ZrbW2sXP8zTexUwbAq20ZrZ7/zbyv5iBt8pN3uhbGThqBMUlVc3ebrBFc5GXaBFtfY7m/rZ4zexaSpRS8cBipdQLwH6guqEXNbZmtlIqWWtd4v91IpDtf9zqamZXrv8O16I3WOdR9DnzGgZ2Tw93k4QQokkCDRS/wgwMtwGXA8nAkTecG8VfM/sq86GaDVwIjFFKPQqUAQeBK/2rPwm8rpT6LTA30mtmu7atoHrRG3zGyZx68bl0SI0Ld5OEEKLJGqyZrZSyAl9rrae0TJOCqsVrZnv2b6P0kz8xxzOKSZdeRbukyE8RHs2n6dEi2voczf0NS81srbUP8Cml0oK547bIV5pP0Wd/Y1l1FuPOv6xVBAkhhGhIoJeeLMBGpdR84FCYlpnZPzNc5Rz46ElyqtrR+6xr6ZKeEO4mCSFEUDSUwuNb/yWnJ1uoPa2S4fWw/5OnyS/zEnPSDWR1bx/uJgkhRNA0dEaRASGbmd0mGIbB/q//RVXhXvJH3sLEgV3D3SQhhAiqhgJFmlLq10d7Umv9UpDb0+oULP4Yy67VbOx9NaeN6R/u5gghRNA1FCgcQCeCfAe9rajYtRn7+s9Y2P4czjhFMsAKIdqmhgJFntb6sRZpSSvjq67i4DcvsMUyiClnny4Fh4QQbVZDgcLbIq1ohbZ9/gqG24f61TU4HVLfWgjRdtU7j0JrHYrEf63e7pWLaH/gJypGXUGnDqnhbo4QQoRUZKUxbQVKCwuwLXuDze0nMvTYkeFujhBChFzA2WMFeH0+dn48A4u1PSPPviTczRFCiBYhZxSNsOarD0h37ybjjJtwOCTGCiGiQ9g+7ZRSXwCpgA14SGv9rX/5I8BkoBS4TGudHwk1s7du1PTY9TUHB11A3y7dWnr3QggRNuE8o7hDa308cAbwFIBSahBwrNZ6PGZN7bv969bUzB6PWSp1YEs21GcYFC14l4LELPqOb41JdIUQounCFii01jVFiaoAn//xBMya2Pj/neB/PP6I5Se0RBtrrFyTQx8jl84Tzm7J3QohRESIhAvtfwGe8T9uD+QAaK0rlVKJ/uVhq5nt9RnsXj6HbrFp9Bsyok1OrJP6wm1ftPVZ+htcIQ0UDdXM9les82qt/+tffhDzvgVKqVjMSncQxprZS9blMcCzgYThkygurmzgla1TNBd5iRbR1udo7m84a2Y3SX01s5VSl/ifu7DW4vnAn4AXMWtkL/QvD0vNbK/Px/JFy7jSWkz8wAkNv0AIIdqgsNyjUErZMG9W9wDmKqXmAPhrYa9WSi0EruPnOhhPAtf5l69uqZrZS9btY4BnI9ZuQ7DGywxsIUR0Css9Cq21F6izTqjW+iHgoSOWHcA8k2gxHq+PLxdlc1dMLjEDrmvJXQshRESRCXdHsXBtHn28Odgdduw9hoW7OUIIETYSKOrg9nj5fHEuU9rvwNHveCy2SBgcJoQQ4SGBog6zl+8k0VdCatk2HGp8uJsjhBBhJV+Vj1Dt9vL+3Gyu7XkAqycTW/vu4W6SEEKElZxRHGHBmjysVuheugZHPzmbEEIICRRH6N4hkTtPSsCoLMLRt84pIEIIEVUkUByhX/dUMgpWYM8chSUmIdzNEUKIsJNAcQSjuoJKvRSHkpnYQggBEih+wb11Gda4JGxdWjSTuRBCRCwJFEewOONJmXAhFqscGiGEABke+wuOPqNJiLLMk0IIUR/52iyEEKJeEVUzWymVCfwErPWvdofWelUk1MwWQohoFVE1s/2WaK1P9P+s8i8La81sIYSIZpFWMxvMQLBAKfVPpVScf1lYa2YLIUQ0i4Sb2bVrZucBfbXWpUqpx4DbgScIY83saCD9bfuirc/S3+CKqJrZWmsX4PKv8y7wsP9x2GpmRwPpb9sXbX2O5v62+ZrZSqlkrXWJ/9eJQM3lqSbXzG7qQQvFwY5k0t+2L9r6LP0NHothGCHb+NH4a2ZXACsx71F4tdaTlFLTgEeBMuAgcKXWukgplQG8jjnqaa6/XKoQQogWEJZAIYQQovWQCXdCCCHqJYFCCCFEvSRQCCGEqJcECiGEEPWSQCGEEKJekTAzO6Iopa4DrgKqgau11jlhblKDlFIOYB4wCLhWa/3+0RIp+ocg3w8YwO1a6+VKKSvwPDAY2IM5LLlSKdUHeAVwAv/RWv/bv42wHiOl1Fjg7/79lwGXYP5fbpP99behI/AR4MZMpHkDsBV4DegCrANu1lr7lFLHAs8CFuCPWuvP/dt4BJgMlAKXaa3zG/P/pGV6ejil1HjMeVQZ/kVt+T0uB2qO8xPA90TI+ytnFLX4Z5Jfi5lL6i7MN6s18ADn8XMqFKgjkaJ//srjwBTgfOBp/7pTAZ/WegLwI+YfDJj9vwuYAFyrlGofIcdoOzBJaz0R+Ay4mbbdX4B8YLy/zw8A9wJXAz/6++EDTvOv+zRmf08BHldK2ZRSg4Bj/cfnVeBu/7qNOW7h8BvM9wja/nu8rVZC1K+JoPdXAsXhRgPztNYef4RV4W5QILTWhtY674jFdSVSzAI2a61Ltda7AYdSKhbzj6aupIv9tNbLtdZezDOW0UTAMdJa79Fa1+RnqMYMlG22vwBaa6/WuiZ5Ziqwmjr64e+fXWu9W2tdBmzGPA5HrltTFL4xx61F+b/1LgTKm9DWVvceA92VUvOVUm8ppdKIoPdXAsXh2mPOCK/Rmo/PkYkU2/PL/tW1vGYZmKe29a0LYTxG/j+mmzAvJURDfwcqpRYDz2FelqirH+39j6lj+UEA/3FK9D/fmOPWYvyXjm4CXqi1uK2/x3201icAc4A/EkHvb2v+IAyFg5jf1mp4w9WQIKio9S2hJpHikf2ra3ntpItGA+tCmI6RUioemAncprXOp433F0BrvUFrPQ6Yhhks6upHg332H6cy//ONOW4t6WLgU38i0Bpt+j32/z8GMyHqCCLo/ZVAcbgfgIn+a34j+TkpYWtUk0gRzOu1CzD7008plaCU6gR4/H+I82ute7p/XYDNSqmR/muaE4FlRMAxUkrZMf+YntNaL/YvbrP9BVBKxdT6tQgzV9ov+uH/9uhRSnVWSiVgXmbY4l93aq11F/ofN+a4taQhwHlKqa+BocDbjWxrq3qP/e23+X+tSYgaMe+vjHqqRWtdqJT6L+bBdAPXhLlJAVNKvQccA5QppUYDTwKv+1O5z9Var/ev9wgwG/Ob1W/8L/8KOEsptQCzJsiV/uW/x7ys4wBe82cDJgKO0UWY11qTlVK3A1/QtvsLMFIp9QTmTU0L8FtgE/CaUmo+sBGzXwB3Ah/413tUa+0B1iulViulFmKOirncv25jjluL0VrfU/NYKTUP8wzD0oi2trb3uD/wslKqBLPUwrWYAxgi4v2VpIBCCCHqJZeehBBC1EsChRBCiHpJoBBCCFEvCRRCCCHqJYFCCCFEvSRQCCGEqJfMoxARQyn1I+b/yU6Y49kLgHyt9eQAXnsccJbW+v5G7vNa4A/A3lqLR/lzATWLUupkoEhrvaK526q1zQmYmXOdmHMB/q61frme9d8ExvDzTN37tNZfBqs9IjpIoBARQ2t9DByaDLRXa/1i7eeVUrajfYBrrX/AnGHbFC9rrR9o4mvrczKQCwQtUAAvA2dorbf4Z2v3COA1N2itZzdmJ/UdaxF9JFCIiKaUmoyZMtkAbEqp84EPMfPTANyitV7sX+9KrfWlSqk/YNYvGAx0BK7XWs9p5H6vBSb5X98TeFhr/aZS6lPgz1rrJf71fgLOAk7ETP9dDWzAnAF8LVCtlLoFOBfz7+15oB2wH7hca31AKbULeBMzh9M+4AJ/LYG/Y6ZfqMacRfx3/2sPAGitXfjTTSil+mGml0727//qWhl2j+xbu3qO4aFjjVnbQAi5RyFahZGYhVgmY6acPlNrPRI4G/jbUV7THTPNxyXAQw1s/1ql1Cr/z6e1lg8AzvBv5zH/spmYH/ooswhOlT9V8wPAFK31MMxv8LmY3/4f01oP11pvxQwSV2mtRwGvYxaOqbFDaz0Y+BJ4QJmFis4EBmith2KmnQD4N7BVKfU/pdRltfIDzQCe9K+7B7it1rZfrNW/uAaOYe1jLQQggUK0DvO11vv9jy3A35RSa4FPgYFHec0X/ksnK4HMBrb/sv/DfLjW+qxay2dprSv9gSDGn/r6U8xv/mAWi/rA/3gR8IpS6irMfEyHUUqlAmOBz5RSq4D7gG61VnnX/+87mDUECjHPJP6tlDoTM38P/nsw44HFmDl/au5PDNZa1wS5N4Hja237hlr9q6T+Y1j7WAsByKUn0TrUvoRSk+xsOOYHcslRXuPy/+vDvIzSFK5ajw3AqrUuVkptUUqNwjyzOM///HXAOGA6sFQpNfSIbVmB7Vrr4UfZl1HrX0Nr7fbv41TMPk/HvJSF1noTsEkp9T/MxIBX1bG9+tR3DOu8XCWim5xRiNYmGdjvP1u4AGjxymuYl59+h/mBvsO/rJfWehHmvYl4/08pZq1i/FlKK5VSkwCUUk6l1IBa27yg1r8LlVJJQJLW+hPMsqfD/a+bWus1Q4Ga/a+r9dzF/Jxmui6RcAxFKyJnFKK1eRP4XCk1HbMSWEEQtnmtMstu1pjUwPqfAC8BD9Za9oxSqpf/8b+11qVKqU+AmUqpKzDPPi4CXvDfpLYBf8FMHw3QUym1Dv/NbMwbzR8ppZyYZxn3+de7Rin1DFCJ+e3/av/yW4BXlVJ/wbyZXd99mVAcQ9GGSZpxIcLMP+op019XQIiII5eehBBC1EvOKERUUEqdDvzpiMVfNHYmtxDRSAKFEEKIesmlJyGEEPWSQCGEEKJeEiiEEELUSwKFEEKIekmgEEIIUa//Bxh3EJdbPRyrAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=figsize)\n", + "sns.lineplot(data=full_q2_data, x='Train_EnvstepsSoFar', y='Train_AverageReturn', hue='Config')\n", + "plt.savefig(os.path.join(export_dir, 'hw3_q2.png'), dpi=200, bbox_inches='tight')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 3" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ConfigTrain_EnvstepsSoFarTrain_AverageReturn
0hparam11.0-208.769302
1hparam110001.0-190.801102
2hparam120001.0-175.555710
3hparam130001.0-156.841217
4hparam140001.0-145.930069
............
44hparam2440001.0142.106491
45hparam2450001.0141.662888
46hparam2460001.0159.932724
47hparam2470001.0146.924301
48hparam2480001.0144.613419
\n", + "

196 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " Config Train_EnvstepsSoFar Train_AverageReturn\n", + "0 hparam1 1.0 -208.769302\n", + "1 hparam1 10001.0 -190.801102\n", + "2 hparam1 20001.0 -175.555710\n", + "3 hparam1 30001.0 -156.841217\n", + "4 hparam1 40001.0 -145.930069\n", + ".. ... ... ...\n", + "44 hparam2 440001.0 142.106491\n", + "45 hparam2 450001.0 141.662888\n", + "46 hparam2 460001.0 159.932724\n", + "47 hparam2 470001.0 146.924301\n", + "48 hparam2 480001.0 144.613419\n", + "\n", + "[196 rows x 3 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def read_q3_data(question):\n", + " full_data = pd.DataFrame()\n", + " for folder in os.listdir(data_dir):\n", + " split = [s.strip() for s in folder.split('_')]\n", + " if 'LunarLander-v3' in split and question in split:\n", + " config_list = split[split.index(question)+1] # get dqn/ddqn after q2\n", + " logdir = os.path.join(data_dir, folder, 'events*')\n", + " eventfile = glob.glob(logdir)[0]\n", + "\n", + " X, Y = get_section_results(eventfile) # Y is Train_AverageReturn\n", + " X.pop()\n", + " data = pd.DataFrame({'Config':config_list,\n", + " 'Train_EnvstepsSoFar': X, \n", + " 'Train_AverageReturn': Y})\n", + "\n", + " full_data = full_data.append(data)\n", + " \n", + " return full_data\n", + "\n", + "full_q3_data = read_q3_data('q3')\n", + "full_q3_data" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=figsize)\n", + "sns.lineplot(data=full_q3_data, x='Train_EnvstepsSoFar', y='Train_AverageReturn', hue='Config')\n", + "plt.savefig(os.path.join(export_dir, 'hw3_q31.png'), dpi=200, bbox_inches='tight')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 4" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ConfigTrain_EnvstepsSoFarEval_AverageReturn
010_101013.029.928572
110_1011507.0197.000000
210_1021984.0200.000000
310_1031984.0200.000000
410_1042144.0199.666672
510_1053288.0200.000000
610_1064436.0200.000000
710_1074633.0200.000000
810_1084633.0200.000000
910_1094633.0200.000000
01_1001013.025.687500
11_10011167.038.000000
21_10021617.0132.500000
31_10032345.0124.750000
41_10043015.0147.000000
51_10053503.0200.000000
61_10063648.0152.333328
71_10074251.088.800003
81_10084765.0200.000000
91_10094765.0200.000000
0ac_1_11013.025.000000
1ac_1_111125.09.595238
2ac_1_121184.09.348837
3ac_1_131230.09.302325
4ac_1_141268.09.325582
5ac_1_151317.09.441860
6ac_1_161345.09.465117
7ac_1_171381.09.488372
8ac_1_181410.09.227273
9ac_1_191453.09.372093
0100_11013.037.363636
1100_111443.088.199997
2100_122112.0158.333328
3100_132631.0133.500000
4100_143496.0102.000000
5100_153967.0125.750000
6100_164596.092.400002
7100_175247.0123.500000
8100_185785.0159.666672
9100_196564.0200.000000
\n", + "
" + ], + "text/plain": [ + " Config Train_EnvstepsSoFar Eval_AverageReturn\n", + "0 10_10 1013.0 29.928572\n", + "1 10_10 11507.0 197.000000\n", + "2 10_10 21984.0 200.000000\n", + "3 10_10 31984.0 200.000000\n", + "4 10_10 42144.0 199.666672\n", + "5 10_10 53288.0 200.000000\n", + "6 10_10 64436.0 200.000000\n", + "7 10_10 74633.0 200.000000\n", + "8 10_10 84633.0 200.000000\n", + "9 10_10 94633.0 200.000000\n", + "0 1_100 1013.0 25.687500\n", + "1 1_100 11167.0 38.000000\n", + "2 1_100 21617.0 132.500000\n", + "3 1_100 32345.0 124.750000\n", + "4 1_100 43015.0 147.000000\n", + "5 1_100 53503.0 200.000000\n", + "6 1_100 63648.0 152.333328\n", + "7 1_100 74251.0 88.800003\n", + "8 1_100 84765.0 200.000000\n", + "9 1_100 94765.0 200.000000\n", + "0 ac_1_1 1013.0 25.000000\n", + "1 ac_1_1 11125.0 9.595238\n", + "2 ac_1_1 21184.0 9.348837\n", + "3 ac_1_1 31230.0 9.302325\n", + "4 ac_1_1 41268.0 9.325582\n", + "5 ac_1_1 51317.0 9.441860\n", + "6 ac_1_1 61345.0 9.465117\n", + "7 ac_1_1 71381.0 9.488372\n", + "8 ac_1_1 81410.0 9.227273\n", + "9 ac_1_1 91453.0 9.372093\n", + "0 100_1 1013.0 37.363636\n", + "1 100_1 11443.0 88.199997\n", + "2 100_1 22112.0 158.333328\n", + "3 100_1 32631.0 133.500000\n", + "4 100_1 43496.0 102.000000\n", + "5 100_1 53967.0 125.750000\n", + "6 100_1 64596.0 92.400002\n", + "7 100_1 75247.0 123.500000\n", + "8 100_1 85785.0 159.666672\n", + "9 100_1 96564.0 200.000000" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def get_section_results(file,tag):\n", + " \"\"\"\n", + " requires tensorflow\n", + " \"\"\"\n", + " X = []\n", + " Y = []\n", + " for e in tf.train.summary_iterator(file):\n", + " for v in e.summary.value:\n", + " if v.tag == 'Train_EnvstepsSoFar':\n", + " X.append(v.simple_value)\n", + " elif v.tag == 'Eval_AverageReturn':\n", + " Y.append(v.simple_value)\n", + " return X, Y\n", + "\n", + "def read_q4_data(question):\n", + " full_data = pd.DataFrame()\n", + " Y_tag = 'Eval_AverageReturn'\n", + " for folder in os.listdir(data_dir):\n", + " split = [s.strip() for s in folder.split('_')]\n", + " if 'CartPole-v0' in split and question in split:\n", + " config_list = split[split.index(question)+1:split.index('CartPole-v0')]\n", + " config_list = '_'.join(config_list)\n", + " logdir = os.path.join(data_dir, folder, 'events*')\n", + " eventfile = glob.glob(logdir)[0]\n", + " \n", + " X, Y = get_section_results(eventfile, Y_tag) # Y is Train_AverageReturn\n", + " data = pd.DataFrame({'Config':config_list,\n", + " 'Train_EnvstepsSoFar': X, \n", + " Y_tag: Y})\n", + "\n", + " full_data = full_data.append(data)\n", + " \n", + " return full_data\n", + "\n", + "full_q4_data = read_q4_data('q4')\n", + "full_q4_data" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAADWCAYAAAA0PvKyAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzsnXd4FNX3h9/tm94DAZLQwqUpIoJKEcSKFTsoimIHFXtBERV779h7wS7K96codkFEUAQpN/SEFJJANnX7zu+PTUKAhOwm25LM+zx5dmd25t4zu5uzd84993w0iqKgoqKiotIx0YbbABUVFRWV4KE6eRUVFZUOjOrkVVRUVDowqpNXUVFR6cCoTl5FRUWlA6M6eRUVFZUOjOrkVVRUVDowqpNXUVFR6cCoTl5FRUWlA6M6eRUVFZUOjOrkVVRUVDow+nAb0EbUwjsqKiqdEY2vB7Z3J09paZXPxyYmRmOx1AbRmsiis10vdL5r7mzXC53vmve93rS0OL/OV8M1KioqKh0Y1cmrqKiodGCCGq4RQhwJPAk4gGrggro+3wXigMVSynvqjj0FuBNvnH2mlPKvYNqmoqKi0hkI9kh+O3CMlHIs8DUwA7gNeENKORoYLoQYKITQAXOB44FzgKeCbJeKiopKpyCoI3kpZWGjTQfgAkYDd9ftWwgcBXiAXCllFVAlhDAIIcxSSlsw7etoKIqC3emm2uqkxupie2kNO8uqqbY6G/5qrE4cLk/YbNRoNGg13keNBrR1j3vv3/u1xsfs2d67nfrtqCgjDrtrv+Pr3x9F8T56FFDYZ3vf1xttKwp4Gm831V4L7Zvc1Qyq/YvV0Ufi1JoC8n4aDDqcTndA2movtOaau9m3kmNbEySLDkxKzxwyxp3bsK24XOz639ckjByNIS0t6P2HJLtGCJECTAdOBC6QUlrrXrIAvYBkoLzRKZa6fY1/JJokMTHaZzt0Oq1fx4cTl9tDda2TqlpH3d+e53v273msrnt0ufc48BiznthoI3HRhobHpIQoTAYdGp8TsAKHotDgHD2eeqep7OckPR4Fj6LgVkDxKHgUz15O1uPZ95ymz99zjvd5Uz8aWm3TPzL7/xDt/6Oy//nNtKUFLR6GbP2MROs2uuqr+K/nZNC0/UZao9HQ2SQ8W3PNh25chsMUQ425S5Csap7YLt0a/I7H6WTzUy9Qs3kLWaedhNEHf9RWvxV0Jy+EiAY+Aa6TUpYJIWobjdITgN14HXxio9Pq97eIP6lUkZB65XJ7+Du3lIoaBzX1o2uba6+RdrXVic2xZ6Si12mJjdITG2UgNspATN1jSpyJ7PRYYhq/Zq4/Rk9KcmzYrzfURMJn3BT25Z/i9OwmauJstIue5jjtX5gOP7flE1sgUq83mPh7ze7dBdSuLiRm8uNo41KDaFnzWCy1eOx2Cuc9j3NnMT1uuZ1ajYlaH66jrSmUwZ541QPzgeeklEvrdv8GnAR8DkwAZgEbgX5CiBi8E7KujhqqWbN5F68tXE92l9gGZ50QY6RbagyxZn3DvsYO3ajXognH0FslILi2/4Pj32+IOuVWdOm9iTruWmoXPoI2qTuGfqPCbV6Hx7VxCbqM/mFz8AAem42C557GVWGhx62zMCQlhazvYI/kJ+ONuccLIWYC/wMeBd4RQtwI/CilXAsghLgHWIz3jv6GINsVNmS+hYP7pHDNmQeF2xSVEOCpLMH606uYRpyNPkMAoOuag/moi7H9+ibahC7ouvQNs5UdF8XjwblxKabhZ4XNBndtLQXPPInHZiPzljvQJySEtP9gT7y+izddcl8mNHHsV8BXwbQnEpB5Fo4c3DXcZqiEAMXlwPr9C+i7DcBw8Il7vWboNxr37gKs3z1L9Blz0MamhMnKjo27cB2KvRZ9r8PC0391NTueehw0GjJvuR1dbGzIbVAXQ4WQWpuLvJIqRGZiywertHvsS99Dcdowj7u0yXCbacQ5aNN6YV30DIrTHgYLOz7O3CXoew1DY4wKed+uigryH3sYjV5PjxtvCYuDB9XJh5RNBRbMRj2Z6eH5sFVCh1P+hnPjH0QdNwONsenMCI1WS9T4q8DjxvbTKyhK+FJbOyKKw4pr68qwzHs4d+8m/9GH0MXF0eOGm9FFhy+rT3XyIUTmWcjpkYBWq06idmTcu/Kw/f4O5jFT0aVkHfBYjTGKqBNm4i6SOFZ+GSILOweurSvQmKLRdRsY0n6dpaXsePQhDGnpdL/uBrRmc0j73xfVyYeQ3HwLIksN1XRkFHsN1u+fx5AzEkO/0T6do41Px3zcNThW/Q/n5j+DbGHnwblxKYackWi0oXNzjuJi8h99CFNmFt1mXIvWaAxZ382hOvkQYXe42VZcRT81Ht9hURQF2y+vozFGYRp5gV/n6rv1xzTqQmw/v4a7dGuQLOw8eKrKcBeuR58zMmR92gt2kP/og0T160fGVdPRGgwh6/tAqE4+RGwqqECv05Ldxb+FDCrtB+fqb3AVbiDq2GvQ6P0fwRkHjMMwYBzWRc/gqSlv+QSVZnFuXIo2NRtdco+Q9Gfbvo38xx4m5uAhdL30CjQ6XUj69QXVyYcImW+hb/d49Dr1Le+IuAo3YF/+GVFHX4E2vvX1SExHTEKb1B3rd8+iuBwBtLDzoCiKN1TjY7isrVg3b2LH448QP+Jwulx0SUjDQ74QWdZ0YHLzyumXFbpVbiqhw1NrwfbDixiHTECffUib2tJodUQdOx3FYcX2y+udri5NIPCUbkGpLEXf5/Cg91W7YT07nnyMhKPGkTZ5SsQ5eFCdfEhwON1sKapU8+M7IIrHje2HeWiTumM87MyAtKkxxRB9wvW48tfg+OfrgLTZmXDmLkGXeRDaqPig9lPz3xoKnn2K5BMmkHr2uRFbekR18iFga1ElGo2GXhnB/dKphB778k/xVOzEfMzVAR3FaRO7EnXsdBwrF+DcujJg7XZ0FLcT5+Y/g54bX/3P3xQ+/wwpp04k5bSJEevgQXXyIUHmWejTLR6DXn27OxLObStx/vcd5mNnBGXUqO8xGNORk7H99DLusu0Bb78j4sr7FxSlzWGzA1G1/E8KX3qB1HMnkTzhpKD1EyiCXYXSAPwMDAIuk1J+KoR4FBhRd8hgYJqU8ishxGYgv27/W1LKt4JpWyiR+RY1dbKD4anYie2n1zAdfi76rjlB68cw6Bg85TuwLnrGW+MmOrTFrdobrtwlGPocjkYXnPTFiiW/s/OdN+ky5SISxowNSh+BJthVKF3A2cCV9TuklLcC1En+rQe+q3vJKqUcF2R7Qo7L7WFzQQWnHJkdblNUAoTismP9/nn0mYMxDD4+qH1pNBpMo6bgsTyO9fvniD7ltqA5sPaOx1qJK2810afdEZT2LT/9SMn89+k67TLiDz8yKH0Eg6DGD6SUipSyqJmXxwN/NKobbxRC/CyEWCCE6BVMu0LJtqIq3B6F3t3VEVhHQFEUbL+/i+J2Yj5qWkhisRqtnqjjrkGprcD229tqxk0zuDb/iSY+FW16n4C3Xf7dIko/+oCMK65uVw4eQiT/1wznAx822h5Zpxx1DPAiTZQjbopIl//LW1VI38xEuvip5hII2pPcYaAI9jVX//sDNVv/In3KAxjTQlkeOJrYc+5g53t3ouvWk/gRpwHqZ9yY4i3LiDtoHAlJMQHtr/Czzyn74jNybr2ZxEMPDWjbvhDx8n9NIYQw4RX0vrx+n5SyrO7xByHEM762Fenyf6tyS+jbLT4sEm2qNFxgcZdto3bx65iPmkatIdUn6baAok/GPP4qKhY9i8Ocij7rEPUzrsNdXoCzeDPGo68K2PuhKAq7vviM8sXf0f26G6B3/4j4P/ZX/i9c6R4nA99JKV3gdfpCCHPd88HArjDZFVDcHg+bdlSo+fEdgIbCY+IoDCGsh7Iv+qwhmA4/G+sPL+HeXRA2OyINV+4SdBkCbVzrVxs3RlEUSj/6AMuPi+lxwy1EDwhtJctAEnQnL4T4GLgIuLsuswa8soCNQzUpwB9CiF/xhmquDbZdoSBvZzUOp4c+ajy+XaMoHqw/vYLGHIfpyMnhNgfDQSei73UY1kVP466tDLc5YUfxeHBu+gNDTmBy4xWPh5J336Zy6VJ63HQrUTnBy54KBUEP10gp95Okl1Kes892ITA02LaEGplnIbtrLFGmcE59qLQVx6r/w71zEzFn3hsRmS0ajQbzmKnULnyEXQuexHD8jWh0nfc75i5cj2KrQd97eJvbUtxuit96ndr/1pB5y+2YMjMDYGF4UVfnBJFcNT++3eMqWIdjxRdEjb8SbVxquM1pQKMzEHX8dbgqSrAvea9TZ9w4Ny5B3+vQNkv8KS4XRa++RO36dWTeekeHcPCgOvmg4VEUNu6wIDLVomTtFU9NObYf5mEcegr6zIPDbc5+aKPiST3zVpyb/sC5dnG4zQkLXom/FW0O1XicDgrnPY9t6xYyb52FMaNbgCwMP6qTDxIFpTXU2lzkZKrx+PaI4nFhW/wi2tRsjIeeHm5zmsWY3hPz+Cuw/zEf147/wm1OyHFtW4nGGI2u+6BWt+Gx2yl87hkcRUVeB5+eHkALw4/q5IOEzCunR3osMebwx3BV/Mf+5yd4qndhHn9lRJaPbYyh5zCMh03EuvgFPJbm1h52TJy5S9D3PbLVn5HHZqXg6SdwWcrJvPUODCmhXPsQGnyerRFCxALnAT2BBtkTKeWswJvV/pH5FjV1sp3i3PIXzrWLiT5tFlpz+1DyMh5yCp7dBdQueoaYibPRmAK7ICgS8VTvwl24wW+pxXrcNTUUPPMEitNFj1tuRx/XMavE+vPztxAYAmwBZKM/lX1QFEWddG2neCxF2H55HdMRk9EFYXl8sNBoNJjHTkNjjMK6+EUUjzvcJgUd58alaFOyWiXx56qqZMfjjwDQ4+bbOqyDB/9SKBOllNcFzZIORNGuWqpqnfTLUp18e0Jx1hUeyxqCYdAx4TbHbzR6I1EnzKT2i3uxL5uPuZUj3PaAoijeipMDj/b7XJfFwo4nH0UXG0f3665Ha25bVk6k44+T/1IIcT7wNWCv3ymlVIUo90HmW+iWGkN8tP9izsFGURTs+XmYemRGfKw5lCiKgu23t0BRMB91SUSLQBwIbXQiUcfPpParB71qVQPGhdukoOAp3YqnsgR9X/+KhdkLCyl45gmMXTPoNv1atCZTkCyMHPxx8lPrHh8AFEBT99g70Ea1dyI5VFO1fBnFr76MuW8OXS64qMPkArcV5/qfcG37m+gz5qAxmMNtTpvQpfXEPO4ybD+9jDahC/puA8JtUsBpjcRfba6k8PlniR1yCF2mXoJG3zkWkPl0lUIILTBFSrkkyPa0exRFQeaVc974yFsK7bFZKf34I5JPOgXn7l1sv/8eEscfS8ppE9FFdexb1gPhLtmCfekHmI++HF1Sx8iPNvQZgae8AOv3zxNzxhy08R0nLVBxOXFuXoZ5zNSWD66jasVyil97haQTJ5By+pnt9k6tNfh0vy6l9ADPBdmWDkGpxYql2hGRI/ldX3+FLjqalNMmknHZlfS44WZq165h2113ULl8WadcNanYqrEufgHDgHEY+hwebnMCinHY6ei7DcC66GkUhzXc5gQM65Z/vBJ/Wb5J/JV/t4iiV18mbfIUUiee1akcPPiXXfOtEOJyIUSiEMJY/xc0y9opMs9CelIUSXGRFetzFBVSvvg70iZf0HCbGt1/ANl330fSccez8+03KXjyMRxFhWG2NHQ0FB6LTsR0xKRwmxNwNBot5nGXg9aA9ceXUDyecJsUEGrX/oKhzwg0+gO7H8XjoWT++5R9+RndZlxL4thxoTEwwvAnKFVffq9xXvwBY/LNaLzeA5wDlALFUspJdceeAtxZ1+ZMKeVfftgWMURifryiKJR8+D6xhwwlZuDeKwM1ej3JJ55E3IjDKf3oQ7bdM5vkEyaQfPKpHX5SyvHP13hKtxJ95j0dtsCXxmAi6oTrqP3iXhx/fYrp8P3qBbYrPLYqrJv/JvqU2w98nMNB8euvYM3NJfPWOzD37DBic37j8zdbStmad2k/jdc65kgpP63fqNN7nQscBcQDH+EVFWl35OZbOH10ZH2hqv/5G+umjfSc+2CzxxiSU+h29TXU/LeGkg/eo3LZH6RPPp+YQw7tkLe3rh3/4Vj5FVETbkAb2/FWOTZGG5uC+dgZWBc+gj57KLogCo8HG9emP9HHp6Lt0rfZY9zV1RQ89zTu6moyZ92FMa3jzEe0Bn9WvF7R1H4p5SvNnSOlVIAiIcS+L90lhJgJvCil/BDIAXKllFVAlRDCIIQwN9J/bRfsqrBRVmFDRFB+vMfhoPSjD0iecDKGlJarKMYMPojse+dS/u03FL3yEtEDBpI2+YIO9Y/iqd6F7YeXMA47DX2PweE2JyToMwSGgeOx/foG0Wfe22KoI1JxblxC7KCxKM0MPJylpex4+gl0sbFk3XEXutjYEFsYefhzj5rR6LkJOB7YADTr5JvhOSnlPUKIBOBHIcTvQDJQ3ugYS92+FgPEkaTx+u/W3aQlRtE3OzJGhjqdltqfvkOn19PrvLPQGn39x44m+cLJdD9+PNtff5Ptc+6k2xlnkHH6aX60ER5a+owVt4uSr1/C1D2H1KPPQ6Np32sF/PlOe467iOI3bkK7/lsSxrS/OYiKwq1U9zoSR9dBaCw793vdbbNhKywk6oJJmLp2pcpVA5aaMFgaGBTF+/maTGmh0XiVUt7beFsIcS/wrb8dSil31T1WCCF+AAYD24DGw98EYLcv7UWSxus/G3bSt3tCxGhuRtmrKfriSzKumkFlrQtqXf41YIoj/epriVn1Dzvnv0/JT7+Qfv4FxAyOvLK79RzoM1ZcDuxL3sNVtZuY42ZSUdGubhSbxN/vtHH0VCq/eQpXt0PQpWQF0bLAU1JSSlLWIKLSMnG7955EdtfW4qywEp/dD31ycocJMbrdLnbu3EliYpeGfaHUeE0B/F5JUzeCRwihB44ENgMbgX5CiBghRFfA1d5CNeDNrImkUE3e228T1X8gMUN8SzVrCo1GQ+zQQ+l534PEHTacgueeoXDe8zh3tx8ZXsXjxrnhV2o+uh3Xjv+IOu5aNObOeRuv7zEYfc6R2H55vV3Vt1E8HhRbNfomFj+5qqpwlpagT0zqUA4eQBeAhAB/YvJFeDNf6qkG7vbhvI+Bw4BqIcQIIFkIMRBvJcsPpJS5dcfdAyyu6+MGX+2KFCzVdnaWWyMms6bmv9VY/v6H7HvvD8iXXmsykXrm2cQfOZKSD95j2+xZpJxyOknHHR+xKwcVRcG1/W8cyz/DY63ANPRUDAPHt9t4dKAwHzGJmk9m4Vi9CNMhJ4XbHJ9wF20AxY3GtCdsoSgKLosFd2UFhtQ0dDEdv/Jma/AnXJPR8lFNnudTzpaU8ivgq9b0EQnk5ltIiDWSnhT+laOKy0XJhx/Q9dRTMHbpGtC2jRnd6H7jLVT/tZySjz6kcunvpF9wIdH9I2vpvKtIYl/+CZ5deRgPOgHjkAlojMGbj2lPaMyxmEZfhO3HlzH0PBRtYmC/I8HAmbsETfZwNFpvlXNFUXCVleG21mLo0hWdueVSFLt2lfHss0+wfv06YmPjSE5O5rrrbiIrK9svW/799x8ee+wh9Ho9jz32NM888zj33/9oq64rFPgcrhFC/OLLvs5KfX58JNwqln//HYrDTrczzwxK+xqNhrgRh9Pz/oeIHnwQO556nKJXX8ZVYQlKf/7gKNlO7TdPYl34KLqULGImPYpp+Fmqg98HQ6/D0GcNwfbrGyhKZC+SUpw2XFtXoKmr7a94PDh37sRjt2HsmuGTg1cUhVmzbmHo0GF8/PEC3njjPa688hrKy32a+tuL7777hgsvvJi33vqAtLT0iHbw4MNIXgiRDKQBqUKIHLyFycCbz95x8uraSG6ehfGHdg+3GTjLy9m1cAFdp05DF2UGe/AmgXVRUaSfN5mEUaMpef9dtt11BykTzyRx3Hg0Ol3LDQQQT2Up9hWfU7V5Gfpew4k59wG0CZE/Qg0nplFTqPnkTpzrfsIYwaWVXVtXojGY0Rij8bhcOEp2ogDGrhk+hwr//nsFer2eiRPPbtiXk9MPRVF44YVnWLZsCRqNhqlTL+WYY47n779X8MYbr5CYmMiWLZsRYgB33z2XhQsX8OOPi1m+fBnLli3liiumc+ut1/Puux9js9l44IF72Lp1M5mZ2ZSVlXLTTbfRv//AIL0zvuHLO3QqcDGQxd7pkpV4V6h2eqpqHRSU1dAvK/yi3WWffIS5Zy9ih48IWZ+mHpn0uPUOKpcuoezTj6j8/TfSp1xEVJ/mF6wECo+1Esc/X+Nc9yO6jP50ufAhas2qc/cFbXQi5iMnY1vyHvrsQyJ2UZhz4xL0OUeiOBw4i4vQGo0YUtP8KpXtddT999v/yy8/snGj5K23PqSiwsJll13EkCGHArBxo+Tddz8mNTWNq6++lNWr/+XUUyeyevUqRo4czdFHH0tRozIgn3/+CXFxcbz33ids2bKJSy6JjHr+LTp5KeXbwNtCiIlSyi9DYFO7Ize/gtgoA91SwhsSqM2VVK38i+zZ94Q8bKTRaEgYNZrYQ4ZS9sVn5D/yIPEjR5N21jno4gIvoac4rDjWLMKx+lu0CV2JOvFG9D0GYUyMpjZCUljbA/qcUeg2LcP229tEnXhDRIQbG+Op3oW7YD2e9COwFxag7ZmDKT0djycwxfRWr17FsceegE6nIzk5haFDD2XDhrVER8cwYMAg0tO9qYs5Of0oLi5kyAEy1dasWcU553irv/Tu3Zc+IRjk+II/KZRrhRBfCyGWAwghBgshbg2SXe0KmV8e9ni84nZT8v67JB49HlOP8NWI18XE0GXKRWTNmo19Rz5b77ody68/B6w4luJ24fjve2rm34pz4x+Yj5pG9Bl3o+8xqOWTVfZDo9FgHnMx7iKJa+PScJuzH85Nf2CzJ1P0+jvoExLRp6S26v+sV6/eSLnBr3OMjRb+abVa3O72k3LaGH+c/GvAvYChbnstcFHALWqH5OZZwi71Z/nlJ9yVFaScNjGsdtRj7tmLrFmzST3zbMo+/YT8h+/Htn1bq9tTFA/OTX9Q8/EdOP5ZiPGwM4g59wFvNcJ2vmo13GjjUjGNOAfbHx/gqa0ItzkNeDweyhctonxNOelTLkKflNTqgdSwYcNxOBwsWPB5w75NmzYSGxvHjz9+j9vtpry8nFWr/mHAgNYNGA46aAg//vg9AFu3bmHz5k2taifQ+JPgHCWlXFFfh0ZKqQgh/FxC2fGotTnJL6kOa368q7KSXV9+Ttq5k9FFR06usEarJXHs0cQeOoyyTz8h74H7SBh7NKlnnOmznYqi4N6xBvvyT/FUlmIcMgHjQSegMXTsCpmhxjBoPK7Nf2Jf+j5Rx04PtzneMsGvv0jV5ioyrriKuMOOoKysqNXtaTQaHnrocZ555gnef/9tjEYTGRkZXHfdTVitVi6+eDIajYbp068jJSWV7a0YkJxxxjk88MAcpkw5h6ysnvTq1YeYmPAvutP4KhQhhPgSuAd4Q0p5qBDicmCClDI4eXq+oZSWVvl8cDDKGqzaVMZrX6/j2Zlj0GrDE64pfusNHIU7yLz9rr0mo/a9XsVeg2KvRRPXulvetmLduJGd77+Du6qSjMuuJHrAgbMO3CWbsf/5Ce6STRgGHYvpkFNaXKka7NIVkUYgr9djKaLms9mYj7kaQ89hAWmzVXbY7RS9+hJWuZbUkdkkTvbmd5SVFZGamoFOp92vrEEk4Ha7cblcmEwmCgp2cP310/ngg88wGAwtn3wALJYmyxr4/A/sz0j+CuApIEMIUQD8Blzlx/kdkno913A5eOuWLVQu/Z2sWbNbzDawfv887sL1YIhCl5KJNiUTbUoWupQstEndg74SNConh+zZ97Dr6y/Z8fQTJJ90Cimnnr6f3W5LIY7ln+Ha/jf6nNHEHH15xGZ+dCS0iRkYD52I/bd30Gf0R2MK/V2hq6qSwueexmO1kjpYT8yI40JuQ2ux221ce+1VuFwuQOHGG29rs4MPBP6seC0B9soJEkK0b8XjACDzLAzvH57lAorHQ8kH75IwekyLogjuXfm4CzcQffpdKA4r7l35eHbl4VyzCLulCNCgTeyKNiULbXJW3Y9AFtrohIDarNHpSJ14FlH9+lP82stYcyUZl1+JPjEJT005jpVf4JS/o88aQvRZ96NLDv/ag86EcciJuLYsx77sI8xjp4W0b8fOnRQ88yT6hAS6nn8Kzj+9qZ3thejoGF5//d1wm7Efvgp5dwe6Af9KKR1CiC7AtcBUWlGkrKNgtbvYXlzFlOP7haX/yiW/4SwpocfMG1s81rn2e3RZB6OrE1vQZx7U8JricuApL8C9Kw/Prjzceatw/PMVOG1oohLQpmR6R/v1fwldGpaXt5aYgYPInnMfRa++zPZ7ZpMyZgA6yyp0ab2IOvUO9O1Y2KI9o9HqMY+9lNov7kPf5/CQZS1Zt2ym8Nmnieo/gK6XXob9p5cx9G5Z4k+lZXxZ8XozcBuwCYgWQrxGXWweGN7CuU3J/72Kt7ywFnheSvlu3bE1QL3k38NSSr/LGIeazYUVGAxasrqEfnLFXVND2eefkjrxjBbz0BVbNc6NfxB1wswmX9fojejSeqFL23M3oCgelKqyhhG/Z1cezs1/olTvAp0BbXKPPaP9lCx0yZlojP7V7dHFRJM2fhC7F26i5Nu/SBw5nNSTrkQboQXPOgu61GyMQyZg++1NYs5+IOiT3NWr/qHolXkkjhtP6tnngqMWV94qolqQ+FPxDV/+my4FhJRytxAiE8gFRkgp1/hwblPyf49KKTcKIUzAv0KID6WULmCrlHKcn/aHFZlnIad7Ajo/Vt4Fil0LvkCfmEjC2KNbPNax4We0cWnouvs+KtNotGji09HGp0OvPZNwir3G6/h35+Muy8Mpf8OzuwA8LjRxaQ0jfu9jJprYlP0meRWPG2fu7zhWfgkaLWmTLibBnUzx6y9jf+JRul5+FYbkZN/fDJWAYzz0NFxbV2D/6zPMI88PWj+Wn36gZP4HpJ0ziaRjvfF3x+Y/0cQkN9yaWJ2bAAAgAElEQVR1qrQNX5y8VUq5G0BKmS+E2OCjg29S/k9KubHuqQNws6d8caYQ4lcgH7iuXlwkksnNt3Bwn9BPCNrz87H8/COZt9zeYo0YxePGufZHjENPCUhGjcYUg75bf+i2Z4m44nHhsRR7Qz278nAX5+JcuxjFVgXG6IYRvy4lC7Q6HP98jWKtwnhoXelfnQEDkD3nPopfe4Xt991N12mXEXtw+4nH+krNf6sp/eRjzD17kT7lQrSGyAxHaPRGTGMvxfr1Qxj6jAi4w1U8Hso+/xTLD9+TccXVxA07rOE1Z+4SDP1GRdzq2/aKL06+pxDig7rnGiC70TZSytb+zN8EfCylrF9G1kdKWSaEmAY8gI+ZO+GS/7M73WwtquLiUwYFVVJwXxRFYcOTH5AyaiQZww/sBHU6LabStdS4bKQedixaYxDnyZPjofeeuQlFUfBUl+Mo3Y6zZBuOku0413yDu6aCuENPIG7EaWhN+7xvidGkzLmLogVfUfDCc3Q5+SR6nD/Zr/BNsCUeW4utqJi8t96i4t/VpJ9wPJaVf1P0xCPk3HIzxpTWDxSCer2JQyjfcTy239+k69RH0egDkynicTrZ+sI8Kletov+c2cT13zNgcO4qoKp0Cyln3IB+n+uyWLTodN675vrHYONyOZk+/Qq2bt3MHXfczfjxx2KxlHPvvbOpra1l+PARXHZZ065q4cIFvPPOmxgMBt5//5OG/QsWfM7ChV9hMBi48845dO/eowUrNEGX/ztjn+2XWt1bHUKIs4EjgIZa81LKsrqn89k7vHNAwiX/t357OVoNpMUZQ5qXXfnnMqo3b6XXtCta7DcxMRrLnwvR9xtDZa0HakOdP26GZAHJAn3/PV82Bai0Atam7Yk++nh69OhF0SvzsPy3lowrrsaQmuZTj5GWJ++xWdm18GvKv19UJ5L+AMYuXYg9/mSKXn2JNTffRrfp1xCV07rJ+6Bf75CJuHP/ouSn+ZiGn9Xm5hylJRS9PA9PdTWZt9+Ju2vGXvbbV/6Arms/qomDfa7L5fLgdntCnCevZe7cR1iw4DM8Hm//77zzFieddBrjxx/LLbfMZNOmTfTq1Xu/M484YjTHHTeBSy45v8HeysoKFiz4gnnzXmfjRskLLzzL3LkPt2CDstd75K/8ny8Fyhpqxtdl1fSRUi6ti6n7/XMqhBgHTAdOllJ66vbFALa6Uf1YvHKAEU1uvoU+3RPQh2hEAeCx2Sj9ZD4pp56GPrHlipeOnVtx79yIedzlIbAusETl5HjDN2+8yvb75tD1kkuJHRq+BTr+ong8VC37g9LPPkYXFU33a68nZvCejCZdTAzdr7uBss8/Jf/xR0g/fwqJPsyvhBqNwYx5zMVYv30afe/hbdKFrVq5gp1vvU6U6E/XG27eT8lJUTw4Ny7FOOx0n9qrtTmxO9vm7E0GLdHm5u9QNBoNqampe+1bvXoVl13mHYeOHDmGf//9u0knn5S0///ounVrGTp0GHq9ngEDBpGXt71N9vuCP/J/lwKX460t3wfIBl4Ejm3hvH3l/84CqoBv6mL15+AtY/yaEKISsAOX+X0lIUbmlSNCXFp418Kv0JrNJB17vE/HV638Bn3WIWjjfRsFRxq62Fi6XXs9lu8XUfjSiw3ZF9oIWGByIKxbtlA6/z0cRUWknDqRxPHHNFn3XKPVknb2uZizsil+63Xs27eTfv6UiJNT1GcehD7nCGy/vEH0xNl+p896nE7KPv0Yy88/knb2uSQee3yT8XZ34QYUWxWG3gdM2vMe6/Fwy7ylWO1tKxoWZdLx7MwxfiVP2GxWTCZv6DM2NnavcsMtUVlZSVzcHp3aUAi2+PNtuhZvyuRyACllbt3I/oA0If/XVOXKUmCoH7aEFZfbw+bCSk4bdeAFSIHEUVxE+feL6H7dDT45AY+1ktr1vxN1Yss59JGMRqMh6fgTMfftR9ErL2LdtJGMK6djTI88vRpXhYWyzz6lctlS4keNpts116OP3194el/iRhyOMSODguefIf+xh+l29TXoEyNDK7ge8xGTW6ULWx+ecVdVknnbnUT13n/EW49z4xL0PQ/1ScVLp9Xy2NUjAzKS9zc7zmQyY7fbMZlM1NRUE+/DZ1xPXFwcmzfvCVRo27jexBf8uTqHlNJJXTZMXbgmMEWd2xlbiypRFIXe3Xz/cNuCoiiUfPg+sQcfQsygwT6d41z/M4akDHTdIkt7tbVE9e5N9t33YkhOIW/uHKpWLA+3SQ0oLhe7v/0/tt15O46dxWTNupuuU6f55ODrMWVmkX3XPWgMBrbffw/WLVuCZ3Ar0JhjMY26EMfKL/BYin06p2rlCvLum4M+MZHsu+87oINXnHZcW1ZgyBnls03RZgNJcaY2/R0oVNMcQ4YMZdmyJQAsW7aUgw/2fXw6aNBgVq36G7fbjZQb6BGCsuD+jOS/FEI8BcQJISbhzZ9/JzhmRTYyz0KvjHiMhtBI3NWs+gdrrqTn3Ad9Ol7xuHCu+5HEMefi6kBpaLroGDKmX4Plpx8ofu0VajdsIO28SWFNQ6xe/S+lH32Ax24n/cKpxI04otWpf7q4OHrccDOln3zEjkcfJP3CqSSMGhNgi1uPofdwXJuWYfvtTaJOua3ZEs++hmca49q2Eo3BhC4CdQFmz76dDRvWEx0dxfr1azn//Iu4//45zJ//PsOGDad37z5NnrdkyW98/PGHFBcXMXPmdGbOvJHevfsyYcLJzJhxOXq9nttvnx10+32uQgkghDgBOA5vKuViKeU3wTLMR8JShfLJj1bRMyOOM49q+sMNJB6Hg213zyJh1BhSTvVtQsq5aRm2Je/SffpLVNa0T6GDlrBt20bRyy+iNZvIuHIGxq5eyb9QZdc4iosp/egDatevI+n4E0k+6RS0PghK+0rl0iXsfOdNEsYeTdo55zUbogt1NpGn1kLNx7MwjTgb48Dx+73eODyTceWMA47eG1P7v8fQJvfAfOTkZo+J9CqUwSKUVSiRUi4CFvlzTkfD7fGwsaCC40eEpmRP+SLv72jSCRN8PsexdjHG/mPRGkxA5KQTBhJzz55k3X0vJe+8yfa5c+hy4VTijxgZ9H7dViu7Fy6gfPH3xBw8hOy5D2JMC/z8QPzIURgzMih88TnsO/LJuGo6+rjQhAcPRIMu7NL30WcN2as6aOPsmR5NZM80h6d6N+6CdZiOmBQss4PODTfMwOl0NmyPHn0UkyZNCaNFe/Anu6YISGeP14jGuzp1CzDT11Ww7Z3txdU4nR76dg9sdcamcJaVsvv/FpJxxdVojb6FJNwlW/CUbMYwvuNXgdZFRdH1iqup+PUXdr79JrUbNhB3dXDSRRWPxytU/vkn6GJj6T7zRmIGBje0YO7Vm6y77qHopRfIm3sv3a65DnNWdlD79AV9v9HoNv/ZoAuruFx7wjPnnEfiMcf5FbJybvoDbYq3FlJ75amnXgi3Cc3iz8TrV8BpUso4KWUccCrwDXA38GowjItEcvMtZHeNw2wMfppb6UfziRL9iTnE94kdx9rF6HsOQxuX2vLBHQCNRkPi2HFkzbob66Zc1t0+C3thQUD7sG7eRN6Dcyn9+EOSTzqV7LvvC7qDr0efkECPm24l5uAh5D/8AJV/LgtJvwfCqws7FXeRxLpiEfmPPEj1qr/JvO1OknyIvzdGURRcG5f4NeGq4h/+OPmRUsr/1W9IKf8PGC2l/B3oNHXlvfnxwU9vq1n7H9WrV5E+6QKf/2k8tRZcm//EMLj9CC0EClNmJtl33UN0r17k3X8vFUt+a3ObLks5Ra+/Qv4jD2LOzqbnAw+TdOxxIc9j1+j1dJlyEWmTzmfnm69R+slHARNGby3auDRcySMoeG0++rjYFrNnmsNTtg2PpRh93yOCYKUK+BeT3ySEeBT4qG77XGCzEMKIt9pkh8fjUcjdUcG4ocEVslBcLko+fI+k405omFD0Bef6n9EmdUPXNTz17cON1mym97Uz0PfOoeT9d7Fu2ED6BRf6PSHqcTqxLP6OXQu/xpyVRdZdcyIiTJJ41DhM3bpTOO95b5z+8qsgDHV69mTPLCWhfypxA80+x9/3xZm7BF2PwWijI2tdQEfCn5H8BXgXLd0FzAZ21e1zA8cE3rTIY0dpNTa7i5wewY3Hly/+Do/NRsopp/l8juL2pk0aB/kXD+1oaDQaEkaPIevOOdi2byXv/nux5+f7dK6iKFSv+oftc+7C8uMPdJl6MT1uvSMiHHw9UX1zyLrrHjy1teQ9cB+1eXkh7d9RWuINz/z7D5m33UnqJTfi3v4Pzm0r/W5Lcbu8d579IjdU43K5uPrqaZx44jh++mlxk8eUlZUybdoUjjtuDBs2rGvYX1Cwg2uuuYKrrprGV1990bD/q6++4KqrpnHNNVdQULAj6Nfgj/xfLfBYMy9XBMacyEbmWcjsEtuqBRS+4rKUs+vrr+hy0cV+jUBdW5aDx6Pe9tZh6t6drDvnUPLhe+Q9eB9pky4g4aixzf4AOooKKZn/AVa5gaQTTyJ5wsloTcEVy2gthqQketx6OyXvvcu6WXfS5ZLL9yrVGywasmf6D9gre8Y47HTsv7/rty6sO38NituFPjtyF7vrdDrmzn2UBQs+a/aYuLh4nnrqeZ5//um99s+b9xwzZsykX7/+XHXVNMaN86acfv31lw0Fyl566XkfCpS1DX+yawTwEDAAaPj2Syn9D8S1U3LzLYjM4NarKf3kY8zZ2cSNONyv8xz/LcYwYJwql9YIrclE14svJVoMYOd7b2OV60m/8GJ0UXsUrNy1tez6egGWHxcTe8hQet7/kM8VL8OJ1mCky8XTSOqfw/ZX5mGfcBIpp53Roph7a9hrcVMT2TPGIRNwbfnLb11YZ+7vGPoMb/V3VrHXoLgcrTq3Ho3eeMAfpqYKlO2LyWTC1MSAID8/jwEDvBP0Q4cOY926tQ3PI7JAGV65v+vxZtKMBi4BQi/nHiYURUHmW5h6Yv+WD24ltbmSqr/+JHv2vX6FXNw7N+Ep24bhuGuCZlt7Jv7IkZh79aLwpRfJm3sPGVdNx9Qjk8olv1H2+afo4hPocf1NRA8YGG5T/UKj0dBlwom4k9IoeulF7Hl5dL3sSnTRgYvTNyxuqq5qtvaMVxd2GrVfzEXf9wj03Vt+HxVbdZ3E322tskvxuKn+4GZwWlt1fgOGKGKnPt9mzeKm2bPQNC4ujsrKyrrnkVugzCSl/EsIoatTbXpcCPE3cG9zJzSj8ZoKvAvE4V01e0/dsacAd+J9Z2ZKKf9qstEwUbirlmqrk36ZwYnHK243JR+8R+K48Zgy/csXdvy3GH2vw9DGqpJ5zWHsmkHWrNmUfvQh+Q/OxdClK67yclInnkHC2KNbVNiKZKL7DyBr9hwKX3iOvAfvo/s1MzF2zWhzu82FZ5pCl9oT45ATsf36JjFn39+iLqxzy/I6ib/WCbZrtDpiz388MCP5oBUJ2zNQq66uJicnHkVRQl6gzB8nb61z2quFELOBYh/Ob0rj9TbgDSnlJ0KI/wkhBgISmAscBcTjzeAZ7YdtQSc3r5zuqTHERQcnHFLxy0+4KyykTNxXo+XAeGrKcW35i6hTVdHjltAajXS5cCrRAwdiz8sj6bgT0MWGXoQ9GBhSUsm8bRY733mTvAfuo+tlVxI7pHXyiS2FZ5rDeOjpOLeu9EkX1pm7BEPOyDYlCWhMMX7NAYSazMwspNxA3745rFr1NxdccBEAb731Gm63m02bNkZcgbKpgA6YgTdsMwCvA2+WpjRe8Trvu+ueL8Tr2D1ArpSyCqgSQhiEEGYppc0P+4KKzLfQL0j58a6qSsq+/Jy0c85DF+3fl9a5/ie0KZmq6LEfxA0bTtywlmuWtze0JhNdL7uS8u++pfDF50g59XSSTz7VL0fqS3imOTR6I+ax07B+/fABdWE9lqK6Vdk+C8CFlX0LlE2fPnOv110uFzfddB3btm1h27atHHPMcUyaNIWrrrqGhx+ei8vlYsKEU4iP90YBQl2gzCcnL4TQAvdJKacANuCeNvQZI6WsD6RZgF5AMlDe6BhL3b4Wq/GHQuNVURQ27qhg2qnB0XPdOv9dorplkHXyCX5NnCkuB4UbfiZx3IXEJO3/4xCpeqfBpLNdc1PXm3TeWaSIvmx6+mk8xQX0njEDXVTLmVq7l/1J/ovziB88iF73zEbfmrucxEMozz8O2+9v0XXqI03qwlas+Qtjj/4kZ/X0q+lwaLwCPPjgowd8Xacz8vzz+6uiZmdnM2/ea/vtP+uscznrrH1lNg5E8DVekVJ6hBA9hBDRdamUbaG20Sg9AdiN18E3HibX72+RUGi87txdS3mVnR7JUQGv+GfbuoXSH38i6467qKj078bFmfs7igKOjENwNmFXpOmdhoLOds3NXm/PHDJnzaHwhWdZc/ssus24rlmhlabCM9UuzX4aqz4zZCLujSso+fkjTIeduddLiuKhZs0vGIee6vfnFB6N172ZP/89fv/914Ztg8EQgro1QdZ4bUQp8LcQ4lsalTaUUs7yq0f4DTgJ+ByYAMzCq+nar07rNQ5wRVqopktyNAmxgc2bVjweSj54j/iRozE3oRF5wHMVBcea771pk7rIlsNTCQ/G9HSy7riL4jdfI+/+e8m48ur9RGfaEp5pDo0xyqsLu+hp9L2G71V4zF0kUawVPkn8RSKTJk2JmOqSvuLPPc9CvHny/+CdKK3/OyB1Gq8XAXfXlUV4FLhcCPE78K+Ucq2U0oU3BLQYr/O/yZ+LCDYyz4IIQlZN5dIlOHYWk3rWAac2msS9cxOe3TswNFHTW0WlHq3ZTMZVM0g6/gQKnn2K3Yu+oV5DokG5KSmJ7Nn3BsTB16PPPAh93yOw/foGimePpoEzdwn67EMjesK0o+HPite36zRd+0gpl9bJ/7X4I9GExit4R/D7HvcV3kqXEUdufnnABULctTWUffYxKRPPbFWdcOd/36HvM1yt+aHSIhqNhpRTTsOUmUXxay9j374dXVxcq0sD+0q9LqxzzSKMQ07ySvxtXUHUMVcHvC+V5vF5JC+EuBRYgDfHHSAb+DoYRkUSZRVWdlXaA155ctdXX6KLTyBx7NF+n+up3oVr60qMnbDapErriR1yCFl33o0tb1tD7Rl/SwP7Q70urH3FF3gqir0Sf3ojuh6+6RSrBAZ/YvLXAsOB5QBSyty6kX2HRuZZSE0wkxwfuGrK9h35WH78gR4339aqRTjOdT+hTe2JLj348oMqHQtj1wyy58wFRfFZiKYtNOjC/vomaPXo+x4ZxMVHKk3hT0zeIaV0UrdWty5c47tAbDtF5lsQmYEbxSuKQskH7xE3fATR/UTLJ+x7vsuBc/3PGAcfGzCbVDoXWoMhJA6+HtPoC3HvysddsBZDTvAlGiOBZcuWMmXKOZx44rgDHve//33FpElncuGF/qRU+oc/Tv5LIcRTQJwQYhLeidh3gmNW5JAb4EVQlUuXYNu+jdSzz2vV+a5Ny0CrQ997RMBsUlEJJtroRMyjL0KfPRRdauDKNtc6rVjsFW36q21r7ZtmGDhwEK+//i5pLej/jhw5hvfe+zgoNtTjz8Trg0KIE/DWjx8OPCml/CZolkUA5VV2SsqtARvJ2/K2U/L+O6RPugBDkv/VLBVFwfHf9xgGjkejC606kYpKWzD0PQJDAMtguz1uZi99CJu7bZnWZp2ZR8fMQddMCMlisTBnzh243W60Wi333vsQmzbl8vrrL2MwGBg+/HAuumj/ypv1q1tbIqkVfsBf/Ck1PAX4Skq5KIj2RBS5+RaS4kykJUa1fHALuKuqKHzhWeKPHEnCUWNb10aRxGMpxDBgXJvtUVFpz+i0OuaOvAOHp20FyoxaY7MOHiA2NpYnnngOvV7Pl19+xv/+t4Bvv/0/XnjhFRISEnG73c2eGyn4Mxw8CLhTCLEZ+BT4UkppCY5ZkYHMt9AvM7HN2QeK203RK/PQJyaRPrn1Cymc/32Pvs/haKODq0ylotIeiDZEEU3bB2AHorKygieeeBiLxUJNTQ2DBx9ESkoKCQneu3tdO6he6nNMXkp5m5RyAN7iYv2AJUKIDh2ukXnlAQnVlH3+CfbCQrpdfU2rRaA9VWW4tv+NcfDxbbZHRUXFN7777huGDBnKCy+8ysSJZwIadu/e1VAb3hNmQXVfaE2VH0vdXxXessAdksoaB0W7atucH1/55zIsPyym2/Rr0Ce2vi3H2h/QpvdBl9azTfaoqKj4zmGHHc7//vcVt956Pbm5Eq1Ww3XX3cgtt8zk2muv5L333mryvA0b1jFz5nSKi4uYOXM6K1Ysb/K4JUt+2+u4LVs2Bfwa/InJ3wWcAdTgDdecJaUsCLhFEUJuvoX4aANdk1tf/c2en8fOt98g7fwpRPVpfSlgxWnHueEXzGOmtroNFRUV/+nbN4e3356/3/7hww88idy//0CeeebFFtsfNWoMo0aNabV9vuBP7KACOFVK2WL5345Abhvj8e7qagpeeJb4I0aSeNS4Ntni3PQHGoMJfa9hbWpHRUUl8Mydezc7dxY3bA8cOGi/mvMAN9wwA6fT2bA9evRRISl25k8K5XP1z4UQ/YFzgbOllAf702GdElT9T1ws3pDRs8BsIL+ur3H+tBkMZL6FMQe3TkJNcbspenke+oRE0iZf0CY7FEXBWZ82qVXTJlVUIo3Zs+/z6bjglyRuGn/CNQI4D68aVF+gPnzjF1LKdcC4ujZnsKeO/Dwp5eP+thcMamxOdpRUI7Jal8Na9vmn2At3kD37HrSGtpUBdheux1O5E0P/1qVdqqiodG5adPJ1sfizgUq8sfiTgV+llE8GoP/JeMsQHwVcJoSYCHwqpXw6AG23mo35FUSb9XRP878catXyP7H88D09br4NfWLbFzp40yaPRBvVYee4VVRUgogvI/kZwFa8IZavpZQ1Qog216wRQvQEdFLKLUKI3XirW+qBr4UQy6SUy3xpJxjyf9tKqhnYK4XkJiT1DkTttm3sfPsNsqddQvphQ/w6tylclp1UbV9Fl6mPYGyF/Fdnk8KDznfNnel6wyX/F36CL//XDe9I+1zgQSHEP0CMECKuTni7tUwC5gM0WlTlFkJ8CQwFfHLywZD/W7OplBEDuvjVtru6mryHHyPu8CMwjhgVEAk62x8L0WX0o9aUTm0r2utsUnjQ+a65M11vOOT/XC4X1157BVu3buG22+7i6KOPxWKxMHfu3dTW1nDYYSO49FKvIPmSJb/xzjtvoNFomDnzJgYMGNRkm3fccTOrV//DBRdczPnnX+iDFW2T//NF9EORUv4ipZwB9AGewxu2WSuEaEuJg/OAjwCEEAl1jxq8Pygb29Bum7DaXWwvrvYrP17xeCh69SV08fGktWFF615tOm045a8YBqnVJlVUwoVOp2Pu3Ec555zJDfvef/9tTj75NObNe50NG9axdesW3G43r702j6eeep65cx/m2Webj2bfeOOtzJhxfSjMB/xLoURKqQA/Az8LIa7F65ABEEJcI6V83pd2hBCDgF1Syvq8o5uEEMfjLV38q5RysT92BZJNBRUYDVoy031Xqi/7/FPsO/IDMtFajzN3CRpDFPqehwakPRWVjoa7tgbF0bbaNRqjEV1082FZjUZDamrqXvtWr17FZZd5R+8jR47h33//RqvVkpmZTXR0DNHRMbhcLux2OybT/rrQLVWmDDStzsmTUnrwOvx6pgE+OXkp5Vrg2Ebbd+MtlxB2cvMt5PRIRKf1LeZX9ddyyr9fRObNtwdkohW8ivbOtYsxDDpGFVhQUWkCxe1m620347G2rVSwNiqKPk8/75d4j81mxWTyigjFxsZSVFRIZWUFcXF7wihxcXFUVVViMqW1yb5AEMjE6+BoiIUYmWdhSN8Un46178in+M3XSJ98AVE5OQGzwV2wDk/VLoxq2qSKSpNodDp6PfJ4QEby/qqzmUzmhlF6TU018fHxxMXFU129Z4qyurqauFZoNweDQDr5dq8SZXe62VpUybnjWy5B4K6upvCFZ4kbcQQJrdBpPRCO/77HkHMkGrPvISMVlc6GLjoGDhBqCRZDhgxl2bIljB07nmXLlnLFFTPo0SOT/Pw8rFYrtbU16HS6JkM14UAdyTdiS0EFOp2Gnl0PPHvdMNEaF0f6BRcGVAjZU1GMO281prN9W0WnoqISXGbPvp0NG9YTHR3F+vVrOf/8i7j//jnMn/8+w4YNp3dvr9bytGlXcP3109FoNFx77Y3Ntvf004+xYsVfuFwutmzZxF133RtU+wPp5J8JYFthQeZb6NMtAX0LObhlX3yGPT+PrNn3BmyitR7H2h/QdeuPLjkzoO2qqKi0jrlzH95v3xNPPLvfvtGjxzJ6dMsh1uuvvyUgdvmKLyteP+QAoRgp5fl1j28FzqzwkJtvoX/2gSdPq1Ysp/y7b8m8+bZWSfgdCMVhxSl/w3z05QFtV0VFJfSsXPkXb7756l77brrpdnr16h1SO3wZyb8UdCsiAKfLw+bCSk4f3avZY+w78il+4zXSJ51PVE6/wNuQ+zsacyz6rKEBb1tFRSW0DBs2nGHDhofbjJadvJTyl1AYEm62FlWiKNC7W9Mz4u6aGgpfeI64EYeTMG58wPtXFA+OtYsxDjoGjY/pmyoqnQ2324VOZwy3GSHD7Xa1uQ1/qlCOBJ4EBtbtigGKpZTd22xFBCDzLfTuFo9Bv386VcNEa2xswCda63Hnr0GpKccgjmr5YBWVTkhcXCIWSxlarSZkZQ3CjUajoUuXdFxt8PX+TLw+B5wGLJRSDhVCnA2Mbn3XkUVuXjn9mtFz3fXl59i3bydr9j1oDcEZRXjTJkehMYU+JUxFpT1gMkVhMkV1qno9ALGxbbtef+ICSp3cnw5ASvkpdXXh2zsut4dNBZVN1qupWvEXuxd9Q8bVMzAkJwelf7elEPeOte8HhCEAABMTSURBVBgGq3VqVFRUAotf8n9CiBjgdyHEq0AJYAuOWaFl+84qXG4Pfbsl7LXfXrDDu6L1vMlE9xNB69/53w/oug9El9QhIl8qKioRhD9OfiJgB2YCFwDxwCmt6VQIUQP8Vbf5MPAL8Bbessb/ATPqauOEhNw8Cz27xmEy7onHu2tqKHz+WeKGDSfh6GOC1rfiqMWZ+ztRx1wdtD5UVFQ6L/44+dOBr6SUlXgdclvY2ljHtU4GcIWU8jEhxAvAicD/tbEPn5H5Fvo1CtV4J1pfRhsTQ/qFFwVlorUe54bf0EQnoMvySypXRUVFxSf8ickfBPwphFgohLhYCOF7wfX9yRRC/CqEeF8IkQKMARbWvbaQRiWMg43Ho7BxhwXRaNJ114IvsG/fRrfp1wRtohW8PyYNaZMaNW1SRUUl8Pg8kpdS3gbcJoQ4FK/m6xIhRJ6UckIr+u0jpSwTQkwDHgCSgfK61yx12z7RVvm/zQUV2B1uDhuUQbTZwO5lf1K+6P8Qd88mvndwSwtYN62gxlZF6ogT0JoCL+HWmaTh6uls19zZrhc63zW39XpbU7vGUvdXhTcu7zdSyrK6p/OBK4FtQCJQDCQAu302po3yfyvXFZPZJQ6HzUnV5m3kPfc8qedMwtOtZ9DTtGr//B/6fqOotALWwPfV2VLNoPNdc2e7Xuh817zv9for/+fPYqi7gDOAGrzyf2fVpVT6RV2Gjk1K6QbG4pX6+wM4CdhQ99gWWUG/kHnliMxE3LU1FL74LHHDDiNxfPBTGd27C3AXrMM8KjBygSoqKipN4VcKJXCqlLKwjX32B14TQlTizda5DCgD3hJC/AqsB75pYx8+4VEUNu6oYPTgLhS/+jJacxTpU6YGdaK1Hufa79FlDkabmBH0vlRUVDovvlShPFNK+bmU8rm6eHxho9emSSnf8KdDKeVKoKkKXOf6004gKCyrodrqpMvqX7Fu2+pd0WoMfl0MxV6DM3cpUcdfE/S+VFRUOje+pHTc1ej5a/u81q69lMyzcKR2J9WLvyXjqhkYkn2T/Wsrzg2/oolNRtdjcEj6U1FR6bz44uQ1zTxvartdUbBuE6O3/ETaOZOIFv1D0ueetMlj1bRJFRWVoOOLl1Gaed7UdrvBVVND/z8+x93vIBKPCV3NGNf2f1DstRj6jQpZnyoqKp0XXyZeDxJCFOIdtafUPaduOzgVu4KM4vGQ99I8rBoD/S65JCQTrfU4//segxiDxhgVsj5VVFQ6L76IhgRWxDQC2PX1Auxbt7BkwBmMTYoNen+Kx4O7ZBOuLStwF0nMR10S9D5VVFRUILBC3u0G+7atrBl2Kt0zgreiVXE5cBesxbXtb1zbV6E4rOi6D8R87NVoE7oErV8VFRWVxnRKJ9/tuhv4//bONEiu6jrAXy+jGa2jlZEmWhHyEUJI49FmjcDGYDA2MlABgrEDMVguVBWKpeykCCjGxs5iKshQNrYrgCtOZAMBm4CFQyoG40USSBGCgLDOIBEtaAHtuzTT0y8/7uuZNz3T26in1/OpRt3vLu+ec9/t07fPe/fc136wmutSbBLSV7xTx4htf9MZ9vffgnCE6MTZ1F5wI9Hx55uLxjCMglOVRn7f4VMcPHo65U5QuRA/upfY1g3Etr5Ox55WQoPqiU5qZuBldxAZJ4QiVdnFhmGUCFVpgVp3HGLM8DpGDqvLua7necT3b/fdMK8T37+D8IjxRCd/lNqPfZ7w6EkFvZFrGIaRjqo08rr9EDJhRNblvXgHHXtanWHf+jre8QNEGqZRM20R0UubCQ87qx+lNQzD6DtVaeRbdxxiccvktGW89tPE3n/LGfbtb0Ksjej4mdTOuZrIxNmEB/YpAKdhGEZBqUojP39GA03TRvdIj588Qmyb71/fuRGitUQnNVH3iVuI/slMQjW1RZDWMAyj7xTcyIvIQmA50AYcw+0XeydwHbAX2KOqn+9PGf7042d3vo8f/qDTDdPxwWZCQ0cRndTMgFmfITJ2GqFwJM2ZDMMwSptizOS3AZeo6gkRWQr8pZ9+n6o+UwgBOg68T2zzq8S2bSB+cCfhUZOITm6m9oIbCY+cYDdODcOoGApu5JPi0bcBMaAGWCYidwA/UNUn+lOG/3j1h4wODaB5+oUMnjyX8NCerhvDMIxKIOR5xYkx5m/g/V/A5YCnqvtFpB54GbhaVXdkcRqvvb0j6zYjkTAdHXFWtv6a/9z8MqdibbRMmMMnJ7cwZfjEipvBJ/StJqpN52rTF6pP52R9a2oikEME4KIYeREZBKwElqnq6qS8B4DfqGo2u0N5e/cezbrd4F6JHfEONu7fxOrda3l73yYah4xlUeMC5jU0MaimMjYJrra9MKH6dK42faH6dE6xx2vWRr4YN16juA28v5cw8CJSr6qH/byF9NycJO9EwhFmjTmPWWPO49Dpw7y6ez0vbf8dz25eSdOYWSxqnMc5w8+uuNm9YRjVRTFuvN4AfBwY5vvgXwBERGYAEeBnqtpaSIGG19Zz+eSLuWzSRbQe3MLqXWv5/huPMbJuBAsb57Fg7Fzqa3PbId0wDKMUKJpPPk/02V2TiWPtx1m3ZwOrdr3GByf2cv7oGbSMm8eMUUK4THZ0qraftVB9OlebvlB9Opedu6ZcGFIzmE9OuICLxi9i65EdrN61lsc3/pRB0YEsHDeXhePmMWpgWe6ZYhhGFWFGPgOhUIgp9ROZUj+Ra6YtZv2Hb7J61zpe3Poy00dOo6VxPuePnkFN2LrSMIzSwyxTDtRF61jUuIBFjQvYeWw3a3at48lNv+Cp0LPMH9tMS+N8xg22DUEMwygdzCd/hrR3tPPmvo2s2rWW1oObObt+Ei3j5tPcMJvayIC8tpUr1ea7hOrTudr0herT2XzyRaYmUsPchibmNjSx98R+1uxexy/fe5Fn3n2euQ1NtDTOZ+LQ8fYopmEYRcGMfB4ZM2gUV069nCumXMo7B5RVu9byT+sfYdzghopbaGUYRnlg7pp+JrHQas2utRxuO8LU+ilEw1FCoRAhQl2v0CMNQoQT70MQ9tNCoWC9xHt6pNXV1dB22oV9CBOCpF8TqY56/OYI9Z4X6lEyUC6LHy6ph17vGV7K9C7q6mo4daq9swEvUMoLNOolnc/rTPe60r2kMi6hM62zhtetREo5Uymc/hOYoo6fPKA2StvpWFZny/RJTyl3NpWh1zEaPA774zjUeeweRe7KCwXyUtcbPLCWk6faO497v07dr0Xw+ibKd79+gSvvJV9hej1f45CxzB/bnEXHnBnmrilxkhdabTm81R9wnttKMDBoPD+t819iYCWneR6eF3d1/QEbT5wzcI5oR4S2tlhnWpDuH+igsUvWwOvlXS8GwUuTl4aeXxSdGTmVT6RGT0aIdYtnFAp84XR9obrDxPvA/4kvzG5fWMEvuYTx6S5PZ/mEMepd/F4kTpGbNrur/XDC0CVJmMtJM/Vp9jluPCfGdzweJxYYe3HPw8PFYEmM/Z6fBS8pr6ss/rgOR0K0xzpcG57XdQW6XeeutG7XKOn6JvouMZEKJdUlUDc4PiDEoJqBKXuolDAjXyDCoTDTR05j+shpBWuz2m5QQfXpXG36QnXqfCaUx9JNwzAMo0+YkTcMw6hgSspdIyJfAW7GbSZyi6q+V2SRDMMwypqSmcmLyEhgCS5C5V8B/1hciQzDMMqfkjHywHzgFVWNqeo6QIotkGEYRrlTSu6akcDBwHFWX0DDh2e/uCgSCedUvtypNn2h+nSuNn2h+nQ+U31LycgfBGYFjrPavNXf7zBrwuHcypc71aYvVJ/O1aYvVJ/OZ6JvKRn514Cvi0gEmA28m0UdCwhjGIaRhpIx8qp6QER+AvweaAe+XGSRDMMwyp5yj11jGIZhpKGUnq4xDMMw8owZecMwjArGjLxhGEYFY0beMAyjgimZp2vySboYOCIyD3gY9/jl36nqyuJImV9S6Swiw4GfAwNwOt+uqq8XTdA8kSnOkYjUA1uApar6TBFEzDsZxvVZwCPAKGCPqn6hOFLmjwz6/gVwGxAHfqaqDxdHyvwhIjXAK8B5wJLkcSsii4F7cbs33OFHBshIxc3ks4iB813gOuBS4Fv+c/llTQadTwM3qeqFfpnvFF7C/JJlnKOv4dZeVARZ6PwgcLeqXlwhBj6Tvn8DXAQsBG4VkQEFFbB/iAHXAg8lZ/h26lvAZTj79d1sT1pxRp40MXBEpA6IqupOVT0GtAKF28Wj/0ips6qeVNWd/mEbbiCVO2njHIlIA3A2kNVMp0xIN64jwHTgGyLyWxG5vlhC5pFMsaw2AUOAgcBJslwhX8qoqqequ1NkTwNaVfWo/3mu8e1ZRirRyKeLgTMSOBQ4PuSnlTsZ4/6ISAhYDjxQKKH6kUz63ksF/GJJIp3OZ+FWiX8b+Cxwtz8TLmcyXeNngA04Y/8TVS17I5+B5P7I2nZVopE/CAwPHHekyasHDhRCqH4mnc4JHsbNjH5TGJH6lZT6isgUYLiq/m/BpepfMo3rbeo4DqwHzimkcP1Aums8FLgHN7ufClwjIhMLK17B6bPtqsQbrylj4KjqSRGJicg44AjuJ9Dm4oiZV9LG/RGRe4CYqvbw9ZUp6fT9KDBVRF7EGbqjIvJHVd1YBDnzSbpxfUpEdvpuqn3ATGBbccTMG+mucRznejyuqnEROQEMK4KMheRd4CMiMhgYivs8n8qmYkWGNRCRpcBNdMXAuQD4P1X9rYgswN20CAH/oKrPF0/S/JFKZ+A9YCvwB9xd+Z2q+sUiiZk30l3jQJlvAG9X0NM16cb1XJw7bgDwU1X9XvEkzQ8Z9L0TuAE3pteo6l3FkzR/iMi/A3OBY8CLuNn6s6qqInIl7oazB9ylqlk9WFCRRt4wDMNwVKJP3jAMw/AxI28YhlHBmJE3DMOoYMzIG4ZhVDCV+AilYRhGSZMpTk2g3GTcuoe3/KQ7VfWNXNoyI28YhlF4EnFqbs2i7BpVXdzXhszIGwVFRP4HN+7G4p5/3g/sU9VPZVF3AXClqt6bY5tLcEv+9wSS5+RjKbyIXAwcymdkTxG5kK5n3muA5ar6WJryK4CP4Z6tBrhHVX+VL3mM/KOqHrBbpCskj4jMxl33CKDAUj9rnoj8Hjeb/6qqnsylLTPyRkFR1bnQuVBpj6r+KJgvIpFUxtdf/NHXyJKPqeqyPtZNx8W4xWb5DN/8GHCFqm4WkVogmyX7S1X117k0kq6vjaLwEHCDqu4RkQdxESdfAc5R1aMicj9wB71HXU2JGXmj6IjIp4C/xq3ki4jIdcAvcPE5AG5T1dV+uS+p6p+LyLeBMbgl/A3Arar6Uo7tLgEu8etPAu5T1RUi8jxuNfQav9x64EpcaNtluCX17+BWHy4B2kTkNuAa3GfqEWAE8CEuzPNeEXkfWAEsBj4ArlfVfSKyHBdUrA34F1Vd7tfdC6Cqp/GX9IvIR4Af45bwv4OLsX4ihW4j0vRhZ18DGX9BGQVjJvCkP7sfglutfRoXLhzgSeC+XE9qT9cYpUIzcKPvtjkOfE5Vm4GrcbHSe2MCLt74F4GvZzj/EhF5w/8LhrI4F7jCP8/9ftrTOIONiEwFTvnhXZcBl6nqbNzMeStu1n2/qjap6hacgb9ZVecA/4qLiJlgu6rOBH4FLPNjzXwOOFdVZwGP++UeBbaIyFMicmNgz4PvAw/4ZXcBtwfO/aOAfgMz9GGwr43S4S3gWlW9yP/Fu0JEgjF5PkFSXKpssJm8USr8TlU/9N+HgAdFpAUXfXBKijovqGqHiGwAJmc4fyp3zX/7Ps6dIlIrImHgeZxx/hru5tjP/bKrgMdF5AlcqNtu+LtwLQR+6c/GEr7VBE/6r0/4bRzAzeAfFZHngBcAVPVeEfk34NPAV3EuoZuBmYFYSyuAbwbO3c1d47t5UvVhsK+NIhGMUyMi84G7gCdEJIoLwnY7MEVEvom733IQ+FKu7ZiRN0qFoNvhJv+1CTfYj6Sok/gZG8cZ1L5wOvDeA8KqelhENovIHNyM/lo//ytAC3AV8KqIzEo6VxgX8rcpRVte4NVT1Xa/jU/jdL4K5/5BVTcBm0TkKVzM9Jtz1CtdH/bq4jEKi6r+WS/JlyYdbwTOaItSc9cYpcgw4EP/puD1QFY74OSZp3EzeU9Vt/tpU1R1Fc4XP8j/O4oL/YqqHgBOisglACIyQETODZzz+sDrH/y46ENV9TngbpxBRkQ+E6gzC0i0/3Yg7wu4yKKpKIU+NEoAm8kbpcgKYKWIXAW8hHvM8kxZ4m+EnOCSDOWfA/4Z+NtA2kP+piQAj/pPPDwHPO1vLH0NLvztD/0bqhHcDlV/9OtMEpG38W+84m6KPuvvT+rhNsIA+LKIPITb1u4EcIuffhvwYxH5Du7Ga7r7EP3Rh0YZYqGGDaMA+E/XTFbVSthj1ygjzF1jGIZRwdhM3qgYROSzwN8nJb+Q6wpZw6gkzMgbhmFUMOauMQzDqGDMyBuGYVQwZuQNwzAqGDPyhmEYFYwZecMwjArm/wG3k1H5OGd4cwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=figsize)\n", + "sns.lineplot(data=full_q4_data, x='Train_EnvstepsSoFar', y='Eval_AverageReturn', hue='Config')\n", + "plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))\n", + "plt.savefig(os.path.join(export_dir, 'hw3_q4.png'), dpi=200, bbox_inches='tight')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 5" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ConfigTrain_EnvstepsSoFarEval_AverageReturn
010_105011.08.888889
110_1055076.07.228070
210_10105143.07.846154
310_10155195.08.826087
410_10205250.08.760870
510_10255313.08.183674
610_10305352.08.204082
710_10355417.08.200000
810_10405465.08.431373
910_10455502.08.695652
01_1005011.012.264706
11_10055322.070.000000
21_100105611.062.285713
31_100156636.0144.666672
41_100207338.085.000000
51_100257857.0581.500000
61_100308113.01000.000000
71_100358880.01000.000000
81_100409022.01000.000000
91_100459022.01000.000000
\n", + "
" + ], + "text/plain": [ + " Config Train_EnvstepsSoFar Eval_AverageReturn\n", + "0 10_10 5011.0 8.888889\n", + "1 10_10 55076.0 7.228070\n", + "2 10_10 105143.0 7.846154\n", + "3 10_10 155195.0 8.826087\n", + "4 10_10 205250.0 8.760870\n", + "5 10_10 255313.0 8.183674\n", + "6 10_10 305352.0 8.204082\n", + "7 10_10 355417.0 8.200000\n", + "8 10_10 405465.0 8.431373\n", + "9 10_10 455502.0 8.695652\n", + "0 1_100 5011.0 12.264706\n", + "1 1_100 55322.0 70.000000\n", + "2 1_100 105611.0 62.285713\n", + "3 1_100 156636.0 144.666672\n", + "4 1_100 207338.0 85.000000\n", + "5 1_100 257857.0 581.500000\n", + "6 1_100 308113.0 1000.000000\n", + "7 1_100 358880.0 1000.000000\n", + "8 1_100 409022.0 1000.000000\n", + "9 1_100 459022.0 1000.000000" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def read_q5_data(question):\n", + " full_data = pd.DataFrame()\n", + " Y_tag = 'Eval_AverageReturn'\n", + " for folder in os.listdir(data_dir):\n", + " split = [s.strip() for s in folder.split('_')]\n", + " if 'InvertedPendulum-v2' in split and question in split:\n", + " config_list = split[split.index(question)+1:split.index('InvertedPendulum-v2')]\n", + " config_list = '_'.join(config_list)\n", + " logdir = os.path.join(data_dir, folder, 'events*')\n", + " eventfile = glob.glob(logdir)[0]\n", + " \n", + " X, Y = get_section_results(eventfile, Y_tag) # Y is Train_AverageReturn\n", + " data = pd.DataFrame({'Config':config_list,\n", + " 'Train_EnvstepsSoFar': X, \n", + " Y_tag: Y})\n", + "\n", + " full_data = full_data.append(data)\n", + " \n", + " return full_data\n", + "\n", + "full_q5_data = read_q5_data('q5')\n", + "full_q5_data" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=figsize)\n", + "sns.lineplot(data=full_q5_data, x='Train_EnvstepsSoFar', y='Eval_AverageReturn', hue='Config')\n", + "plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))\n", + "plt.savefig(os.path.join(export_dir, 'hw3_q5_11.png'), dpi=200, bbox_inches='tight')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ConfigTrain_EnvstepsSoFarEval_AverageReturn
010_1030000.0-75.416679
110_1060000.0-73.736649
210_1090000.0-75.464218
310_10120000.0-80.089256
410_10150000.0-41.744469
............
14510_104380000.0143.853867
14610_104410000.0164.700409
14710_104440000.0161.115509
14810_104470000.0168.482147
14910_104500000.0158.386398
\n", + "

150 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " Config Train_EnvstepsSoFar Eval_AverageReturn\n", + "0 10_10 30000.0 -75.416679\n", + "1 10_10 60000.0 -73.736649\n", + "2 10_10 90000.0 -75.464218\n", + "3 10_10 120000.0 -80.089256\n", + "4 10_10 150000.0 -41.744469\n", + ".. ... ... ...\n", + "145 10_10 4380000.0 143.853867\n", + "146 10_10 4410000.0 164.700409\n", + "147 10_10 4440000.0 161.115509\n", + "148 10_10 4470000.0 168.482147\n", + "149 10_10 4500000.0 158.386398\n", + "\n", + "[150 rows x 3 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def read_q5_data(question):\n", + " full_data = pd.DataFrame()\n", + " Y_tag = 'Eval_AverageReturn'\n", + " for folder in os.listdir(data_dir):\n", + " split = [s.strip() for s in folder.split('_')]\n", + " if 'HalfCheetah-v2' in split and question in split:\n", + " config_list = split[split.index(question)+1:split.index('HalfCheetah-v2')]\n", + " config_list = '_'.join(config_list)\n", + " logdir = os.path.join(data_dir, folder, 'events*')\n", + " eventfile = glob.glob(logdir)[0]\n", + " \n", + " X, Y = get_section_results(eventfile, Y_tag) # Y is Train_AverageReturn\n", + " data = pd.DataFrame({'Config':config_list,\n", + " 'Train_EnvstepsSoFar': X, \n", + " Y_tag: Y})\n", + "\n", + " full_data = full_data.append(data)\n", + " \n", + " return full_data\n", + "\n", + "full_q5_data = read_q5_data('q5')\n", + "full_q5_data" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=figsize)\n", + "sns.lineplot(data=full_q5_data, x='Train_EnvstepsSoFar', y='Eval_AverageReturn', hue='Config')\n", + "plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))\n", + "plt.savefig(os.path.join(export_dir, 'hw3_q5_2.png'), dpi=200, bbox_inches='tight')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "cs285", + "language": "python", + "name": "cs285" + }, + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/hw3/cs285/agents/ac_agent.py b/hw3/cs285/agents/ac_agent.py index 8aa4ff98e59cffd16226299269b74c8d16beaa16..37669b88bfa3bb2c47382c0feeaceed33ee9762e 100644 --- a/hw3/cs285/agents/ac_agent.py +++ b/hw3/cs285/agents/ac_agent.py @@ -39,10 +39,17 @@ class ACAgent(BaseAgent): # for agent_params['num_actor_updates_per_agent_update'] steps, # update the actor + for i in range(self.agent_params['num_critic_updates_per_agent_update']): + loss_critic = self.critic.update(ob_no, ac_na, next_ob_no, re_n, terminal_n) + + advantage = self.estimate_advantage(ob_no, next_ob_no, re_n, terminal_n) + + for i in range(self.agent_params['num_critic_updates_per_agent_update']): + loss_actor = self.actor.update(ob_no, ac_na, advantage) loss = OrderedDict() - loss['Critic_Loss'] = TODO - loss['Actor_Loss'] = TODO + loss['Critic_Loss'] = loss_critic + loss['Actor_Loss'] = loss_actor return loss @@ -53,7 +60,10 @@ class ACAgent(BaseAgent): # 3) estimate the Q value as Q(s, a) = r(s, a) + gamma*V(s') # HINT: Remember to cut off the V(s') term (ie set it to 0) at terminal states (ie terminal_n=1) # 4) calculate advantage (adv_n) as A(s, a) = Q(s, a) - V(s) - adv_n = TODO + value_s = self.critic.forward_np(ob_no) + value_s_prime = self.critic.forward_np(next_ob_no) + qsa_value = re_n + self.gamma * value_s_prime * (1-terminal_n) + adv_n = qsa_value - value_s if self.standardize_advantages: adv_n = (adv_n - np.mean(adv_n)) / (np.std(adv_n) + 1e-8) diff --git a/hw3/cs285/agents/dqn_agent.py b/hw3/cs285/agents/dqn_agent.py index 8b071ff8fbf3805e9c59575ec0d6175a15ade563..5cceb95c9c063ee420dbb56f009c53e33292a4f5 100644 --- a/hw3/cs285/agents/dqn_agent.py +++ b/hw3/cs285/agents/dqn_agent.py @@ -46,37 +46,41 @@ class DQNAgent(object): # TODO store the latest observation ("frame") into the replay buffer # HINT: the replay buffer used here is `MemoryOptimizedReplayBuffer` # in dqn_utils.py - self.replay_buffer_idx = TODO + self.replay_buffer_idx = self.replay_buffer.store_frame(self.last_obs) eps = self.exploration.value(self.t) # TODO use epsilon greedy exploration when selecting action - perform_random_action = TODO + # random if minus eps or at start point it will return True or False + perform_random_action = np.random.random() < eps or self.t < self.learning_starts if perform_random_action: # HINT: take random action # with probability eps (see np.random.random()) # OR if your current step number (see self.t) is less that self.learning_starts - action = TODO + action = np.random.randint(self.num_actions) else: # HINT: Your actor will take in multiple previous observations ("frames") in order # to deal with the partial observability of the environment. Get the most recent # `frame_history_len` observations using functionality from the replay buffer, # and then use those observations as input to your actor. - action = TODO + obs = self.replay_buffer.encode_recent_observation() + action = self.actor.get_action(obs) # TODO take a step in the environment using the action from the policy # HINT1: remember that self.last_obs must always point to the newest/latest observation # HINT2: remember the following useful function that you've seen before: #obs, reward, done, info = env.step(action) - TODO + self.last_obs, reward, done, info = self.env.step(action) # TODO store the result of taking this action into the replay buffer # HINT1: see your replay buffer's `store_effect` function # HINT2: one of the arguments you'll need to pass in is self.replay_buffer_idx from above - TODO + # store_effect(self, idx, action, reward, done): + self.replay_buffer.store_effect(self.replay_buffer_idx, action, reward, done) # TODO if taking this step resulted in done, reset the env (and the latest observation) - TODO + if done: + self.last_obs = self.env.reset() def sample(self, batch_size): if self.replay_buffer.can_sample(self.batch_size): @@ -92,14 +96,13 @@ class DQNAgent(object): ): # TODO fill in the call to the update function using the appropriate tensors - log = self.critic.update( - TODO - ) + # update(self, ob_no, ac_na, next_ob_no, reward_n, terminal_n) + log = self.critic.update(ob_no, ac_na, next_ob_no, re_n, terminal_n) # TODO update the target network periodically # HINT: your critic already has this functionality implemented if self.num_param_updates % self.target_update_freq == 0: - TODO + self.critic.update_target_network() self.num_param_updates += 1 diff --git a/hw3/cs285/critics/bootstrapped_continuous_critic.py b/hw3/cs285/critics/bootstrapped_continuous_critic.py index b410eff61452c78589b6c1ecb74ffc70f92be30b..758f7e2dc26e9b8c5f3fbfed5b6c1030963e9128 100644 --- a/hw3/cs285/critics/bootstrapped_continuous_critic.py +++ b/hw3/cs285/critics/bootstrapped_continuous_critic.py @@ -85,5 +85,21 @@ class BootstrappedContinuousCritic(nn.Module, BaseCritic): # to 0) when a terminal state is reached # HINT: make sure to squeeze the output of the critic_network to ensure # that its dimensions match the reward + # print(self.num_grad_steps_per_target_update,'num_target_updates', self.num_target_updates) + for i in range(self.num_grad_steps_per_target_update * self.num_target_updates): + if i % self.num_grad_steps_per_target_update == 0: + value_s_prime = self.forward_np(next_ob_no) + targets = reward_n + self.gamma * value_s_prime * (1-terminal_n) + targets = ptu.from_numpy(targets) + # print("In it ",i) + + predictions = self.forward(ptu.from_numpy(ob_no)) + + assert predictions.shape == targets.shape + loss = self.loss(predictions, targets) + + self.optimizer.zero_grad() + loss.backward() + self.optimizer.step() return loss.item() diff --git a/hw3/cs285/critics/dqn_critic.py b/hw3/cs285/critics/dqn_critic.py index 5ff5e9dfc8eed5947540ffe3501c32083086caf4..a40a66a0479ca21a2bdacadf09842244d3a96b4a 100644 --- a/hw3/cs285/critics/dqn_critic.py +++ b/hw3/cs285/critics/dqn_critic.py @@ -66,21 +66,23 @@ class DQNCritic(BaseCritic): q_t_values = torch.gather(qa_t_values, 1, ac_na.unsqueeze(1)).squeeze(1) # TODO compute the Q-values from the target network - qa_tp1_values = TODO + qa_tp1_values = self.q_net_target(next_ob_no) if self.double_q: # You must fill this part for Q2 of the Q-learning portion of the homework. # In double Q-learning, the best action is selected using the Q-network that # is being updated, but the Q-value for this action is obtained from the # target Q-network. See page 5 of https://arxiv.org/pdf/1509.06461.pdf for more details. - TODO + next_qa_value = self.q_net(next_ob_no) + actions = next_qa_value.argmax(1) + q_tp1 = torch.gather(qa_tp1_values, 1, actions.unsqueeze(1)).squeeze(1) else: q_tp1, _ = qa_tp1_values.max(dim=1) # TODO compute targets for minimizing Bellman error # HINT: as you saw in lecture, this would be: #currentReward + self.gamma * qValuesOfNextTimestep * (not terminal) - target = TODO + target = reward_n + self.gamma * q_tp1 * (1 - terminal_n) target = target.detach() assert q_t_values.shape == target.shape diff --git a/hw3/cs285/infrastructure/dqn_utils.py b/hw3/cs285/infrastructure/dqn_utils.py index a8ae1bb1617a88b0ce2b9e69db2d8f4426ec9f52..8091f0dba226c902f18d79359bf5f8a06b9e8ae7 100644 --- a/hw3/cs285/infrastructure/dqn_utils.py +++ b/hw3/cs285/infrastructure/dqn_utils.py @@ -41,8 +41,8 @@ def get_env_kwargs(env_name): kwargs = { 'learning_starts': 50000, 'target_update_freq': 10000, - 'replay_buffer_size': int(1e6), - 'num_timesteps': int(2e8), + 'replay_buffer_size': int(1e5), + 'num_timesteps': int(1e6), 'q_func': create_atari_q_network, 'learning_freq': 4, 'grad_norm_clipping': 10, @@ -122,7 +122,7 @@ def atari_exploration_schedule(num_timesteps): return PiecewiseSchedule( [ (0, 1.0), - (1e6, 0.1), + (1e5, 0.1), (num_timesteps / 8, 0.01), ], outside_value=0.01 ) @@ -132,7 +132,7 @@ def atari_ram_exploration_schedule(num_timesteps): return PiecewiseSchedule( [ (0, 0.2), - (1e6, 0.1), + (1e5, 0.1), (num_timesteps / 8, 0.01), ], outside_value=0.01 ) @@ -234,7 +234,10 @@ class PiecewiseSchedule(object): raised when outside value is requested. """ idxes = [e[0] for e in endpoints] + # print(idxes == sorted(idxes)) + # print(idxes,'shape of ',sorted(idxes)) assert idxes == sorted(idxes) + # print(idxes,'shape of ',sorted(idxes)) self._interpolation = interpolation self._outside_value = outside_value self._endpoints = endpoints diff --git a/hw3/cs285/infrastructure/rl_trainer.py b/hw3/cs285/infrastructure/rl_trainer.py index b0fa472eb385a2f67229aa6f6c6f72ee6aa51d3c..2ef597d978ed254098f17373deb079a111652e95 100644 --- a/hw3/cs285/infrastructure/rl_trainer.py +++ b/hw3/cs285/infrastructure/rl_trainer.py @@ -210,12 +210,43 @@ class RL_Trainer(object): envsteps_this_batch: the sum over the numbers of environment steps in paths train_video_paths: paths which also contain videos for visualization purposes """ - # TODO: get this from Piazza + # DONE : get this from Piazza + if itr == 0: + if initial_expertdata is not None: + with open(initial_expertdata,'rb') as f: + paths = pickle.loads(f.read()) + # after paths collecting and we need to save expert_data while itr==0 + # TODO 这里的expertdata是否是第一次的? 需要确认一下 + # if save_expert_data_to_disk: + # with open('expert_data_{}.pkl'.format(self.params['env_name']), 'wb') as file: + # pickle.dump(paths, file) + return paths, 0, None + + + print("\nCollecting data to be used for training... ") + paths, envsteps_this_batch = utils.sample_trajectories(self.env, collect_policy, num_transitions_to_sample, self.params['ep_len']) + + train_video_paths = None + if self.logvideo: + print("\nCollecting train rollouts to be used for saving videos... ") + train_video_paths = utils.sample_n_trajectories(self.env, collect_policy, MAX_NVIDEO, MAX_VIDEO_LEN, True) + + return paths, envsteps_this_batch, train_video_paths def train_agent(self): # TODO: get this from Piazza + # print("\nTraining agent using sampled data from replay buffer...") + train_logs = [] + for train_step in range(self.params['num_agent_train_steps_per_iter']): + # sample some data from the data buffer + ob_batch, ac_batch, re_batch, next_ob_batch, terminal_batch = self.agent.sample(self.params['train_batch_size']) + + # use the sample data to train an agent + train_log = self.agent.train(ob_batch, ac_batch, re_batch, next_ob_batch, terminal_batch) + train_logs.append(train_log) + return train_logs #################################### #################################### diff --git a/hw3/cs285/infrastructure/utils.py b/hw3/cs285/infrastructure/utils.py index eabdc393203ca15673c8872ea33b46700b0feb6a..9da5df139ba6cd811555116b7d673886700ad3c0 100644 --- a/hw3/cs285/infrastructure/utils.py +++ b/hw3/cs285/infrastructure/utils.py @@ -55,7 +55,47 @@ def mean_squared_error(a, b): ############################################ def sample_trajectory(env, policy, max_path_length, render=False, render_mode=('rgb_array')): - # TODO: get this from Piazza + # TODO: get this from Piazza -> get from hw2 since I don't have Piazza + # initialize env for the beginning of a new rollout + ob = env.reset() + + # init vars + obs, acs, rewards, next_obs, terminals, image_obs = [], [], [], [], [], [] + steps = 0 + while True: + # render image of the simulated env + if render: + if 'rgb_array' in render_mode: + if hasattr(env, 'sim'): + image_obs.append(env.sim.render(camera_name='track', height=500, width=500)[::-1]) + else: + image_obs.append(env.render(mode=render_mode)) + if 'human' in render_mode: + env.render(mode=render_mode) + time.sleep(env.model.opt.timestep) + + # use the most recent ob to decide what to do + obs.append(ob) + ac = policy.get_action(ob) + ac = ac[0] + acs.append(ac) + + # take the action and record results + ob, rew, done, _ = env.step(ac) + + # record result of taking that action + steps += 1 + next_obs.append(ob) + rewards.append(rew) + + # rollout done if max path length or done through step + rollout_done = 1 if steps >= max_path_length else done + terminals.append(rollout_done) + + if rollout_done: + break + + return Path(obs, image_obs, acs, rewards, next_obs, terminals) def sample_trajectories(env, policy, min_timesteps_per_batch, max_path_length, render=False, render_mode=('rgb_array')): """ @@ -64,6 +104,13 @@ def sample_trajectories(env, policy, min_timesteps_per_batch, max_path_length, r """ # TODO: get this from Piazza + timesteps_this_batch = 0 + paths = [] + while timesteps_this_batch < min_timesteps_per_batch: + path = sample_trajectory(env, policy, max_path_length, render) + paths.append(path) + timesteps_this_batch += get_pathlength(path) + return paths, timesteps_this_batch def sample_n_trajectories(env, policy, ntraj, max_path_length, render=False, render_mode=('rgb_array')): @@ -71,7 +118,12 @@ def sample_n_trajectories(env, policy, ntraj, max_path_length, render=False, ren Collect ntraj rollouts using policy """ # TODO: get this from Piazza - + paths = [] + + for i in range(ntraj): + path = sample_trajectory(env, policy, max_path_length, render) + paths.append(path) + return paths ############################################ diff --git a/hw3/cs285/policies/MLP_policy.py b/hw3/cs285/policies/MLP_policy.py index 4c2184a7589f3bff310c6ca4d68224ae4909c07c..380a723e1bf5715a47486e9000d16e1f94867870 100644 --- a/hw3/cs285/policies/MLP_policy.py +++ b/hw3/cs285/policies/MLP_policy.py @@ -87,7 +87,15 @@ class MLPPolicy(BasePolicy, nn.Module, metaclass=abc.ABCMeta): # query the policy with observation(s) to get selected action(s) def get_action(self, obs: np.ndarray) -> np.ndarray: # TODO: get this from Piazza - return action + # for this one remember to ptu.to_numpy as it required + if len(obs.shape) > 1: + observation = obs + else: + observation = obs[None] + + # it's distribution so it need sample for actions + action_distribution = self.forward(ptu.from_numpy(observation)) + return ptu.to_numpy(action_distribution.sample()) # update/train this policy def update(self, observations, actions, **kwargs): @@ -100,7 +108,13 @@ class MLPPolicy(BasePolicy, nn.Module, metaclass=abc.ABCMeta): # `torch.distributions.Distribution` object. It's up to you! def forward(self, observation: torch.FloatTensor): # TODO: get this from Piazza - return action_distribution + if self.discrete: + prob_action = self.logits_na(observation) + return distributions.Categorical(logits = prob_action) + else: + mean_prob = self.mean_net(observation) + std_prob = torch.diag(self.logstd.exp()) + return distributions.MultivariateNormal(mean_prob, scale_tril = std_prob) ##################################################### @@ -110,5 +124,15 @@ class MLPPolicy(BasePolicy, nn.Module, metaclass=abc.ABCMeta): class MLPPolicyAC(MLPPolicy): def update(self, observations, actions, adv_n=None): # TODO: update the policy and return the loss - loss = TODO + observations = ptu.from_numpy(observations) + actions = ptu.from_numpy(actions) + advantages = ptu.from_numpy(adv_n) + + log_pi = self.forward(observations).log_prob(actions) + loss = torch.neg(torch.mean(torch.mul(log_pi, advantages))) + + self.optimizer.zero_grad() + loss.backward() + self.optimizer.step() + return loss.item() diff --git a/hw3/cs285/policies/argmax_policy.py b/hw3/cs285/policies/argmax_policy.py index a7e443c3b668a49bcf1e4bcb6c64a9f0578d0cf1..b7110fe86af1cf6e62356f22a9ee2e81e1da55fc 100644 --- a/hw3/cs285/policies/argmax_policy.py +++ b/hw3/cs285/policies/argmax_policy.py @@ -14,6 +14,6 @@ class ArgMaxPolicy(object): ## TODO return the action that maxinmizes the Q-value # at the current observation as the output - actions = TODO + actions = self.critic.qa_values(observation).argmax(-1) - return action.squeeze() \ No newline at end of file + return actions.squeeze() \ No newline at end of file diff --git a/hw3/cs285/scripts/run_hw3_actor_critic.py b/hw3/cs285/scripts/run_hw3_actor_critic.py index 0b6f1f08040f1fb5b05bcc18e903416ed25a67ee..d5f918c7b2d5c6d5935c941cf0f46e1a52cf076a 100644 --- a/hw3/cs285/scripts/run_hw3_actor_critic.py +++ b/hw3/cs285/scripts/run_hw3_actor_critic.py @@ -123,4 +123,7 @@ def main(): if __name__ == "__main__": + start = time.perf_counter() main() + end = time.perf_counter() + print(f"The whole programm run time: {(end - start)/60:0.4f} mins") diff --git a/hw3/cs285/scripts/run_hw3_dqn.py b/hw3/cs285/scripts/run_hw3_dqn.py index c8ecab0e6ea0cbf2c611636130873520ad2c1259..5795b5bea415a54ecbad58c7a08f37bf322da4dd 100644 --- a/hw3/cs285/scripts/run_hw3_dqn.py +++ b/hw3/cs285/scripts/run_hw3_dqn.py @@ -91,4 +91,7 @@ def main(): if __name__ == "__main__": + start = time.perf_counter() main() + end = time.perf_counter() + print(f"The whole programm run time: {(end - start)/60:0.4f} mins") diff --git a/hw3/solution.md b/hw3/solution.md new file mode 100644 index 0000000000000000000000000000000000000000..4ef0651013d68348a8f4e237f5c474ead2d851e2 --- /dev/null +++ b/hw3/solution.md @@ -0,0 +1,222 @@ +# 前言 +详细写的记录见博客:[CSDN 链接:https://blog.csdn.net/qq_39537898/article/details/117673108](https://blog.csdn.net/qq_39537898/article/details/117673108) +参考: +1. [https://github.com/vincentkslim/cs285_homework_fall2020/tree/master/hw3](https://github.com/vincentkslim/cs285_homework_fall2020/tree/master/hw3) +2. [https://github.com/fokx/cs285_fall2020/tree/master/hw3](https://github.com/fokx/cs285_fall2020/tree/master/hw3) + +## 编译运行前 +使得cs285用在 +``` +cd +$ pip install -e . +``` +关于环境的要求: +```bash +pip3 install atari-py +``` +还有一个是报错提示的: +`Exception: ROM is missing for ms_pacman, see https://github.com/openai/atari-py#roms for instructions` +### ROM +>In order to import ROMS, you need to download Roms.rar from the Atari 2600 VCS ROM +Collection and extract the .rar file. +
Once you've done that, run: +`python -m atari_py.import_roms ` +
This should print out the names of ROMs as it imports them. The ROMs will be copied to your atari_py installation directory. + +需要在这里下载并安装[http://www.atarimania.com/rom_collection_archive_atari_2600_roms.html](http://www.atarimania.com/rom_collection_archive_atari_2600_roms.html) + +但是这里有个问题,有人在issue上也提到了 python得3.7 而不能保持原来的3.6 不然没法`python -m atari_py.import_roms `执行成功这句话 +所以我们又得切到python3.7的环境进行 +### conda 环境配置 +```bash +conda activate py37 +``` +提前先把这两个error的依赖装好了: +1. error: command 'gcc' failed with exit status 1 while installing eventlet +```bash +sudo apt-get install libosmesa6-dev +``` +参考地址:[https://github.com/ethz-asl/reinmav-gym/issues/35](https://github.com/ethz-asl/reinmav-gym/issues/35) +2. error: [Errno 2] No such file or directory: 'patchelf': 'patchelf' +``` +conda install anaconda patchelf +``` +参考地址:[https://github.com/openai/mujoco-py/issues/147](https://github.com/openai/mujoco-py/issues/147) + +这个好像有点慢.. 这是另一种方法,同一个参考地址 +```bash +sudo apt-get update +sudo apt install patchelf +``` + + +再直接走requirements.txt就好了(就是有时候清华源不稳总断 大家就自行解决吧) +```bash +pip install --user -r requirements.txt +``` + +### Notebook +运行Notebook里的代码时要添加conda环境,进入py37环境 +```bash +conda install ipykernel +python -m ipykernel install --user --name=py37 +``` +```bash +conda install tensorflow seaborn +``` + + +# PDF问题 +看tensorboard数据的命令行: +```bash +tensorboard --logdir data +``` +## Question 1: basic Q-learning performance. (DQN) + +### 运行指令 + +emmm 这不看不知道 一看吓一跳,这Iteration是!2x10的八次方`'num_timesteps': int(2e8)` 也就是200,000,000,这真的是一个很大很大很大的数字哈!但是我发现其实不需要200,000,000这么多次的迭代,就可以达到平均reward大于1000 +```bash +python cs285/scripts/run_hw3_dqn.py --env_name MsPacman-v0 --exp_name q1 +``` + +但是这里可以修改 +```python +'replay_buffer_size': int(1e6), +'num_timesteps': int(2e8), +``` +不过需要注意的是如果`'num_timesteps': int(1e7)`以下的话,`'replay_buffer_size': int(1e6)`这个和下面关于1e6的部分部分是需要变的 +然后我用的就是1e6,然后运行了269.2109 mins!!巨长(但是可以并行运行其他的python没啥大问题) + +整个的迭代和return的示意图如下: + +![运行结果示意图](../image/hw3_q1.png) + +## Question 2: double Q-learning (DDQN). +### 运行指令 +此运行在配置为:CPU i7-9700 内存16G 无GPU参与 +```bash +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q2_dqn_1 --seed 1 +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q2_dqn_2 --seed 2 +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q2_dqn_3 --seed 3 +``` +运行时间大致为:15.9101 mins到16.1607 mins之间 + +```bash +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q2_doubledqn_1 --double_q --seed 1 +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q2_doubledqn_2 --double_q --seed 2 +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q2_doubledqn_3 --double_q --seed 3 +``` +运行时间大致为:17.0641 mins到17.9384 mins之间 + +此问题主要是对比DQN和DDQN的优劣,首先两者的Q-value都是根据网络学习而来的,DDQN是以当前policy的参数进入到下一个policy参数的Q值计算中,这样的好处是:能减小DQN对于value estimate的虚高现象,具体建议看一下第八节课[b站链接](https://www.bilibili.com/video/BV1dJ411W78A?p=8) +不同之处在代码: +```python +qa_tp1_values = self.q_net_target(next_ob_no) +if self.double_q: + # You must fill this part for Q2 of the Q-learning portion of the homework. + # In double Q-learning, the best action is selected using the Q-network that + # is being updated, but the Q-value for this action is obtained from the + # target Q-network. See page 5 of https://arxiv.org/pdf/1509.06461.pdf for more details. + next_qa_value = self.q_net(next_ob_no) + actions = next_qa_value.argmax(1) + q_tp1 = torch.gather(qa_tp1_values, 1, actions.unsqueeze(1)).squeeze(1) +else: + q_tp1, _ = qa_tp1_values.max(dim=1) + +target = reward_n + self.gamma * q_tp1 * (1 - terminal_n) +``` +### 结果分析 +首先因为PDF里说了DQN和DDQN各随机运行三次来避免considerable variance between runs,然后结果分析像hw2里一样是由DataViz.ipynb求和取平均做图的: + +![运行结果示意图](../image/hw3_q2.png) + +可以比较明显看出来double dqn的方法在后面迭代中return逐步增加,但是我感觉... 我这图隐隐约约有点不太对劲 emmm 差距不明显后面反而降下来了... +-[] 这里可能有问题需要重新回来看一下 + +这是另一台主机的随机结果:(好像是一样的趋势 emmm) + +![运行结果示意图](../image/hw3_q2_acom.png) + +## Question 3: experimenting with hyperparameters +这里的超参数调整得自己去py文件里改?好像是的..哎,也可以在命令行里加就行,PDF中给了选项: learning rates, neural network architecture, exploration schedule or exploration rule (e.g.you may implement an alternative to $\epsilon$-greedy), etc. + +```bash +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q3_hparam1 +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q3_hparam2 --batch_size 64 +python cs285/scripts/run_hw3_dqn.py --env_name LunarLander-v3 --exp_name q3_hparam3 --batch_size 64 +``` +默认大概需要16.7583 mins +那就改num_timesteps和batch_size两项,首先默认的是:`'gamma': 1` 然后`'batch_size': 32`,修改这个都需要到dqn_utils.py里面改 +对于hparam1我们就改`'gamma': 0.9` 运行时长:20.9463 mins +hparam2改`'batch_size': 64` 运行时长:17.2012 mins +hparam3改`'gamma': 0.9` & `'batch_size': 64` 运行时长:21.5064 mins +运行完了对比图: + +![运行结果示意图](../image/hw3_q3.png) + +结果上来看,增加network的batch_size会更好,但是时长会增加,gamma0.9效果很差... 是不是应该0.99来着,我记得课程说这个是一般0.99 + +然后又花了半小时去输出gamma:0.99的时候: + +![运行结果示意图](../image/hw3_q31.png) + +对于hparam1我们就改`'gamma': 0.99` 运行时长:16.2794 mins +hparam2改`'batch_size': 64` 运行时长:17.2012 mins +hparam3改`'gamma': 0.99` & `'batch_size': 64` 运行时长:17.1102 mins + +## Question 4: Sanity check with Cartpole + +```bash +python cs285/scripts/run_hw3_actor_critic.py --env_name CartPole-v0 -n 100 -b 1000 --exp_name q4_ac_1_1 -ntu 1 -ngsptu 1 +``` +大概运行时长:0.3502 mins +```bash +python cs285/scripts/run_hw3_actor_critic.py --env_name CartPole-v0 -n 100 -b 1000 --exp_name q4_100_1 -ntu 100 -ngsptu 1 +python cs285/scripts/run_hw3_actor_critic.py --env_name CartPole-v0 -n 100 -b 1000 --exp_name q4_1_100 -ntu 1 -ngsptu 100 +python cs285/scripts/run_hw3_actor_critic.py --env_name CartPole-v0 -n 100 -b 1000 --exp_name q4_10_10 -ntu 10 -ngsptu 10 +``` +大概运行时长:0.5576 mins - 0.6268 mins + +![运行结果示意图](../image/hw3_q4.png) + + +## Question 5: Run actor-critic with more difficult tasks +是自己选择参数即可,主要是需要运行两个环境,如果运行前面的都不报错,唯独这两个报错的话,可能是mujoco的环境没有安装好的原因...(因为我在另一台主机上就报错了) +```bash +python cs285/scripts/run_hw3_actor_critic.py --env_name InvertedPendulum-v2 --ep_len 1000 --discount 0.95 -n 100 -l 2 -s 64 -b 5000 -lr 0.01 --exp_name q5_10_10 -ntu 10 -ngsptu 10 +``` + +然后呢我主要是看到前一个问题中10_10这组参数不错,emmm就选择的是这组 + +这是InvertedPendulum-v2环境下的图,大概运行时间:4.2144mins(有q1同时在运行) + +![运行结果示意图](../image/hw3_q5_1.png) + +但是效果有点太太太差了... 所以我又试了上面第二好的也就是1_100的数据长这样: +```bash +python cs285/scripts/run_hw3_actor_critic.py --env_name InvertedPendulum-v2 --ep_len 1000 --discount 0.95 -n 100 -l 2 -s 64 -b 5000 -lr 0.01 --exp_name q5_1_100 -ntu 1 -ngsptu 100 +``` + +emm,从PDF对我们的期望是,大概100迭代后,这个return should be around 1000,所以完成挺好的 + +![运行结果示意图](../image/hw3_q5_11.png) + + +第二个环境呢是HalfCheetah-v2 首先还是采取10_10的看一下,大致运行时间:30.32754mins(有q1在同时运行) +```bash +python cs285/scripts/run_hw3_actor_critic.py --env_name HalfCheetah-v2 --ep_len 150 --discount 0.90 --scalar_log_freq 1 -n 150 -l 2 -s 32 -b 30000 -eb 1500 -lr 0.02 --exp_name q5_10_10 -ntu 10 -ngsptu 10 +``` +这是HalfCheetah-v2环境下的图: + +![运行结果示意图](../image/hw3_q5_2.png) + +感觉这个环境下10_10的就挺不错的 --- 然后我收回我的话1_100吧: 29.8561mins +```bash +python cs285/scripts/run_hw3_actor_critic.py --env_name HalfCheetah-v2 --ep_len 150 --discount 0.90 --scalar_log_freq 1 -n 150 -l 2 -s 32 -b 30000 -eb 1500 -lr 0.02 --exp_name q5_1_100 -ntu 1 -ngsptu 100 +``` + +应该差不多就算成功了? + +![运行结果示意图](../image/hw3_q5_22.png) + diff --git a/image/hw3_q1.png b/image/hw3_q1.png new file mode 100644 index 0000000000000000000000000000000000000000..c897abdbc5ad2a751a9fad219221bb8953796c3c Binary files /dev/null and b/image/hw3_q1.png differ diff --git a/image/hw3_q2.png b/image/hw3_q2.png new file mode 100644 index 0000000000000000000000000000000000000000..d2a17d5f6cf2d964df6f2e9df63ad705e1e59a81 Binary files /dev/null and b/image/hw3_q2.png differ diff --git a/image/hw3_q2_acom.png b/image/hw3_q2_acom.png new file mode 100644 index 0000000000000000000000000000000000000000..90b0c17bcd34be7219dea1b598afb5bd36dc7a78 Binary files /dev/null and b/image/hw3_q2_acom.png differ diff --git a/image/hw3_q3.png b/image/hw3_q3.png new file mode 100644 index 0000000000000000000000000000000000000000..fe597d27b8a12e7bc5ee3c5ee8f2fb19784f378f Binary files /dev/null and b/image/hw3_q3.png differ diff --git a/image/hw3_q31.png b/image/hw3_q31.png new file mode 100644 index 0000000000000000000000000000000000000000..11827450b4846b3bf2fef003795df9121ad3f4d6 Binary files /dev/null and b/image/hw3_q31.png differ diff --git a/image/hw3_q4.png b/image/hw3_q4.png new file mode 100644 index 0000000000000000000000000000000000000000..a8487bbf6bdd512305dd7c69c9c05d44014c6383 Binary files /dev/null and b/image/hw3_q4.png differ diff --git a/image/hw3_q5_1.png b/image/hw3_q5_1.png new file mode 100644 index 0000000000000000000000000000000000000000..dd3e9711c6bde7e0b61a5cc3a895601140104617 Binary files /dev/null and b/image/hw3_q5_1.png differ diff --git a/image/hw3_q5_11.png b/image/hw3_q5_11.png new file mode 100644 index 0000000000000000000000000000000000000000..243b4d3767e9a61e4e2b3067a23abe008275431b Binary files /dev/null and b/image/hw3_q5_11.png differ diff --git a/image/hw3_q5_2.png b/image/hw3_q5_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a07f997ea79e0280eb60d65c69c604806f8b3bc6 Binary files /dev/null and b/image/hw3_q5_2.png differ diff --git a/image/hw3_q5_22.png b/image/hw3_q5_22.png new file mode 100644 index 0000000000000000000000000000000000000000..66349b05dd15d78def5ea2acf4e041fdfb7c4fdd Binary files /dev/null and b/image/hw3_q5_22.png differ