diff --git a/epymarl_continuous_action_demo.ipynb b/epymarl_continuous_action_demo.ipynb new file mode 100644 index 00000000..7e8c8dc5 --- /dev/null +++ b/epymarl_continuous_action_demo.ipynb @@ -0,0 +1,1085 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "M3w1MGpYePHX", + "outputId": "7b9b80d6-4b6c-4c12-8ff4-380f0135229a" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Cloning into 'epymarl_continuous'...\n", + "remote: Enumerating objects: 855, done.\u001b[K\n", + "remote: Counting objects: 100% (599/599), done.\u001b[K\n", + "remote: Compressing objects: 100% (201/201), done.\u001b[K\n", + "remote: Total 855 (delta 470), reused 405 (delta 398), pack-reused 256 (from 1)\u001b[K\n", + "Receiving objects: 100% (855/855), 3.16 MiB | 10.20 MiB/s, done.\n", + "Resolving deltas: 100% (544/544), done.\n", + "/content/epymarl_continuous\n" + ] + } + ], + "source": [ + "!git clone https://github.com/MatthewCWeston/epymarl_continuous\n", + "%cd /content/epymarl_continuous" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Install requirements" + ], + "metadata": { + "id": "ELZK_OjiqfKr" + } + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true, + "id": "hO_xEsVKiAjG", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "082e1c54-3f20-4efd-e846-2d2054f6b7f9" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + " Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m958.1/958.1 kB\u001b[0m \u001b[31m21.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m108.5/108.5 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m434.2/434.2 kB\u001b[0m \u001b[31m27.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m98.7/98.7 kB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m108.2/108.2 kB\u001b[0m \u001b[31m7.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m46.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m183.5/183.5 kB\u001b[0m \u001b[31m14.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h Building wheel for mpyq (setup.py) ... \u001b[?25l\u001b[?25hdone\n" + ] + } + ], + "source": [ + "!pip install -qr requirements.txt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "id": "dhxh-tLciF3d" + }, + "outputs": [], + "source": [ + "!pip install -qr env_requirements.txt" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Train a model in a discrete setting" + ], + "metadata": { + "id": "8lMQhOV-3HgZ" + } + }, + { + "cell_type": "markdown", + "source": [ + "### Run training" + ], + "metadata": { + "id": "kIuu11MVpQxD" + } + }, + { + "cell_type": "code", + "source": [ + "%cd /content/epymarl\n", + "'''\n", + " batch_size_run: Number of CPUs running agents\n", + " t_max: Total timesteps to train\n", + " save_model: Save the model during training.\n", + " buffer_size, batch_size: size of replay buffer; timesteps to update weights after.\n", + " obs_agent_id: Append a one-hot boolean to the end of the observation\n", + " runner/learner/<> log interval: Rate at which runner/learner/system should log outputs\n", + " target_update_interval_or_tau: Determines hard or soft updates to target weights.\n", + "'''\n", + "!python src/main.py --config=mappo --env-config=mpe with env_args.key=\"pz-mpe-simple-v3\" env_args.time_limit=25 env_args.max_cycles=25 save_model=True save_model_interval=20000 t_max=20000 batch_size_run=1 buffer_size=100 batch_size=100 obs_agent_id=False runner_log_interval=1000 learner_log_interval=1000 log_interval=1000 use_rnn=False" + ], + "metadata": { + "id": "l-QStfvAhI-V", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "2c6312f0-9d7a-4c2f-c733-ed2f6a8ae7d7", + "collapsed": true + }, + "execution_count": 5, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[Errno 2] No such file or directory: '/content/epymarl'\n", + "/content/epymarl_continuous\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'version'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'version'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'diff', '--cached', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'diff', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'cat-file', '--batch-check'], cwd=/content/epymarl_continuous, stdin=, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'diff', '--cached', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'diff', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'cat-file', '--batch-check'], cwd=/content/epymarl_continuous, stdin=, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'diff', '--cached', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'diff', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:00:43] git.cmd Popen(['git', 'cat-file', '--batch-check'], cwd=/content/epymarl_continuous, stdin=, shell=False, universal_newlines=False)\n", + "[INFO 07:00:43] root Saving to FileStorageObserver in results/sacred.\n", + "[DEBUG 07:00:43] pymarl Using capture mode \"fd\"\n", + "[INFO 07:00:43] pymarl Running command 'my_main'\n", + "[INFO 07:00:43] pymarl Started run with ID \"1\"\n", + "[DEBUG 07:00:43] pymarl Starting Heartbeat\n", + "[DEBUG 07:00:43] my_main Started\n", + "[WARNING 07:00:43] my_main CUDA flag use_cuda was switched OFF automatically because no CUDA devices are available!\n", + "[INFO 07:00:43] my_main Experiment Parameters:\n", + "[INFO 07:00:43] my_main \n", + "\n", + "{ 'action_selector': 'soft_policies',\n", + " 'add_value_last_step': True,\n", + " 'agent': 'rnn',\n", + " 'agent_output_type': 'pi_logits',\n", + " 'batch_size': 100,\n", + " 'batch_size_run': 1,\n", + " 'buffer_cpu_only': True,\n", + " 'buffer_size': 100,\n", + " 'checkpoint_path': '',\n", + " 'common_reward': True,\n", + " 'critic_type': 'cv_critic',\n", + " 'entropy_coef': 0.001,\n", + " 'env': 'gymma',\n", + " 'env_args': { 'continuous_actions': False,\n", + " 'key': 'pz-mpe-simple-v3',\n", + " 'max_cycles': 25,\n", + " 'pretrained_wrapper': None,\n", + " 'seed': 325454985,\n", + " 'time_limit': 25},\n", + " 'epochs': 4,\n", + " 'eps_clip': 0.2,\n", + " 'evaluate': False,\n", + " 'gamma': 0.99,\n", + " 'grad_norm_clip': 10,\n", + " 'hidden_dim': 128,\n", + " 'hypergroup': None,\n", + " 'label': 'default_label',\n", + " 'learner': 'ppo_learner',\n", + " 'learner_log_interval': 1000,\n", + " 'load_step': 0,\n", + " 'local_results_path': 'results',\n", + " 'log_interval': 1000,\n", + " 'lr': 0.0003,\n", + " 'mac': 'basic_mac',\n", + " 'mask_before_softmax': True,\n", + " 'name': 'mappo',\n", + " 'obs_agent_id': False,\n", + " 'obs_individual_obs': False,\n", + " 'obs_last_action': False,\n", + " 'optim_alpha': 0.99,\n", + " 'optim_eps': 1e-05,\n", + " 'q_nstep': 5,\n", + " 'render': False,\n", + " 'repeat_id': 1,\n", + " 'reward_scalarisation': 'sum',\n", + " 'runner': 'parallel',\n", + " 'runner_log_interval': 1000,\n", + " 'save_model': True,\n", + " 'save_model_interval': 20000,\n", + " 'save_replay': False,\n", + " 'seed': 325454985,\n", + " 'standardise_returns': False,\n", + " 'standardise_rewards': True,\n", + " 't_max': 20000,\n", + " 'target_update_interval_or_tau': 0.01,\n", + " 'test_greedy': True,\n", + " 'test_interval': 50000,\n", + " 'test_nepisode': 100,\n", + " 'use_cuda': False,\n", + " 'use_rnn': False,\n", + " 'use_tensorboard': False,\n", + " 'use_wandb': False,\n", + " 'wandb_mode': 'offline',\n", + " 'wandb_project': None,\n", + " 'wandb_save_model': False,\n", + " 'wandb_team': None}\n", + "\n", + "!!! USING MPE ENVIRONMENT\n", + "error: XDG_RUNTIME_DIR not set in the environment.\n", + "ARGS.agent_output_type equals pi_logits\n", + "BUILDING AGENTS! ARGS.N_ACTIONS = 5\n", + "[INFO 07:00:54] my_main Beginning training for 20000 timesteps\n", + "/usr/local/lib/python3.11/dist-packages/gymnasium/utils/passive_env_checker.py:245: UserWarning: \u001b[33mWARN: The reward returned by `step()` must be a float, int, np.integer or np.floating, actual type: \u001b[0m\n", + " logger.warn(\n", + "[INFO 07:00:55] my_main t_env: 25 / 20000\n", + "[INFO 07:00:55] my_main Estimated time left: 0 seconds. Time passed: 0 seconds\n", + "[INFO 07:01:00] my_main Saving models to results/models/mappo_seed325454985_pz-mpe-simple-v3_2025-01-20 07:00:43.729418/25\n", + "[INFO 07:01:04] my_main Recent Stats | t_env: 1000 | Episode: 40\n", + "ep_length_mean: 25.0000\treturn_mean: -6.9297\treturn_std: 0.0000\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:01:06] my_main Recent Stats | t_env: 2000 | Episode: 80\n", + "ep_length_mean: 25.0000\treturn_mean: -22.9197\treturn_std: 15.6504\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:01:17] my_main Recent Stats | t_env: 3000 | Episode: 120\n", + "advantage_mean: -0.0328\tagent_grad_norm: 0.3232\tcritic_grad_norm: 3.3858\tcritic_loss: 20.0603\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0145\tpi_max: 0.2220\tq_taken_mean: 0.0048\n", + "return_mean: -31.6833\treturn_std: 22.2490\ttarget_mean: -0.0280\ttd_error_abs: 3.5779\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:01:28] my_main Recent Stats | t_env: 4000 | Episode: 160\n", + "advantage_mean: 0.0081\tagent_grad_norm: 0.4809\tcritic_grad_norm: 5.6920\tcritic_loss: 14.9717\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0434\tpi_max: 0.4981\tq_taken_mean: -0.4299\n", + "return_mean: -33.6645\treturn_std: 24.8194\ttarget_mean: -0.4218\ttd_error_abs: 2.6657\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:01:39] my_main Recent Stats | t_env: 5000 | Episode: 200\n", + "advantage_mean: 0.0019\tagent_grad_norm: 0.5715\tcritic_grad_norm: 4.0342\tcritic_loss: 11.8651\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0302\tpi_max: 0.6113\tq_taken_mean: -0.2272\n", + "return_mean: -37.8320\treturn_std: 32.2903\ttarget_mean: -0.2253\ttd_error_abs: 2.1283\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:01:52] my_main Recent Stats | t_env: 6000 | Episode: 240\n", + "advantage_mean: -0.0031\tagent_grad_norm: 0.8296\tcritic_grad_norm: 3.1603\tcritic_loss: 10.1738\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0214\tpi_max: 0.6753\tq_taken_mean: 0.1021\n", + "return_mean: -41.0851\treturn_std: 36.7894\ttarget_mean: 0.0990\ttd_error_abs: 1.8246\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:02:09] my_main Recent Stats | t_env: 7000 | Episode: 280\n", + "advantage_mean: -0.0026\tagent_grad_norm: 0.6884\tcritic_grad_norm: 2.5945\tcritic_loss: 8.2177\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0180\tpi_max: 0.7182\tq_taken_mean: 0.7637\n", + "return_mean: -37.4185\treturn_std: 33.8437\ttarget_mean: 0.7611\ttd_error_abs: 1.5439\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:02:24] my_main Recent Stats | t_env: 8000 | Episode: 320\n", + "advantage_mean: 0.0037\tagent_grad_norm: 0.6502\tcritic_grad_norm: 1.9938\tcritic_loss: 4.3034\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0216\tpi_max: 0.8564\tq_taken_mean: 1.5671\n", + "return_mean: -31.4654\treturn_std: 31.7949\ttarget_mean: 1.5708\ttd_error_abs: 0.9187\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:02:37] my_main Recent Stats | t_env: 9000 | Episode: 360\n", + "advantage_mean: -0.0071\tagent_grad_norm: 0.6249\tcritic_grad_norm: 0.4502\tcritic_loss: 2.4553\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0015\tpi_max: 0.8806\tq_taken_mean: 2.7026\n", + "return_mean: -27.4281\treturn_std: 29.2183\ttarget_mean: 2.6955\ttd_error_abs: 0.6726\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:02:48] my_main Recent Stats | t_env: 10000 | Episode: 400\n", + "advantage_mean: -0.0058\tagent_grad_norm: 0.5313\tcritic_grad_norm: 0.3594\tcritic_loss: 1.4662\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0012\tpi_max: 0.8946\tq_taken_mean: 3.7236\n", + "return_mean: -20.2533\treturn_std: 21.7175\ttarget_mean: 3.7178\ttd_error_abs: 0.5728\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:02:59] my_main Recent Stats | t_env: 11000 | Episode: 440\n", + "advantage_mean: -0.0032\tagent_grad_norm: 0.4595\tcritic_grad_norm: 0.3135\tcritic_loss: 0.5808\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0023\tpi_max: 0.8992\tq_taken_mean: 4.7322\n", + "return_mean: -19.3304\treturn_std: 21.8210\ttarget_mean: 4.7290\ttd_error_abs: 0.4926\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:03:14] my_main Recent Stats | t_env: 12000 | Episode: 480\n", + "advantage_mean: -0.0049\tagent_grad_norm: 0.4810\tcritic_grad_norm: 0.3128\tcritic_loss: 0.5945\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0008\tpi_max: 0.9040\tq_taken_mean: 5.4564\n", + "return_mean: -18.0243\treturn_std: 21.7597\ttarget_mean: 5.4515\ttd_error_abs: 0.4952\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:03:27] my_main Recent Stats | t_env: 13000 | Episode: 520\n", + "advantage_mean: -0.0071\tagent_grad_norm: 0.4792\tcritic_grad_norm: 0.3474\tcritic_loss: 0.5579\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0018\tpi_max: 0.9006\tq_taken_mean: 6.3881\n", + "return_mean: -16.0734\treturn_std: 19.2666\ttarget_mean: 6.3809\ttd_error_abs: 0.4780\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:03:37] my_main Recent Stats | t_env: 14000 | Episode: 560\n", + "advantage_mean: -0.0082\tagent_grad_norm: 0.4032\tcritic_grad_norm: 0.3615\tcritic_loss: 0.5018\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0031\tpi_max: 0.8938\tq_taken_mean: 7.1837\n", + "return_mean: -15.2815\treturn_std: 18.8165\ttarget_mean: 7.1755\ttd_error_abs: 0.4494\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:03:47] my_main Recent Stats | t_env: 15000 | Episode: 600\n", + "advantage_mean: -0.0086\tagent_grad_norm: 0.3972\tcritic_grad_norm: 0.3543\tcritic_loss: 0.4522\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0038\tpi_max: 0.8918\tq_taken_mean: 7.9014\n", + "return_mean: -14.5954\treturn_std: 17.6852\ttarget_mean: 7.8928\ttd_error_abs: 0.4200\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:03:58] my_main Recent Stats | t_env: 16000 | Episode: 640\n", + "advantage_mean: -0.0104\tagent_grad_norm: 0.3606\tcritic_grad_norm: 0.4058\tcritic_loss: 0.5007\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0054\tpi_max: 0.8917\tq_taken_mean: 8.8111\n", + "return_mean: -13.0559\treturn_std: 16.1323\ttarget_mean: 8.8007\ttd_error_abs: 0.4266\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:04:10] my_main Recent Stats | t_env: 17000 | Episode: 680\n", + "advantage_mean: -0.0130\tagent_grad_norm: 0.4132\tcritic_grad_norm: 0.5269\tcritic_loss: 0.6327\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0079\tpi_max: 0.8950\tq_taken_mean: 9.9925\n", + "return_mean: -11.9053\treturn_std: 13.9895\ttarget_mean: 9.9795\ttd_error_abs: 0.4459\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:04:21] my_main Recent Stats | t_env: 18000 | Episode: 720\n", + "advantage_mean: -0.0125\tagent_grad_norm: 0.5489\tcritic_grad_norm: 0.5112\tcritic_loss: 0.6279\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0074\tpi_max: 0.9092\tq_taken_mean: 11.1412\n", + "return_mean: -11.8871\treturn_std: 13.2867\ttarget_mean: 11.1287\ttd_error_abs: 0.4471\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:04:33] my_main Recent Stats | t_env: 19000 | Episode: 760\n", + "advantage_mean: -0.0128\tagent_grad_norm: 0.5516\tcritic_grad_norm: 0.5379\tcritic_loss: 0.6009\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0083\tpi_max: 0.9253\tq_taken_mean: 12.4139\n", + "return_mean: -10.6144\treturn_std: 11.5925\ttarget_mean: 12.4012\ttd_error_abs: 0.4387\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:04:44] my_main Recent Stats | t_env: 20000 | Episode: 800\n", + "advantage_mean: -0.0149\tagent_grad_norm: 0.5191\tcritic_grad_norm: 0.6327\tcritic_loss: 0.5449\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0113\tpi_max: 0.9265\tq_taken_mean: 13.8211\n", + "return_mean: -9.2111\treturn_std: 9.2012\ttarget_mean: 13.8062\ttd_error_abs: 0.4166\n", + "test_ep_length_mean: 25.0000\ttest_return_mean: -33.4314\ttest_return_std: 31.3928\t\n", + "[INFO 07:04:44] my_main Saving models to results/models/mappo_seed325454985_pz-mpe-simple-v3_2025-01-20 07:00:43.729418/20025\n", + "[INFO 07:04:44] my_main Finished Training\n", + "Exiting Main\n", + "Stopping all threads\n", + "Thread Thread-1 is alive! Is daemon: False\n", + "Thread joined\n", + "Exiting script\n", + "[DEBUG 07:04:45] my_main Finished after 0:04:02.\n", + "[INFO 07:04:45] pymarl Completed after 0:04:02\n", + "[DEBUG 07:04:45] pymarl Stopping Heartbeat\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Imports" + ], + "metadata": { + "id": "A5KCf5itfKOU" + } + }, + { + "cell_type": "code", + "source": [ + "%cd /content/epymarl_continuous\n", + "import sys\n", + "sys.path.append('/content/epymarl_continuous/src')\n", + "import os\n", + "import yaml\n", + "import copy\n", + "import json\n", + "from types import SimpleNamespace as SN\n", + "from collections.abc import Mapping\n", + "import numpy as np\n", + "import torch\n", + "import matplotlib.pyplot as plt\n", + "from runners import REGISTRY as r_REGISTRY\n", + "from src.modules.agents.rnn_agent import RNNAgent\n", + "from src.components.action_selectors import ContinuousSelector\n", + "\n", + "from PIL import Image, ImageSequence, ImageDraw\n", + "import IPython.display\n", + "from collections import defaultdict\n", + "from pettingzoo.utils.wrappers.base import BaseWrapper\n", + "\n", + "from pettingzoo.mpe import simple_speaker_listener_v4, simple_reference_v3, simple_world_comm_v3, simple_v3" + ], + "metadata": { + "id": "56Fd6fIR-vZ9", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "c62b3cf0-161b-4a0c-a4b9-0746ffaa5c26" + }, + "execution_count": 15, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "/content/epymarl_continuous\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### View Training Results" + ], + "metadata": { + "id": "-gRwsGbt-IOm" + } + }, + { + "cell_type": "code", + "source": [ + "# @title Display reward over time\n", + "env_name = 'pz-mpe-simple-v3'\n", + "alg_name = 'mappo'\n", + "\n", + "results_path = '/content/epymarl_continuous/results'\n", + "sacred_path = f'{results_path}/sacred/{alg_name}/pz-mpe-simple-v3'\n", + "results_dir = max([os.path.join(sacred_path, d) for d in os.listdir(sacred_path)], key=os.path.getmtime).split('/')[-1]\n", + "models_path = f'{results_path}/models'\n", + "models_path = max([os.path.join(models_path, d) for d in os.listdir(models_path)], key=os.path.getmtime) # Newest run\n", + "models_path = max([os.path.join(models_path, d) for d in os.listdir(models_path)], key=os.path.getmtime) # Last update\n", + "with open(f'{sacred_path}/{results_dir}/metrics.json', 'r') as f:\n", + " metrics = json.load(f)\n", + "metrics.keys()\n", + "plt.plot(metrics['return_mean']['values'])" + ], + "metadata": { + "id": "WMF79VXrK6lu", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 448 + }, + "cellView": "form", + "outputId": "11de2fab-15c9-420a-9f01-3b4ef777282a" + }, + "execution_count": 7, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[]" + ] + }, + "metadata": {}, + "execution_count": 7 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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m24K6HHhdP369++PzMzMVtfIZrNh+/bt7V6j7vwcK00KKUeOHMG6deuQnp4e8Dk6+15Xk9OnT6OqqqrdtobjNQR8PZzjxo3D6NGjA36sktevs/eFcePGQafTtboexcXFKCkpafd6dOdntzsNj0rvvPOOaDAYxDfeeEM8cOCAeP/994spKSlieXm5KIqieNddd4mLFi3yH//VV1+JMTEx4gsvvCAePHhQfOKJJ0SdTifu3btXqZfQoQcffFBMTk4WN23aJJ49e9b/UV9f7z/m4tf45JNPil988YV47NgxcefOneLtt98uxsbGivv371fiJXRowYIF4qZNm8QTJ06IX331lThlyhQxIyNDrKioEEUx/K+fxOPxiH379hUXLlx4yX3hdv3sdru4e/ducffu3SIA8cUXXxR3797tX/HyzDPPiCkpKeJHH30kFhUViTfffLPYv39/saGhwX+Oa6+9VlyxYoX/dmc/x6HW0Wt0Op3ijBkzxD59+oiFhYWtfi4dDof/HBe/xs6+19Xy+ux2u/iLX/xC3Lp1q3jixAlx3bp14mWXXSYOGjRIbGxsbPf1qekadvY9KoqiWFNTI8bHx4svv/xym+dQ8/XryvvCAw88IPbt21fcsGGDuGPHDjE/P1/Mz89vdZ68vDzx/fff99/uys9uT0RtUBFFUVyxYoXYt29fUa/Xi5dffrm4bds2/31XXXWVeM8997Q6/t133xUHDx4s6vV6cfjw4eKaNWtC3OKuA9Dmx+uvv+4/5uLX+Mgjj/i/HhaLRbzxxhvFXbt2hb7xXXDbbbeJvXr1EvV6vdi7d2/xtttuE48ePeq/P9yvn+SLL74QAYjFxcWX3Bdu12/jxo1tfk9Kr8Hr9Yq/+c1vRIvFIhoMBvG666675HXn5OSITzzxRKvPdfRzHGodvcYTJ060+3O5ceNG/zkufo2dfa+HUkevr76+Xpw6dapoMplEnU4n5uTkiPfdd98lgUPN17Cz71FRFMVXX31VjIuLE6urq9s8h5qvX1feFxoaGsSf/vSnYmpqqhgfHy9+//vfF8+ePXvJeVo+pis/uz0hND0pERERkepE5RwVIiIiCg8MKkRERKRaDCpERESkWgwqREREpFoMKkRERKRaDCpERESkWgwqREREpFoMKkRERKRaDCpERESkWgwqREREpFoMKkRERKRaDCpERESkWv8fwswEDw6WelcAAAAASUVORK5CYII=\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "# @title Look up env data\n", + "# Get config dicts\n", + "cfg_path = '/content/epymarl_continuous/src/config'\n", + "alg_name = 'mappo'\n", + "\n", + "def recursive_dict_update(d, u):\n", + " for k, v in u.items():\n", + " if isinstance(v, Mapping):\n", + " d[k] = recursive_dict_update(d.get(k, {}), v)\n", + " else:\n", + " d[k] = v\n", + " return d\n", + "with open(os.path.join(cfg_path,\"default.yaml\",),\"r\",) as f:\n", + " cfg_dict = yaml.load(f, Loader=yaml.FullLoader)\n", + "with open(os.path.join(cfg_path,\"envs\",\"mpe.yaml\",),\"r\",) as f:\n", + " env_dict = yaml.load(f, Loader=yaml.FullLoader)\n", + "with open(os.path.join(cfg_path,\"algs\",f\"{alg_name}.yaml\",),\"r\",) as f:\n", + " alg_dict = yaml.load(f, Loader=yaml.FullLoader)\n", + "config_dict = recursive_dict_update(cfg_dict, env_dict)\n", + "config_dict = recursive_dict_update(cfg_dict, alg_dict)\n", + "#\n", + "config_dict[\"env_args\"][\"seed\"] = 0\n", + "config_dict[\"env_args\"][\"key\"] = env_name\n", + "config_dict[\"env_args\"][\"time_limit\"]=25\n", + "#\n", + "args = SN(**config_dict)\n", + "args.device = \"cpu\"\n", + "args.unique_token = 'TESTTESTTEST'\n", + "#\n", + "runner = r_REGISTRY[args.runner](args=args,logger=None) # Some algs () use parallel. batch_size_run increases parallelism. ippo, coma, ia2c, maa2c, mappo\n", + "env_info = runner.get_env_info()\n", + "args.n_agents = env_info[\"n_agents\"]\n", + "args.n_actions = env_info[\"n_actions\"]\n", + "args.state_shape = env_info[\"state_shape\"]" + ], + "metadata": { + "id": "c9igXBbxUVNg", + "cellView": "form", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "b2d82b20-9dfd-43a7-ad96-87e5b7bb3f0c" + }, + "execution_count": 8, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "!!! USING MPE ENVIRONMENT\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# @title Display a sample run\n", + "args.use_rnn = False # Since the default is 'true' for MAPPO but not MAPPO_NS\n", + "agent = RNNAgent(env_info['obs_shape'], args)\n", + "agent.load_state_dict(torch.load(f'{models_path}/agent.th', map_location=lambda storage, loc: storage))\n", + "env_cfg = {'max_cycles': 75}\n", + "target_env = {\n", + " \"pz-mpe-simple-speaker-listener-v4\": simple_speaker_listener_v4,\n", + " \"pz-mpe-simple-reference-v3\": simple_reference_v3,\n", + " \"pz-mpe-simple-world-comm-v3\": simple_world_comm_v3,\n", + " \"pz-mpe-simple-v3\": simple_v3,\n", + "}[env_name]\n", + "env = target_env.env(**env_cfg)\n", + "while isinstance(env, BaseWrapper): # Discard all wrappers\n", + " env = env.env\n", + "env.reset()\n", + "try:\n", + " env.env.render_mode = 'rgb_array' # We want a video of what our agent is doing.\n", + "except Exception:\n", + " env.render_mode = 'rgb_array' # For e.g. Pettingzoo, with no base env below.\n", + "agent_ids = {agent: torch.nn.functional.one_hot(torch.tensor(i), num_classes=len(env.agents)) for i, agent in enumerate(env.agents)}\n", + "env.reset()\n", + "rewards = defaultdict(lambda: 0)\n", + "random_act = False\n", + "images = []\n", + "\n", + "# We have one agent, so pad the observation with zeros and add a one-hot to the end.\n", + "def act(a, obs):\n", + " #obs = np.pad(obs, (0, env_info['obs_shape'] + len(env.agents) - len(obs)))\n", + " #obs[-len(env.agents):] = agent_ids[a]\n", + " n = env.action_space(a).n\n", + " action_logits, _ = agent(torch.tensor(obs), torch.tensor([]))\n", + " return action_logits[:n].argmax().numpy()\n", + "\n", + "while (True):\n", + " selected_agent = env.agent_selection\n", + " if (env.terminations[selected_agent] or env.truncations[selected_agent]):\n", + " break # Terminated or truncated.\n", + " obs = env.observe(selected_agent)\n", + " if (random_act): # Something to compare against, as a baseline.\n", + " action = env.action_space(selected_agent).sample()\n", + " else:\n", + " action = act(selected_agent, obs)\n", + " env.step(action)\n", + " rewards[selected_agent] += env.rewards[selected_agent]\n", + " images.append(env.render())\n", + "print(rewards)\n", + "# Display the video. Takes a few minutes with large images.\n", + "new_size = 200\n", + "gif_list = [Image.fromarray(x).resize((new_size,new_size)) for x in images]\n", + "gif_list[0].save(\"./test.gif\", save_all=True, append_images=gif_list[1:])\n", + "IPython.display.Image(filename='./test.gif')" + ], + "metadata": { + "id": "CO9yb4FQoXE1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 292 + }, + "cellView": "form", + "outputId": "e018d8db-9423-40f5-95a5-b95399c713f4" + }, + "execution_count": 9, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + ":4: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n", + " agent.load_state_dict(torch.load(f'{models_path}/agent.th', map_location=lambda storage, loc: storage))\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "defaultdict( at 0x7b2c45fd7a60>, {'agent_0': -11.212522623872562})\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "image/gif": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "execution_count": 9 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Train a model in a continuous setting" + ], + "metadata": { + "id": "vycSQ9s9-Lbd" + } + }, + { + "cell_type": "code", + "source": [ + "!python src/main.py --config=mappo_c --env-config=mpe_continuous with env_args.key=\"pz-mpe-simple-v3\" env_args.time_limit=25 env_args.max_cycles=25 save_model=True save_model_interval=20000 t_max=20000 batch_size_run=1 buffer_size=100 batch_size=100 obs_agent_id=False runner_log_interval=1000 learner_log_interval=1000 log_interval=1000 use_rnn=False" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "LWsKBcNsYGK4", + "outputId": "fedf6ee1-e4d1-4321-e5db-65697c22a3e1" + }, + "execution_count": 10, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[DEBUG 07:05:09] git.cmd Popen(['git', 'version'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'version'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'diff', '--cached', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'diff', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'cat-file', '--batch-check'], cwd=/content/epymarl_continuous, stdin=, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'diff', '--cached', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'diff', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'cat-file', '--batch-check'], cwd=/content/epymarl_continuous, stdin=, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'diff', '--cached', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'diff', '--abbrev=40', '--full-index', '--raw'], cwd=/content/epymarl_continuous, stdin=None, shell=False, universal_newlines=False)\n", + "[DEBUG 07:05:09] git.cmd Popen(['git', 'cat-file', '--batch-check'], cwd=/content/epymarl_continuous, stdin=, shell=False, universal_newlines=False)\n", + "[INFO 07:05:09] root Saving to FileStorageObserver in results/sacred.\n", + "[DEBUG 07:05:09] pymarl Using capture mode \"fd\"\n", + "[INFO 07:05:09] pymarl Running command 'my_main'\n", + "[INFO 07:05:09] pymarl Started run with ID \"1\"\n", + "[DEBUG 07:05:09] pymarl Starting Heartbeat\n", + "[DEBUG 07:05:09] my_main Started\n", + "[WARNING 07:05:09] my_main CUDA flag use_cuda was switched OFF automatically because no CUDA devices are available!\n", + "[INFO 07:05:09] my_main Experiment Parameters:\n", + "!!! USING MPE ENVIRONMENT\n", + "[INFO 07:05:09] my_main \n", + "\n", + "{ 'action_selector': 'continuous',\n", + " 'add_value_last_step': True,\n", + " 'agent': 'rnn',\n", + " 'agent_output_type': 'continuous_u_std',\n", + " 'batch_size': 100,\n", + " 'batch_size_run': 1,\n", + " 'buffer_cpu_only': True,\n", + " 'buffer_size': 100,\n", + " 'checkpoint_path': '',\n", + " 'common_reward': True,\n", + " 'critic_type': 'cv_critic',\n", + " 'entropy_coef': 0.001,\n", + " 'env': 'gymma',\n", + " 'env_args': { 'continuous_actions': True,\n", + " 'key': 'pz-mpe-simple-v3',\n", + " 'max_cycles': 25,\n", + " 'pretrained_wrapper': None,\n", + " 'seed': 801163060,\n", + " 'time_limit': 25},\n", + " 'epochs': 4,\n", + " 'eps_clip': 0.2,\n", + " 'evaluate': False,\n", + " 'gamma': 0.99,\n", + " 'grad_norm_clip': 10,\n", + " 'hidden_dim': 128,\n", + " 'hypergroup': None,\n", + " 'label': 'default_label',\n", + " 'learner': 'ppo_c_learner',\n", + " 'learner_log_interval': 1000,\n", + " 'load_step': 0,\n", + " 'local_results_path': 'results',\n", + " 'log_interval': 1000,\n", + " 'lr': 0.0003,\n", + " 'mac': 'basic_mac',\n", + " 'mask_before_softmax': False,\n", + " 'name': 'mappo_c',\n", + " 'obs_agent_id': False,\n", + " 'obs_individual_obs': False,\n", + " 'obs_last_action': False,\n", + " 'optim_alpha': 0.99,\n", + " 'optim_eps': 1e-05,\n", + " 'q_nstep': 5,\n", + " 'render': False,\n", + " 'repeat_id': 1,\n", + " 'reward_scalarisation': 'sum',\n", + " 'runner': 'parallel',\n", + " 'runner_log_interval': 1000,\n", + " 'save_model': True,\n", + " 'save_model_interval': 20000,\n", + " 'save_replay': False,\n", + " 'seed': 801163060,\n", + " 'standardise_returns': False,\n", + " 'standardise_rewards': True,\n", + " 't_max': 20000,\n", + " 'target_update_interval_or_tau': 0.01,\n", + " 'test_greedy': True,\n", + " 'test_interval': 50000,\n", + " 'test_nepisode': 100,\n", + " 'use_cuda': False,\n", + " 'use_rnn': False,\n", + " 'use_tensorboard': False,\n", + " 'use_wandb': False,\n", + " 'wandb_mode': 'offline',\n", + " 'wandb_project': None,\n", + " 'wandb_save_model': False,\n", + " 'wandb_team': None}\n", + "\n", + "error: XDG_RUNTIME_DIR not set in the environment.\n", + "!!! Using continuous action space\n", + "ARGS.agent_output_type equals continuous_u_std\n", + "ARGS.N_ACTIONS equals 10\n", + "BUILDING AGENTS! ARGS.N_ACTIONS = 10\n", + "Action min/max = tensor([0., 0., 0., 0., 0.])/tensor([1., 1., 1., 1., 1.])\n", + "[INFO 07:05:11] my_main Beginning training for 20000 timesteps\n", + "/usr/local/lib/python3.11/dist-packages/gymnasium/utils/passive_env_checker.py:245: UserWarning: \u001b[33mWARN: The reward returned by `step()` must be a float, int, np.integer or np.floating, actual type: \u001b[0m\n", + " logger.warn(\n", + "[INFO 07:05:11] my_main t_env: 25 / 20000\n", + "[INFO 07:05:11] my_main Estimated time left: 0 seconds. Time passed: 0 seconds\n", + "[INFO 07:05:17] my_main Saving models to results/models/mappo_c_seed801163060_pz-mpe-simple-v3_2025-01-20 07:05:09.806787/25\n", + "[INFO 07:05:19] my_main Recent Stats | t_env: 1000 | Episode: 40\n", + "ep_length_mean: 25.0000\treturn_mean: -97.4163\treturn_std: 0.0000\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:05:21] my_main Recent Stats | t_env: 2000 | Episode: 80\n", + "ep_length_mean: 25.0000\treturn_mean: -71.4287\treturn_std: 20.1024\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:05:28] my_main Recent Stats | t_env: 3000 | Episode: 120\n", + "advantage_mean: -0.0095\tagent_grad_norm: 23.9457\tcritic_grad_norm: 4.7066\tcritic_loss: 20.2512\n", + "ep_length_mean: 25.0000\tpg_loss: -0.7599\tq_taken_mean: -0.1117\treturn_mean: -60.6184\n", + "return_std: 25.0593\ttarget_mean: -0.1212\ttd_error_abs: 3.4306\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:05:40] my_main Recent Stats | t_env: 4000 | Episode: 160\n", + "advantage_mean: 0.1101\tagent_grad_norm: 12.8170\tcritic_grad_norm: 5.5825\tcritic_loss: 12.4351\n", + "ep_length_mean: 25.0000\tpg_loss: -0.9735\tq_taken_mean: -0.2281\treturn_mean: -55.4595\n", + "return_std: 27.0492\ttarget_mean: -0.1180\ttd_error_abs: 2.5364\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:05:52] my_main Recent Stats | t_env: 5000 | Episode: 200\n", + "advantage_mean: 0.0740\tagent_grad_norm: 8.9635\tcritic_grad_norm: 4.0214\tcritic_loss: 9.1564\n", + "ep_length_mean: 25.0000\tpg_loss: -0.6552\tq_taken_mean: -0.1237\treturn_mean: -50.9551\n", + "return_std: 26.0949\ttarget_mean: -0.0496\ttd_error_abs: 2.0248\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:06:02] my_main Recent Stats | t_env: 6000 | Episode: 240\n", + "advantage_mean: 0.0540\tagent_grad_norm: 7.2455\tcritic_grad_norm: 3.2324\tcritic_loss: 7.4218\n", + "ep_length_mean: 25.0000\tpg_loss: -0.4888\tq_taken_mean: 0.0144\treturn_mean: -37.4115\n", + "return_std: 30.4888\ttarget_mean: 0.0684\ttd_error_abs: 1.7751\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:06:16] my_main Recent Stats | t_env: 7000 | Episode: 280\n", + "advantage_mean: 0.0408\tagent_grad_norm: 5.9704\tcritic_grad_norm: 2.7585\tcritic_loss: 6.5333\n", + "ep_length_mean: 25.0000\tpg_loss: -0.3831\tq_taken_mean: 0.0559\treturn_mean: -35.0463\n", + "return_std: 28.2351\ttarget_mean: 0.0968\ttd_error_abs: 1.6686\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:06:29] my_main Recent Stats | t_env: 8000 | Episode: 320\n", + "advantage_mean: 0.0414\tagent_grad_norm: 1.6520\tcritic_grad_norm: 1.9828\tcritic_loss: 3.0511\n", + "ep_length_mean: 25.0000\tpg_loss: -0.2296\tq_taken_mean: 0.2686\treturn_mean: -34.1176\n", + "return_std: 27.1870\ttarget_mean: 0.3099\ttd_error_abs: 1.2362\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:06:41] my_main Recent Stats | t_env: 9000 | Episode: 360\n", + "advantage_mean: -0.0051\tagent_grad_norm: 1.8440\tcritic_grad_norm: 0.8005\tcritic_loss: 2.7219\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0039\tq_taken_mean: 0.8437\treturn_mean: -30.5352\n", + "return_std: 25.0523\ttarget_mean: 0.8387\ttd_error_abs: 1.1675\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:06:52] my_main Recent Stats | t_env: 10000 | Episode: 400\n", + "advantage_mean: -0.0098\tagent_grad_norm: 3.0485\tcritic_grad_norm: 0.7740\tcritic_loss: 2.6864\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0236\tq_taken_mean: 1.9520\treturn_mean: -28.5112\n", + "return_std: 24.8412\ttarget_mean: 1.9422\ttd_error_abs: 1.2034\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:07:05] my_main Recent Stats | t_env: 11000 | Episode: 440\n", + "advantage_mean: -0.0140\tagent_grad_norm: 3.4330\tcritic_grad_norm: 0.7819\tcritic_loss: 2.6649\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0405\tq_taken_mean: 3.4180\treturn_mean: -25.7437\n", + "return_std: 22.8684\ttarget_mean: 3.4040\ttd_error_abs: 1.2188\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:07:14] my_main Recent Stats | t_env: 12000 | Episode: 480\n", + "advantage_mean: -0.0128\tagent_grad_norm: 3.9679\tcritic_grad_norm: 0.7167\tcritic_loss: 2.3873\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0333\tq_taken_mean: 5.4551\treturn_mean: -21.8037\n", + "return_std: 20.2891\ttarget_mean: 5.4424\ttd_error_abs: 1.1596\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:07:25] my_main Recent Stats | t_env: 13000 | Episode: 520\n", + "advantage_mean: -0.0145\tagent_grad_norm: 4.1446\tcritic_grad_norm: 0.6684\tcritic_loss: 2.0717\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0400\tq_taken_mean: 7.6995\treturn_mean: -17.4344\n", + "return_std: 17.0198\ttarget_mean: 7.6850\ttd_error_abs: 1.0622\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:07:35] my_main Recent Stats | t_env: 14000 | Episode: 560\n", + "advantage_mean: -0.0129\tagent_grad_norm: 4.0729\tcritic_grad_norm: 0.6556\tcritic_loss: 1.6912\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0343\tq_taken_mean: 9.9183\treturn_mean: -14.9538\n", + "return_std: 14.6946\ttarget_mean: 9.9055\ttd_error_abs: 0.9435\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:07:47] my_main Recent Stats | t_env: 15000 | Episode: 600\n", + "advantage_mean: -0.0094\tagent_grad_norm: 3.3410\tcritic_grad_norm: 0.5496\tcritic_loss: 1.3534\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0200\tq_taken_mean: 11.8002\treturn_mean: -12.2838\n", + "return_std: 12.2316\ttarget_mean: 11.7909\ttd_error_abs: 0.8274\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:08:00] my_main Recent Stats | t_env: 16000 | Episode: 640\n", + "advantage_mean: -0.0036\tagent_grad_norm: 2.8306\tcritic_grad_norm: 0.4950\tcritic_loss: 1.0917\n", + "ep_length_mean: 25.0000\tpg_loss: -0.0034\tq_taken_mean: 13.4693\treturn_mean: -10.5366\n", + "return_std: 11.0997\ttarget_mean: 13.4657\ttd_error_abs: 0.7254\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:08:15] my_main Recent Stats | t_env: 17000 | Episode: 680\n", + "advantage_mean: -0.0062\tagent_grad_norm: 2.4501\tcritic_grad_norm: 0.5308\tcritic_loss: 0.9181\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0108\tq_taken_mean: 14.7738\treturn_mean: -9.7938\n", + "return_std: 10.0751\ttarget_mean: 14.7676\ttd_error_abs: 0.6425\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:08:24] my_main Recent Stats | t_env: 18000 | Episode: 720\n", + "advantage_mean: -0.0072\tagent_grad_norm: 2.3061\tcritic_grad_norm: 0.5755\tcritic_loss: 0.7976\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0196\tq_taken_mean: 15.8772\treturn_mean: -9.1509\n", + "return_std: 8.8361\ttarget_mean: 15.8700\ttd_error_abs: 0.5875\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:08:35] my_main Recent Stats | t_env: 19000 | Episode: 760\n", + "advantage_mean: -0.0118\tagent_grad_norm: 2.0626\tcritic_grad_norm: 0.6216\tcritic_loss: 0.6859\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0435\tq_taken_mean: 16.8370\treturn_mean: -9.4669\n", + "return_std: 8.6544\ttarget_mean: 16.8252\ttd_error_abs: 0.5461\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:08:44] my_main Recent Stats | t_env: 20000 | Episode: 800\n", + "advantage_mean: -0.0124\tagent_grad_norm: 1.7033\tcritic_grad_norm: 0.6542\tcritic_loss: 0.6621\n", + "ep_length_mean: 25.0000\tpg_loss: 0.0461\tq_taken_mean: 17.6163\treturn_mean: -9.8666\n", + "return_std: 9.3582\ttarget_mean: 17.6039\ttd_error_abs: 0.5283\ttest_ep_length_mean: 25.0000\n", + "test_return_mean: -36.2057\ttest_return_std: 29.6607\t\n", + "[INFO 07:08:45] my_main Saving models to results/models/mappo_c_seed801163060_pz-mpe-simple-v3_2025-01-20 07:05:09.806787/20025\n", + "[INFO 07:08:45] my_main Finished Training\n", + "Exiting Main\n", + "Stopping all threads\n", + "Thread Thread-1 is alive! Is daemon: False\n", + "Thread joined\n", + "Exiting script\n", + "[DEBUG 07:08:46] my_main Finished after 0:03:36.\n", + "[INFO 07:08:46] pymarl Completed after 0:03:36\n", + "[DEBUG 07:08:46] pymarl Stopping Heartbeat\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### View training results" + ], + "metadata": { + "id": "4I9MK2CN-Qgd" + } + }, + { + "cell_type": "code", + "source": [ + "# @title Display reward over time\n", + "env_name = 'pz-mpe-simple-v3'\n", + "alg_name = 'mappo_c'\n", + "\n", + "results_path = '/content/epymarl_continuous/results'\n", + "sacred_path = f'{results_path}/sacred/{alg_name}/pz-mpe-simple-v3'\n", + "results_dir = max([os.path.join(sacred_path, d) for d in os.listdir(sacred_path)], key=os.path.getmtime).split('/')[-1]\n", + "\n", + "models_path = f'{results_path}/models'\n", + "models_path = max([os.path.join(models_path, d) for d in os.listdir(models_path)], key=os.path.getmtime) # Newest run\n", + "models_path = max([os.path.join(models_path, d) for d in os.listdir(models_path)], key=os.path.getmtime) # Last update\n", + "\n", + "with open(f'{sacred_path}/{results_dir}/metrics.json', 'r') as f:\n", + " metrics = json.load(f)\n", + "metrics.keys()\n", + "plt.plot(metrics['return_mean']['values'])" + ], + "metadata": { + "id": "PThcSORUSxIm", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 448 + }, + "cellView": "form", + "outputId": "a925b54d-6ddc-4095-fcef-bb5915dbdff8" + }, + "execution_count": 11, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[]" + ] + }, + "metadata": {}, + "execution_count": 11 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "# @title Look up env data\n", + "# Get config dicts\n", + "cfg_path = '/content/epymarl_continuous/src/config'\n", + "alg_name = 'mappo'\n", + "\n", + "def recursive_dict_update(d, u):\n", + " for k, v in u.items():\n", + " if isinstance(v, Mapping):\n", + " d[k] = recursive_dict_update(d.get(k, {}), v)\n", + " else:\n", + " d[k] = v\n", + " return d\n", + "with open(os.path.join(cfg_path,\"default.yaml\",),\"r\",) as f:\n", + " cfg_dict = yaml.load(f, Loader=yaml.FullLoader)\n", + "with open(os.path.join(cfg_path,\"envs\",\"mpe.yaml\",),\"r\",) as f:\n", + " env_dict = yaml.load(f, Loader=yaml.FullLoader)\n", + "with open(os.path.join(cfg_path,\"algs\",f\"{alg_name}.yaml\",),\"r\",) as f:\n", + " alg_dict = yaml.load(f, Loader=yaml.FullLoader)\n", + "config_dict = recursive_dict_update(cfg_dict, env_dict)\n", + "config_dict = recursive_dict_update(cfg_dict, alg_dict)\n", + "#\n", + "config_dict[\"env_args\"][\"seed\"] = 0\n", + "config_dict[\"env_args\"][\"key\"] = env_name\n", + "config_dict[\"env_args\"][\"time_limit\"]=25\n", + "#\n", + "args = SN(**config_dict)\n", + "args.device = \"cpu\"\n", + "args.unique_token = 'TESTTESTTEST'\n", + "#\n", + "runner = r_REGISTRY[args.runner](args=args,logger=None) # Some algs () use parallel. batch_size_run increases parallelism. ippo, coma, ia2c, maa2c, mappo\n", + "env_info = runner.get_env_info()\n", + "args.n_agents = env_info[\"n_agents\"]\n", + "args.n_actions = env_info[\"n_actions\"]\n", + "args.state_shape = env_info[\"state_shape\"]" + ], + "metadata": { + "cellView": "form", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Fc21TOLrKjqN", + "outputId": "4b44da63-713e-4369-8efe-c4ceba76f7fd" + }, + "execution_count": 13, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "!!! USING MPE ENVIRONMENT\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# @title Display a sample run\n", + "args_temp = copy.copy(args)\n", + "args_temp.use_rnn = False # Since the default is apparently 'true' for MAPPO but not MAPPO_NS\n", + "args_temp.n_actions *= 2\n", + "agent = RNNAgent(env_info['obs_shape'], args_temp)\n", + "agent.load_state_dict(torch.load(f'{models_path}/agent.th', map_location=lambda storage, loc: storage))\n", + "selector = ContinuousSelector(args_temp)\n", + "\n", + "env_cfg = {'max_cycles': 75, 'continuous_actions': True}\n", + "target_env = simple_v3\n", + "\n", + "env = target_env.env(**env_cfg)\n", + "while isinstance(env, BaseWrapper): # Discard all wrappers\n", + " env = env.env\n", + "env.reset()\n", + "try:\n", + " env.env.render_mode = 'rgb_array' # We want a video of what our agent is doing.\n", + "except Exception:\n", + " env.render_mode = 'rgb_array' # For e.g. Pettingzoo, with no base env below.\n", + "\n", + "env.reset()\n", + "rewards = defaultdict(lambda: 0)\n", + "random_act = False\n", + "images = []\n", + "\n", + "# We have one agent, so pad the observation with zeros and add a one-hot to the end.\n", + "def act(a, obs, selector):\n", + " #obs = np.pad(obs, (0, env_info['obs_shape'] + len(env.agents) - len(obs)))\n", + " #obs[-len(env.agents):] = agent_ids[a]\n", + " agent_out, _ = agent(torch.tensor(obs), torch.tensor([]))\n", + " agent_out = agent_out.unsqueeze(0).unsqueeze(0)\n", + " action = selector.select_action(agent_out, None, None)\n", + " return action.squeeze()\n", + "\n", + "while (True):\n", + " selected_agent = env.agent_selection\n", + " if (env.terminations[selected_agent] or env.truncations[selected_agent]):\n", + " break # Terminated or truncated.\n", + " obs = env.observe(selected_agent)\n", + " if (random_act): # Something to compare against, as a baseline.\n", + " action = env.action_space(selected_agent).sample()\n", + " else:\n", + " action = act(selected_agent, obs, selector)\n", + " env.step(action)\n", + " rewards[selected_agent] += env.rewards[selected_agent]\n", + " images.append(env.render())\n", + "print(rewards)\n", + "\n", + "# Display the video. Takes a few minutes with large images.\n", + "new_size = 200\n", + "gif_list = [Image.fromarray(x).resize((new_size,new_size)) for x in images]\n", + "gif_list[0].save(\"./test.gif\", save_all=True, append_images=gif_list[1:])\n", + "IPython.display.Image(filename='./test.gif')" + ], + "metadata": { + "id": "AfFEXmYzTBvI", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 292 + }, + "outputId": "bc73fd68-5d57-42bc-b1c1-58ee8cebc7a0", + "cellView": "form" + }, + "execution_count": 16, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + ":6: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n", + " agent.load_state_dict(torch.load(f'{models_path}/agent.th', map_location=lambda storage, loc: storage))\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "defaultdict( at 0x7b2c3b28e200>, {'agent_0': -15.912209230865944})\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "image/gif": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "execution_count": 16 + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "ZoRd5y2_i7su" + }, + "execution_count": null, + "outputs": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index de960f82..969163df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ pygame pyparsing pytest python-dateutil -PyYAML==5.3.1 +PyYAML requests sacred seaborn @@ -34,3 +34,4 @@ urllib3 websocket-client whichcraft wrapt +sacred \ No newline at end of file diff --git a/src/components/action_selectors.py b/src/components/action_selectors.py index 9115b84a..241b0bb0 100644 --- a/src/components/action_selectors.py +++ b/src/components/action_selectors.py @@ -1,14 +1,13 @@ import torch as th +import torch.nn.functional as F from torch.distributions import Categorical from .epsilon_schedules import DecayThenFlatSchedule REGISTRY = {} -class MultinomialActionSelector(): - +class MultinomialActionSelector(): # Multinomial distribution of action probabilities def __init__(self, args): self.args = args - self.schedule = DecayThenFlatSchedule(args.epsilon_start, args.epsilon_finish, args.epsilon_anneal_time, decay="linear") self.epsilon = self.schedule.eval(0) @@ -17,62 +16,65 @@ def __init__(self, args): def select_action(self, agent_inputs, avail_actions, t_env, test_mode=False): masked_policies = agent_inputs.clone() masked_policies[avail_actions == 0.0] = 0.0 - self.epsilon = self.schedule.eval(t_env) - if test_mode and self.test_greedy: picked_actions = masked_policies.max(dim=2)[1] else: picked_actions = Categorical(masked_policies).sample().long() - return picked_actions - REGISTRY["multinomial"] = MultinomialActionSelector - -class EpsilonGreedyActionSelector(): - +class EpsilonGreedyActionSelector(): # epsilon greedy action selection def __init__(self, args): self.args = args - - self.schedule = DecayThenFlatSchedule(args.epsilon_start, args.epsilon_finish, args.epsilon_anneal_time, - decay="linear") + self.schedule = DecayThenFlatSchedule(args.epsilon_start, args.epsilon_finish, args.epsilon_anneal_time, decay="linear") self.epsilon = self.schedule.eval(0) - def select_action(self, agent_inputs, avail_actions, t_env, test_mode=False): - # Assuming agent_inputs is a batch of Q-Values for each agent bav self.epsilon = self.schedule.eval(t_env) - if test_mode: # Greedy action selection only self.epsilon = self.args.evaluation_epsilon - # mask actions that are excluded from selection masked_q_values = agent_inputs.clone() masked_q_values[avail_actions == 0.0] = -float("inf") # should never be selected! - random_numbers = th.rand_like(agent_inputs[:, :, 0]) pick_random = (random_numbers < self.epsilon).long() random_actions = Categorical(avail_actions.float()).sample().long() - picked_actions = pick_random * random_actions + (1 - pick_random) * masked_q_values.max(dim=2)[1] return picked_actions - REGISTRY["epsilon_greedy"] = EpsilonGreedyActionSelector - -class SoftPoliciesSelector(): - +class SoftPoliciesSelector(): # Categorical distribution, softmaxed action logits def __init__(self, args): self.args = args - def select_action(self, agent_inputs, avail_actions, t_env, test_mode=False): m = Categorical(agent_inputs) picked_actions = m.sample().long() return picked_actions +REGISTRY["soft_policies"] = SoftPoliciesSelector -REGISTRY["soft_policies"] = SoftPoliciesSelector \ No newline at end of file +class ContinuousSelector(): # Means and standard deviations of normal distributions. [:k], [k:] + def __init__(self, args): + self.args = args + def select_action(self,agent_inputs,avail_actions,t_env,test_mode=False): + with th.no_grad(): + #print("SELECT ACTION called!") + #print(avail_actions) + k = agent_inputs.shape[-1]//2 + #print(f"!!!! {k}") + #print(agent_inputs) + #print(agent_inputs.shape) + u, var = agent_inputs[:,:,:k], agent_inputs[:,:,k:] + u, var = F.tanh(u), th.sqrt(F.softplus(var)) + action_dist = th.distributions.Normal(u, var) + action = action_dist.sample() + # For now, clip actions to [0,1] manually. + action = th.clip(action,min=0,max=1) + #print(action) + return action + +REGISTRY["continuous"] = ContinuousSelector \ No newline at end of file diff --git a/src/components/episode_buffer.py b/src/components/episode_buffer.py index ca75eab5..269d36c1 100644 --- a/src/components/episode_buffer.py +++ b/src/components/episode_buffer.py @@ -86,7 +86,8 @@ def to(self, device): def update(self, data, bs=slice(None), ts=slice(None), mark_filled=True): slices = self._parse_slices((bs, ts)) - for k, v in data.items(): + #print(f"!!! Updating buffer with data: {data}") + for k, v in data.items(): # Maps each field to save to its value. if k in self.data.transition_data: target = self.data.transition_data if mark_filled: @@ -245,5 +246,4 @@ def __repr__(self): return "ReplayBuffer. {}/{} episodes. Keys:{} Groups:{}".format(self.episodes_in_buffer, self.buffer_size, self.scheme.keys(), - self.groups.keys()) - + self.groups.keys()) \ No newline at end of file diff --git a/src/config/algs/mappo_c.yaml b/src/config/algs/mappo_c.yaml new file mode 100644 index 00000000..00ee92eb --- /dev/null +++ b/src/config/algs/mappo_c.yaml @@ -0,0 +1,34 @@ +# --- MAPPO specific parameters --- + +action_selector: "continuous" +mask_before_softmax: False + +runner: "parallel" + +buffer_size: 10 +batch_size_run: 10 +batch_size: 10 + +# update the target network every {} training steps +target_update_interval_or_tau: 0.01 + +lr: 0.0003 +hidden_dim: 128 + +obs_agent_id: False +obs_last_action: False +obs_individual_obs: False + +agent_output_type: "continuous_u_std" # Continuous means and stds +learner: "ppo_c_learner" +entropy_coef: 0.001 +use_rnn: False +standardise_returns: False +standardise_rewards: True +q_nstep: 5 # 1 corresponds to normal r + gammaV +critic_type: "cv_critic" +epochs: 4 +eps_clip: 0.2 +name: "mappo_c" + +t_max: 20050000 diff --git a/src/config/envs/mpe.yaml b/src/config/envs/mpe.yaml new file mode 100644 index 00000000..2ee6fafb --- /dev/null +++ b/src/config/envs/mpe.yaml @@ -0,0 +1,16 @@ +env: "gymma" + +env_args: + key: null + time_limit: 100 + pretrained_wrapper: null + max_cycles: 100 + continuous_actions: False + +test_greedy: True +test_nepisode: 100 +test_interval: 50000 +log_interval: 50000 +runner_log_interval: 10000 +learner_log_interval: 10000 +t_max: 2050000 \ No newline at end of file diff --git a/src/config/envs/mpe_continuous.yaml b/src/config/envs/mpe_continuous.yaml new file mode 100644 index 00000000..20be82d5 --- /dev/null +++ b/src/config/envs/mpe_continuous.yaml @@ -0,0 +1,16 @@ +env: "gymma" + +env_args: + key: null + time_limit: 100 + pretrained_wrapper: null + max_cycles: 100 + continuous_actions: True + +test_greedy: True +test_nepisode: 100 +test_interval: 50000 +log_interval: 50000 +runner_log_interval: 10000 +learner_log_interval: 10000 +t_max: 2050000 \ No newline at end of file diff --git a/src/controllers/basic_controller.py b/src/controllers/basic_controller.py index a64d3bef..34825556 100644 --- a/src/controllers/basic_controller.py +++ b/src/controllers/basic_controller.py @@ -19,24 +19,26 @@ def __init__(self, scheme, groups, args): def select_actions(self, ep_batch, t_ep, t_env, bs=slice(None), test_mode=False): # Only select actions for the selected batch elements in bs avail_actions = ep_batch["avail_actions"][:, t_ep] + # agent_outputs is log probabilities here. agent_outputs = self.forward(ep_batch, t_ep, test_mode=test_mode) chosen_actions = self.action_selector.select_action(agent_outputs[bs], avail_actions[bs], t_env, test_mode=test_mode) return chosen_actions def forward(self, ep_batch, t, test_mode=False): + # Passes agent_inputs = self._build_inputs(ep_batch, t) avail_actions = ep_batch["avail_actions"][:, t] agent_outs, self.hidden_states = self.agent(agent_inputs, self.hidden_states) - # Softmax the agent outputs if they're policy logits if self.agent_output_type == "pi_logits": - if getattr(self.args, "mask_before_softmax", True): # Make the logits for unavailable actions very negative to minimise their affect on the softmax reshaped_avail_actions = avail_actions.reshape(ep_batch.batch_size * self.n_agents, -1) agent_outs[reshaped_avail_actions == 0] = -1e10 agent_outs = th.nn.functional.softmax(agent_outs, dim=-1) - + elif self.agent_output_type == "continuous_u_std": + # Runs before select_actions; SA has it from here. + pass return agent_outs.view(ep_batch.batch_size, self.n_agents, -1) def init_hidden(self, batch_size): @@ -58,6 +60,7 @@ def load_models(self, path): self.agent.load_state_dict(th.load("{}/agent.th".format(path), map_location=lambda storage, loc: storage)) def _build_agents(self, input_shape): + print(f"BUILDING AGENTS! ARGS.N_ACTIONS = {self.args.n_actions}") self.agent = agent_REGISTRY[self.args.agent](input_shape, self.args) def _build_inputs(self, batch, t): @@ -83,5 +86,4 @@ def _get_input_shape(self, scheme): input_shape += scheme["actions_onehot"]["vshape"][0] if self.args.obs_agent_id: input_shape += self.n_agents - - return input_shape + return input_shape \ No newline at end of file diff --git a/src/envs/__init__.py b/src/envs/__init__.py index 55fec42a..c35ef307 100644 --- a/src/envs/__init__.py +++ b/src/envs/__init__.py @@ -3,7 +3,7 @@ from .multiagentenv import MultiAgentEnv from .gymma import GymmaWrapper -from .smaclite_wrapper import SMACliteWrapper +#from .smaclite_wrapper import SMACliteWrapper # Appears to be broken at the moment. if sys.platform == "linux": diff --git a/src/envs/gymma.py b/src/envs/gymma.py index aeba61fa..aa4cac86 100644 --- a/src/envs/gymma.py +++ b/src/envs/gymma.py @@ -8,22 +8,9 @@ from .multiagentenv import MultiAgentEnv from .wrappers import FlattenObservation +from .pz_wrapper import PettingZooWrapper # noqa import envs.pretrained as pretrained # noqa -try: - from .pz_wrapper import PettingZooWrapper # noqa -except ImportError: - warnings.warn( - "PettingZoo is not installed, so these environments will not be available! To install, run `pip install pettingzoo`" - ) - -try: - from .vmas_wrapper import VMASWrapper # noqa -except ImportError: - warnings.warn( - "VMAS is not installed, so these environments will not be available! To install, run `pip install 'vmas[gymnasium]'`" - ) - class GymmaWrapper(MultiAgentEnv): def __init__( @@ -48,7 +35,17 @@ def __init__( self._obs = None self._info = None - self.longest_action_space = max(self._env.action_space, key=lambda x: x.n) + try: + self.longest_action_space = max(self._env.action_space, key=lambda x: x.n) + self.cont_space = False + self.continuous_action_space = False + except Exception as e: + print('!!! Using continuous action space') + self.cont_space = True + self.longest_action_space = max(self._env.action_space, key=lambda x: x.shape) + self.action_space_min = min(self._env.action_space, key=lambda x: x.low).low + self.action_space_max = max(self._env.action_space, key=lambda x: x.high).high + self.continuous_action_space = True self.longest_observation_space = max( self._env.observation_space, key=lambda x: x.shape ) @@ -83,7 +80,11 @@ def _pad_observation(self, obs): def step(self, actions): """Returns obss, reward, terminated, truncated, info""" - actions = [int(a) for a in actions] + #print(f"!!!!! processing actions: {actions}") + if (self.cont_space): + actions = [np.array(a) for a in actions] + else: + actions = [int(a) for a in actions] obs, reward, done, truncated, self._info = self._env.step(actions) self._obs = self._pad_observation(obs) @@ -129,7 +130,10 @@ def get_avail_actions(self): def get_avail_agent_actions(self, agent_id): """Returns the available actions for agent_id""" valid = flatdim(self._env.action_space[agent_id]) * [1] - invalid = [0] * (self.longest_action_space.n - len(valid)) + if (self.cont_space): + invalid = [0] * (self.longest_action_space.shape[0] - len(valid)) + else: + invalid = [0] * (self.longest_action_space.n - len(valid)) return valid + invalid def get_total_actions(self): @@ -137,6 +141,19 @@ def get_total_actions(self): # TODO: This is only suitable for a discrete 1 dimensional action space for each agent return flatdim(self.longest_action_space) + def get_env_info(self): + env_info = { + "state_shape": self.get_state_size(), + "obs_shape": self.get_obs_size(), + "n_actions": self.get_total_actions(), + "n_agents": self.n_agents, + "episode_limit": self.episode_limit, + } + if (self.continuous_action_space): + env_info['action_min'] = self.action_space_min + env_info['action_max'] = self.action_space_max + return env_info + def reset(self, seed=None, options=None): """Returns initial observations and info""" obs, info = self._env.reset(seed=seed, options=options) diff --git a/src/envs/pz_wrapper.py b/src/envs/pz_wrapper.py index 6fac1df3..1ac2343a 100644 --- a/src/envs/pz_wrapper.py +++ b/src/envs/pz_wrapper.py @@ -22,10 +22,10 @@ def __init__(self, lib_name, env_name, **kwargs): self.last_obs = None self.action_space = Tuple( - tuple([self._env.action_spaces[k] for k in self._env.agents]) + tuple([self._env.action_space(k) for k in self._env.agents]) ) self.observation_space = Tuple( - tuple([self._env.observation_spaces[k] for k in self._env.agents]) + tuple([self._env.observation_space(k) for k in self._env.agents]) ) def reset(self, *args, **kwargs): diff --git a/src/learners/__init__.py b/src/learners/__init__.py index 0e9bd10a..48add35c 100644 --- a/src/learners/__init__.py +++ b/src/learners/__init__.py @@ -6,6 +6,7 @@ from .actor_critic_pac_dcg_learner import PACDCGLearner from .maddpg_learner import MADDPGLearner from .ppo_learner import PPOLearner +from .ppo_c_learner import PPOLearner_C REGISTRY = {} @@ -15,5 +16,6 @@ REGISTRY["actor_critic_learner"] = ActorCriticLearner REGISTRY["maddpg_learner"] = MADDPGLearner REGISTRY["ppo_learner"] = PPOLearner +REGISTRY['ppo_c_learner'] = PPOLearner_C REGISTRY["pac_learner"] = PACActorCriticLearner -REGISTRY["pac_dcg_learner"] = PACDCGLearner +REGISTRY["pac_dcg_learner"] = PACDCGLearner \ No newline at end of file diff --git a/src/learners/ppo_c_learner.py b/src/learners/ppo_c_learner.py new file mode 100644 index 00000000..a497f6b1 --- /dev/null +++ b/src/learners/ppo_c_learner.py @@ -0,0 +1,349 @@ +import copy + +import torch as th +from torch.optim import Adam +import torch.nn.functional as F + +from components.episode_buffer import EpisodeBatch +from components.standarize_stream import RunningMeanStd +from modules.critics import REGISTRY as critic_resigtry + + +class PPOLearner_C: + def __init__(self, mac, scheme, logger, args): + self.args = args + self.n_agents = args.n_agents + self.n_actions = args.n_actions + # Add action range + self.action_min = th.tensor(args.action_min) + self.action_max = th.tensor(args.action_max) + print(f"Action min/max = {self.action_min}/{self.action_max}") + self.logger = logger + + self.mac = mac + self.old_mac = copy.deepcopy(mac) + self.agent_params = list(mac.parameters()) + self.agent_optimiser = Adam(params=self.agent_params, lr=args.lr) + + self.critic = critic_resigtry[args.critic_type](scheme, args) + self.target_critic = copy.deepcopy(self.critic) + + self.critic_params = list(self.critic.parameters()) + self.critic_optimiser = Adam(params=self.critic_params, lr=args.lr) + + self.last_target_update_step = 0 + self.critic_training_steps = 0 + self.log_stats_t = -self.args.learner_log_interval - 1 + + device = "cuda" if args.use_cuda else "cpu" + if self.args.standardise_returns: + self.ret_ms = RunningMeanStd(shape=(self.n_agents,), device=device) + if self.args.standardise_rewards: + rew_shape = (1,) if self.args.common_reward else (self.n_agents,) + self.rew_ms = RunningMeanStd(shape=rew_shape, device=device) + + ############################################################# + ## ----- Retrieves probabilities (old_pi) of actions ----- ## + ############################################################# + def get_discrete_log_probs(self, batch, mask, actions, mac): + mac = [] # The outputs of the old multi-agent controller + mac.init_hidden(batch.batch_size) # Only for recurrent + for t in range(batch.max_seq_length - 1): + agent_outs = mac.forward(batch, t=t) + mac_out.append(agent_outs) + mac_out = th.stack(mac_out, dim=1) # Concat over time + p_i = mac_out # [batch, num_actions] + p_i[mask == 0] = 1.0 + p_i_taken = th.gather(p_i, dim=3, index=actions).squeeze(3) + log_pi_taken = th.log(p_i_taken + 1e-10) + return log_pi_taken + + def construct_cont_dist(self, o): + #print(o.shape) # 100,max_timesteps,1,10 + na = o.shape[-1]//2 + means, vars = o[:,:,:,:na], o[:,:,:,na:] + means, stds = F.tanh(means), th.sqrt(F.softplus(vars)) + # Force means into the target range. Same for std. devs, but half the range (as a generally good heuristic) + means = th.clamp(means, min=self.action_min, max=self.action_max) + action_range = self.action_max - self.action_min + mins = (th.zeros_like(action_range)+1e-3).unsqueeze(0).unsqueeze(0).unsqueeze(0) + maxes = (action_range/2).unsqueeze(0).unsqueeze(0).unsqueeze(0) + stds = th.clamp(stds, min=mins, max=maxes) + #stds = stds * 0 + 0.5 # Try just hard-fixing it to 0.5 (OKAY, THIS LINE WORKS! Note that this is just for optimization, std is not fixed in runtime) + # End of test + action_dists = th.distributions.Normal(means, stds) + return action_dists + + def get_continuous_log_probs(self, batch, mask, actions, mac): + #print("Get Continuous Log Probs called!") + #print(actions.shape) # 100, 100, 1, agent_output size + #print(mask.shape) # [100,100,1], looks like all ones. + mac_out = [] # The outputs of the old multi-agent controller + self.mac.init_hidden(batch.batch_size) # Only for recurrent + for t in range(batch.max_seq_length - 1): # [batch, num_actions] + agent_outs = self.mac.forward(batch, t=t) # 100, 1, 5 in discrete, 100, 1, 10 in continuous + mac_out.append(agent_outs) + mac_out = th.stack(mac_out, dim=1) # Concat over time + dists = self.construct_cont_dist(mac_out) # [batch, num_actions] -> MAC should output probs. + # Note that 'taken' is no longer used; continuous outputs always taken. + log_pi = dists.log_prob(actions).sum(axis=1) + entropy = 0 + #print(dists.entropy().shape) #100,100,1,5 + if (mac == self.mac): + entropy = dists.entropy().squeeze() + return log_pi, entropy + + ############################################################# + ## --------------------- Runs Training ------------------- ## + ############################################################# + def train(self, batch: EpisodeBatch, t_env: int, episode_num: int): + # Get the relevant quantities + + rewards = batch["reward"][:, :-1] + actions = batch["actions"][:, :] + terminated = batch["terminated"][:, :-1].float() + mask = batch["filled"][:, :-1].float() + mask[:, 1:] = mask[:, 1:] * (1 - terminated[:, :-1]) + actions = actions[:, :-1] + + if self.args.standardise_rewards: + self.rew_ms.update(rewards) + rewards = (rewards - self.rew_ms.mean) / th.sqrt(self.rew_ms.var) + + if self.args.common_reward: + assert ( + rewards.size(2) == 1 + ), "Expected singular agent dimension for common rewards" + # reshape rewards to be of shape (batch_size, episode_length, n_agents) + rewards = rewards.expand(-1, -1, self.n_agents) + + mask = mask.repeat(1, 1, self.n_agents) + + critic_mask = mask.clone() + + # This needs to be replaced with continuous probabilities + #old_log_pi = self.get_discrete_log_probs(batch, mask, actions, self.old_mac) + old_log_pi, _ = self.get_continuous_log_probs(batch, mask, actions, self.old_mac) + + # In discrete mode, gets the indices of the old MAC's actions and uses them to grab the corresponding log probabilities. + for k in range(self.args.epochs): + # Training the critic shouldn't affect action probabilities, so I've moved this out of the middle of the probability calc. + advantages, critic_train_stats = self.train_critic_sequential( + self.critic, self.target_critic, batch, rewards, critic_mask + ) + advantages = advantages.detach() + ### Calculate log probabilities + #log_pi_taken = self.get_discrete_log_probs(batch, mask, actions, self.mac) + log_pi, entropy = self.get_continuous_log_probs(batch, mask, actions, self.mac) + + ratios = th.exp(log_pi - old_log_pi.detach()) + # surr1 can have + and - infinity as values + surr1 = ratios * advantages + surr2 = ( + th.clamp(ratios, 1 - self.args.eps_clip, 1 + self.args.eps_clip) + * advantages + ) + + # torch.Size([100, 1, 1, 5]) + #print((th.min(surr1, surr2)).shape) # torch.Size([100, 100, 5]) + #print(entropy.shape) # torch.Size([100, 100, 5]) + # Calculate entropy of normal (rather than categorical) distribution + #entropy = -th.sum(pi * th.log(pi + 1e-10), dim=-1) + + # Calculate total loss + pg_loss = ( + -( + (th.min(surr1, surr2) + self.args.entropy_coef * entropy) * mask + ).sum() + / mask.sum() + ) + + if (th.isnan(pg_loss) or th.isinf(pg_loss)): + print(pg_loss) + print("NEW LOG PI") + print(log_pi.min()) + print(log_pi.max()) + print("RATIOS") + print(ratios.min()) + print(ratios.max()) + print("SURR1") + print(surr1.min()) + print(surr1.max()) + print("SURR2") + print(surr2.min()) + print(surr2.max()) + print("ENTROPY") + print(entropy.min()) + print(entropy.max()) + print("!!!!!!!!!!!!!!!!!!!!!") + sdfafsdadsfasadfasdfasdfasdf + + # Optimise agents + self.agent_optimiser.zero_grad() + pg_loss.backward() + grad_norm = th.nn.utils.clip_grad_norm_( + self.agent_params, self.args.grad_norm_clip + ) + self.agent_optimiser.step() + + self.old_mac.load_state(self.mac) + + self.critic_training_steps += 1 + if ( + self.args.target_update_interval_or_tau > 1 + and (self.critic_training_steps - self.last_target_update_step) + / self.args.target_update_interval_or_tau + >= 1.0 + ): + self._update_targets_hard() + self.last_target_update_step = self.critic_training_steps + elif self.args.target_update_interval_or_tau <= 1.0: + self._update_targets_soft(self.args.target_update_interval_or_tau) + + if t_env - self.log_stats_t >= self.args.learner_log_interval: + ts_logged = len(critic_train_stats["critic_loss"]) + for key in [ + "critic_loss", + "critic_grad_norm", + "td_error_abs", + "q_taken_mean", + "target_mean", + ]: + self.logger.log_stat( + key, sum(critic_train_stats[key]) / ts_logged, t_env + ) + + self.logger.log_stat( + "advantage_mean", + (advantages * mask).sum().item() / mask.sum().item(), + t_env, + ) + self.logger.log_stat("pg_loss", pg_loss.item(), t_env) + self.logger.log_stat("agent_grad_norm", grad_norm.item(), t_env) + '''self.logger.log_stat( + "pi_max", + (pi.max(dim=-1)[0] * mask).sum().item() / mask.sum().item(), + t_env, + )''' # Not readily applicable to continuous spaces + self.log_stats_t = t_env + + def train_critic_sequential(self, critic, target_critic, batch, rewards, mask): + # Optimise critic + with th.no_grad(): + target_vals = target_critic(batch) + target_vals = target_vals.squeeze(3) + + if self.args.standardise_returns: + target_vals = target_vals * th.sqrt(self.ret_ms.var) + self.ret_ms.mean + + target_returns = self.nstep_returns( + rewards, mask, target_vals, self.args.q_nstep + ) + if self.args.standardise_returns: + self.ret_ms.update(target_returns) + target_returns = (target_returns - self.ret_ms.mean) / th.sqrt( + self.ret_ms.var + ) + + running_log = { + "critic_loss": [], + "critic_grad_norm": [], + "td_error_abs": [], + "target_mean": [], + "q_taken_mean": [], + } + + v = critic(batch)[:, :-1].squeeze(3) + td_error = target_returns.detach() - v + masked_td_error = td_error * mask + loss = (masked_td_error**2).sum() / mask.sum() + + self.critic_optimiser.zero_grad() + loss.backward() + grad_norm = th.nn.utils.clip_grad_norm_( + self.critic_params, self.args.grad_norm_clip + ) + self.critic_optimiser.step() + + running_log["critic_loss"].append(loss.item()) + running_log["critic_grad_norm"].append(grad_norm.item()) + mask_elems = mask.sum().item() + running_log["td_error_abs"].append( + (masked_td_error.abs().sum().item() / mask_elems) + ) + running_log["q_taken_mean"].append((v * mask).sum().item() / mask_elems) + running_log["target_mean"].append( + (target_returns * mask).sum().item() / mask_elems + ) + + return masked_td_error, running_log + + def nstep_returns(self, rewards, mask, values, nsteps): + nstep_values = th.zeros_like(values[:, :-1]) + for t_start in range(rewards.size(1)): + nstep_return_t = th.zeros_like(values[:, 0]) + for step in range(nsteps + 1): + t = t_start + step + if t >= rewards.size(1): + break + elif step == nsteps: + nstep_return_t += ( + self.args.gamma ** (step) * values[:, t] * mask[:, t] + ) + elif t == rewards.size(1) - 1 and self.args.add_value_last_step: + nstep_return_t += ( + self.args.gamma ** (step) * rewards[:, t] * mask[:, t] + ) + nstep_return_t += self.args.gamma ** (step + 1) * values[:, t + 1] + else: + nstep_return_t += ( + self.args.gamma ** (step) * rewards[:, t] * mask[:, t] + ) + nstep_values[:, t_start, :] = nstep_return_t + return nstep_values + + def _update_targets(self): + self.target_critic.load_state_dict(self.critic.state_dict()) + + def _update_targets_hard(self): + self.target_critic.load_state_dict(self.critic.state_dict()) + + def _update_targets_soft(self, tau): + for target_param, param in zip( + self.target_critic.parameters(), self.critic.parameters() + ): + target_param.data.copy_(target_param.data * (1.0 - tau) + param.data * tau) + + def cuda(self): + self.old_mac.cuda() + self.mac.cuda() + self.critic.cuda() + self.target_critic.cuda() + + def save_models(self, path): + self.mac.save_models(path) + th.save(self.critic.state_dict(), "{}/critic.th".format(path)) + th.save(self.agent_optimiser.state_dict(), "{}/agent_opt.th".format(path)) + th.save(self.critic_optimiser.state_dict(), "{}/critic_opt.th".format(path)) + + def load_models(self, path): + self.mac.load_models(path) + self.critic.load_state_dict( + th.load( + "{}/critic.th".format(path), map_location=lambda storage, loc: storage + ) + ) + # Not quite right but I don't want to save target networks + self.target_critic.load_state_dict(self.critic.state_dict()) + self.agent_optimiser.load_state_dict( + th.load( + "{}/agent_opt.th".format(path), + map_location=lambda storage, loc: storage, + ) + ) + self.critic_optimiser.load_state_dict( + th.load( + "{}/critic_opt.th".format(path), + map_location=lambda storage, loc: storage, + ) + ) \ No newline at end of file diff --git a/src/run.py b/src/run.py index 41e0a38d..610b7722 100644 --- a/src/run.py +++ b/src/run.py @@ -106,10 +106,21 @@ def run_sequential(args, logger): args.state_shape = env_info["state_shape"] # Default/Base scheme + print(f"ARGS.agent_output_type equals {args.agent_output_type}") + if (args.agent_output_type == 'continuous_u_std'): # Continuous actions; different shape. + actions_shape = {"vshape": env_info["n_actions"], "group": "agents", "dtype": th.float} + # Continuous spaces require mean and standard deviation + args.n_actions = env_info["n_actions"] * 2 + print(f"ARGS.N_ACTIONS equals {args.n_actions}") + # Inform the training module about the space shape + args.action_min = env_info["action_min"] + args.action_max = env_info["action_max"] + else: + actions_shape = {"vshape": (1,), "group": "agents", "dtype": th.long} scheme = { "state": {"vshape": env_info["state_shape"]}, "obs": {"vshape": env_info["obs_shape"], "group": "agents"}, - "actions": {"vshape": (1,), "group": "agents", "dtype": th.long}, + "actions": actions_shape, "avail_actions": { "vshape": (env_info["n_actions"],), "group": "agents", diff --git a/src/runners/parallel_runner.py b/src/runners/parallel_runner.py index 5962c60f..dc3c55eb 100644 --- a/src/runners/parallel_runner.py +++ b/src/runners/parallel_runner.py @@ -2,6 +2,7 @@ from multiprocessing import Pipe, Process import numpy as np +import torch from components.episode_buffer import EpisodeBatch from envs import REGISTRY as env_REGISTRY @@ -23,10 +24,14 @@ def __init__(self, args, logger): # registering both smac and smacv2 causes a pysc2 error # --> dynamically register the needed env + self.continuous_actions = False # By default if self.args.env == "sc2": register_smac() elif self.args.env == "sc2v2": register_smacv2() + elif self.args.env == "gymma" and 'pz-mpe' in self.args.env_args['key']: + print("!!! USING MPE ENVIRONMENT") + self.continuous_actions = self.args.env_args['continuous_actions'] env_fn = env_REGISTRY[self.args.env] env_args = [self.args.env_args.copy() for _ in range(self.batch_size)] @@ -137,7 +142,14 @@ def run(self, test_mode=False): cpu_actions = actions.to("cpu").numpy() # Update the actions taken - actions_chosen = {"actions": actions.unsqueeze(1)} + ''' + START OF MODIFIED SECTION + ''' + #print(f"!!! PRINTING ACTIONS CHOSEN: {actions}") # tensor([[4]]) in discrete + if (actions.type() == torch.LongTensor): # Add a dimension to continuous actions + actions_chosen = {"actions": actions.unsqueeze(1)} + else: + actions_chosen = {"actions": actions} self.batch.update( actions_chosen, bs=envs_not_terminated, ts=self.t, mark_filled=False ) @@ -154,6 +166,10 @@ def run(self, test_mode=False): if idx == 0 and test_mode and self.args.render: parent_conn.send(("render", None)) + ''' + END OF MODIFIED SECTION + ''' + # Update envs_not_terminated envs_not_terminated = [ b_idx for b_idx, termed in enumerate(terminated) if not termed @@ -352,4 +368,4 @@ def __getstate__(self): def __setstate__(self, ob): import pickle - self.x = pickle.loads(ob) + self.x = pickle.loads(ob) \ No newline at end of file