From 9a9995c58644d6f742a21ad397878d45caeab1a3 Mon Sep 17 00:00:00 2001 From: Nicholas Gorichs Date: Fri, 2 Feb 2024 09:58:55 -0600 Subject: [PATCH] Dropped Tensorflow wrapper --- config.yaml | 2 +- connectx/connectx_gym/__init__.py | 2 +- connectx/connectx_gym/connectx_env.py | 1 - connectx/connectx_gym/wrappers.py | 34 +--- outputs/02-02/09-55-53/.hydra/config.yaml | 41 ++++ outputs/02-02/09-55-53/.hydra/hydra.yaml | 154 +++++++++++++++ outputs/02-02/09-55-53/.hydra/overrides.yaml | 1 + .../files/config.yaml | 183 ++++++++++++++++++ .../files/requirements.txt | 120 ++++++++++++ .../files/wandb-metadata.json | 45 +++++ .../run-eb1n06sq.wandb | Bin 0 -> 32799 bytes 11 files changed, 550 insertions(+), 33 deletions(-) create mode 100644 outputs/02-02/09-55-53/.hydra/config.yaml create mode 100644 outputs/02-02/09-55-53/.hydra/hydra.yaml create mode 100644 outputs/02-02/09-55-53/.hydra/overrides.yaml create mode 100644 wandb/run-20240202_095555-eb1n06sq/files/config.yaml create mode 100644 wandb/run-20240202_095555-eb1n06sq/files/requirements.txt create mode 100644 wandb/run-20240202_095555-eb1n06sq/files/wandb-metadata.json create mode 100644 wandb/run-20240202_095555-eb1n06sq/run-eb1n06sq.wandb diff --git a/config.yaml b/config.yaml index 726cb37..40ff29e 100644 --- a/config.yaml +++ b/config.yaml @@ -23,7 +23,7 @@ reward_space_kwargs: {} debug: true act_space: BasicActionSpace obs_space: BasicObsSpace -reward_space: LongGameReward +reward_space: GameResultReward optimizer_class: Adam optimizer_kwargs: lr: 0.0001 diff --git a/connectx/connectx_gym/__init__.py b/connectx/connectx_gym/__init__.py index 9ce71be..dfa2cdb 100644 --- a/connectx/connectx_gym/__init__.py +++ b/connectx/connectx_gym/__init__.py @@ -3,7 +3,7 @@ from . import act_spaces, obs_spaces, reward_spaces from .connectx_env import ConnectFour -from .wrappers import DictEnv, LoggingEnv, PytorchEnv, RewardSpaceWrapper, TensorflowEnv, VecEnv +from .wrappers import DictEnv, LoggingEnv, PytorchEnv, RewardSpaceWrapper, VecEnv ACT_SPACES_DICT = { key: val for key, val in act_spaces.__dict__.items() diff --git a/connectx/connectx_gym/connectx_env.py b/connectx/connectx_gym/connectx_env.py index 526f2ef..7b56d07 100644 --- a/connectx/connectx_gym/connectx_env.py +++ b/connectx/connectx_gym/connectx_env.py @@ -7,7 +7,6 @@ from .act_spaces import BaseActSpace from .obs_spaces import BaseObsSpace -from .reward_spaces import GameResultReward from ..utility_constants import BOARD_SIZE diff --git a/connectx/connectx_gym/wrappers.py b/connectx/connectx_gym/wrappers.py index e167adc..48e7152 100644 --- a/connectx/connectx_gym/wrappers.py +++ b/connectx/connectx_gym/wrappers.py @@ -1,16 +1,10 @@ +import copy import gym -import torch import numpy as np -import copy -# import tensorflow as tf - -from kaggle_environments.core import Environment, make -from typing import Dict, List, NoReturn, Optional, Union, Tuple +import torch +from typing import Dict, List, Union, Tuple -# from . import ConnectFour -from .act_spaces import BaseActSpace -from .obs_spaces import BaseObsSpace -from .reward_spaces import BaseRewardSpace, GameResultReward +from .reward_spaces import BaseRewardSpace class LoggingEnv(gym.Wrapper): @@ -166,26 +160,6 @@ def _to_tensor(self, x: Union[Dict, np.ndarray]) -> Dict[str, Union[Dict, torch. elif isinstance(x, np.ndarray): return torch.from_numpy(x).to(device=self.device) -class TensorflowEnv(gym.Wrapper): - def __init__(self, env: Union[gym.Env, VecEnv], device: torch.device = torch.device("cpu")): - super(TensorflowEnv, self).__init__(env) - self.device = device - - def reset(self, **kwargs) -> Tuple[Dict, List, bool, List]: - return tuple([self._to_tensor(out) for out in super(TensorflowEnv, self).reset(**kwargs)]) - - def step(self, actions: List[torch.Tensor]): - action = [ - act.cpu().numpy() for act in actions - ] - return tuple([self._to_tensor(out) for out in super(TensorflowEnv, self).step(action)]) - - def _to_tensor(self, x: Union[Dict, np.ndarray]) -> Dict[str, Union[Dict, torch.Tensor]]: - if isinstance(x, dict): - return {key: self._to_tensor(val) for key, val in x.items()} - else: - return tf.convert_to_tensor(x, dtype=tf.float32) - class DictEnv(gym.Wrapper): @staticmethod diff --git a/outputs/02-02/09-55-53/.hydra/config.yaml b/outputs/02-02/09-55-53/.hydra/config.yaml new file mode 100644 index 0000000..5403098 --- /dev/null +++ b/outputs/02-02/09-55-53/.hydra/config.yaml @@ -0,0 +1,41 @@ +name: new_beginnings +project: ConnectX +entity: filipinogambino +group: debug +use_mixed_precision: false +total_steps: 10000.0 +batch_size: 8 +checkpoint_freq: 60.0 +num_actors: 1 +n_actor_envs: 2 +unroll_length: 42 +player_id: 0 +seed: 42 +model_arch: mha_model +embedding_dim: 32 +hidden_dim: 128 +n_heads: 4 +n_blocks: 1 +device: cpu +rescale_value_input: false +obs_space_kwargs: {} +reward_space_kwargs: {} +debug: true +act_space: BasicActionSpace +obs_space: BasicObsSpace +reward_space: GameResultReward +optimizer_class: Adam +optimizer_kwargs: + lr: 0.0001 + eps: 0.0003 +min_lr_mod: 0.01 +entropy_cost: 0.001 +baseline_cost: 1.0 +teacher_kl_cost: 0.0 +lmb: 0.8 +reduction: sum +actor_device: cpu +learner_device: cpu +disable_wandb: false +model_log_freq: 100 +sharing_strategy: file_descriptor diff --git a/outputs/02-02/09-55-53/.hydra/hydra.yaml b/outputs/02-02/09-55-53/.hydra/hydra.yaml new file mode 100644 index 0000000..ed40638 --- /dev/null +++ b/outputs/02-02/09-55-53/.hydra/hydra.yaml @@ -0,0 +1,154 @@ +hydra: + run: + dir: ./outputs/${now:%m-%d}/${now:%H-%M-%S} + sweep: + dir: multirun/${now:%Y-%m-%d}/${now:%H-%M-%S} + subdir: ${hydra.job.num} + launcher: + _target_: hydra._internal.core_plugins.basic_launcher.BasicLauncher + sweeper: + _target_: hydra._internal.core_plugins.basic_sweeper.BasicSweeper + max_batch_size: null + params: null + help: + app_name: ${hydra.job.name} + header: '${hydra.help.app_name} is powered by Hydra. + + ' + footer: 'Powered by Hydra (https://hydra.cc) + + Use --hydra-help to view Hydra specific help + + ' + template: '${hydra.help.header} + + == Configuration groups == + + Compose your configuration from those groups (group=option) + + + $APP_CONFIG_GROUPS + + + == Config == + + Override anything in the config (foo.bar=value) + + + $CONFIG + + + ${hydra.help.footer} + + ' + hydra_help: + template: 'Hydra (${hydra.runtime.version}) + + See https://hydra.cc for more info. + + + == Flags == + + $FLAGS_HELP + + + == Configuration groups == + + Compose your configuration from those groups (For example, append hydra/job_logging=disabled + to command line) + + + $HYDRA_CONFIG_GROUPS + + + Use ''--cfg hydra'' to Show the Hydra config. + + ' + hydra_help: ??? + hydra_logging: + version: 1 + formatters: + simple: + format: '[%(asctime)s][HYDRA] %(message)s' + handlers: + console: + class: logging.StreamHandler + formatter: simple + stream: ext://sys.stdout + root: + level: INFO + handlers: + - console + loggers: + logging_example: + level: DEBUG + disable_existing_loggers: false + job_logging: + version: 1 + formatters: + simple: + format: '[%(asctime)s][%(name)s][%(levelname)s] - %(message)s' + handlers: + console: + class: logging.StreamHandler + formatter: simple + stream: ext://sys.stdout + file: + class: logging.FileHandler + formatter: simple + filename: ${hydra.runtime.output_dir}/${hydra.job.name}.log + root: + level: INFO + handlers: + - console + - file + disable_existing_loggers: false + env: {} + mode: RUN + searchpath: [] + callbacks: {} + output_subdir: .hydra + overrides: + hydra: + - hydra.mode=RUN + task: [] + job: + name: run_monobeast + chdir: null + override_dirname: '' + id: ??? + num: ??? + config_name: new_beginnings + env_set: {} + env_copy: [] + config: + override_dirname: + kv_sep: '=' + item_sep: ',' + exclude_keys: [] + runtime: + version: 1.3.2 + version_base: '1.3' + cwd: C:\Users\nick.gorichs\PycharmProjects\Connect_Four_2 + config_sources: + - path: hydra.conf + schema: pkg + provider: hydra + - path: C:\Users\nick.gorichs\PycharmProjects\Connect_Four_2\conf + schema: file + provider: main + - path: '' + schema: structured + provider: schema + output_dir: C:\Users\nick.gorichs\PycharmProjects\Connect_Four_2\outputs\02-02\09-55-53 + choices: + hydra/env: default + hydra/callbacks: null + hydra/job_logging: default + hydra/hydra_logging: default + hydra/hydra_help: default + hydra/help: default + hydra/sweeper: basic + hydra/launcher: basic + hydra/output: default + verbose: false diff --git a/outputs/02-02/09-55-53/.hydra/overrides.yaml b/outputs/02-02/09-55-53/.hydra/overrides.yaml new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/outputs/02-02/09-55-53/.hydra/overrides.yaml @@ -0,0 +1 @@ +[] diff --git a/wandb/run-20240202_095555-eb1n06sq/files/config.yaml b/wandb/run-20240202_095555-eb1n06sq/files/config.yaml new file mode 100644 index 0000000..646d9e7 --- /dev/null +++ b/wandb/run-20240202_095555-eb1n06sq/files/config.yaml @@ -0,0 +1,183 @@ +wandb_version: 1 + +name: + desc: null + value: new_beginnings +project: + desc: null + value: ConnectX +entity: + desc: null + value: filipinogambino +group: + desc: null + value: debug +use_mixed_precision: + desc: null + value: false +total_steps: + desc: null + value: 10000.0 +batch_size: + desc: null + value: 8 +checkpoint_freq: + desc: null + value: 60.0 +num_actors: + desc: null + value: 1 +n_actor_envs: + desc: null + value: 2 +unroll_length: + desc: null + value: 42 +player_id: + desc: null + value: 0 +seed: + desc: null + value: 42 +model_arch: + desc: null + value: mha_model +embedding_dim: + desc: null + value: 32 +hidden_dim: + desc: null + value: 128 +n_heads: + desc: null + value: 4 +n_blocks: + desc: null + value: 1 +device: + desc: null + value: cpu +rescale_value_input: + desc: null + value: false +obs_space_kwargs: + desc: null + value: {} +reward_space_kwargs: + desc: null + value: {} +debug: + desc: null + value: true +act_space: + desc: null + value: connectx.connectx_gym.act_spaces.BasicActionSpace +obs_space: + desc: null + value: connectx.connectx_gym.obs_spaces.BasicObsSpace +reward_space: + desc: null + value: connectx.connectx_gym.reward_spaces.GameResultReward +optimizer_class: + desc: null + value: torch.optim.adam.Adam +optimizer_kwargs: + desc: null + value: + lr: 0.0001 + eps: 0.0003 +min_lr_mod: + desc: null + value: 0.01 +entropy_cost: + desc: null + value: 0.001 +baseline_cost: + desc: null + value: 1.0 +teacher_kl_cost: + desc: null + value: 0.0 +lmb: + desc: null + value: 0.8 +reduction: + desc: null + value: sum +actor_device: + desc: null + value: cpu +learner_device: + desc: null + value: cpu +disable_wandb: + desc: null + value: false +model_log_freq: + desc: null + value: 100 +sharing_strategy: + desc: null + value: file_descriptor +num_buffers: + desc: null + value: 4 +discounting: + desc: null + value: 0.999 +clip_grads: + desc: null + value: 10.0 +num_learner_threads: + desc: null + value: 1 +use_teacher: + desc: null + value: false +teacher_baseline_cost: + desc: null + value: 0.0 +use_index_select: + desc: null + value: true +load_dir: + desc: null + value: null +checkpoint_file: + desc: null + value: null +weights_only: + desc: null + value: false +n_value_warmup_batches: + desc: null + value: 0 +_wandb: + desc: null + value: + python_version: 3.9.6 + cli_version: 0.16.2 + framework: huggingface + huggingface_version: 4.35.0 + is_jupyter_run: false + is_kaggle_kernel: true + start_time: 1706889355.617884 + t: + 1: + - 1 + - 11 + - 49 + - 50 + - 55 + 3: + - 13 + - 16 + - 23 + 4: 3.9.6 + 5: 0.16.2 + 6: 4.35.0 + 8: + - 2 + - 3 + - 5 + 13: windows-amd64 diff --git a/wandb/run-20240202_095555-eb1n06sq/files/requirements.txt b/wandb/run-20240202_095555-eb1n06sq/files/requirements.txt new file mode 100644 index 0000000..cd284c9 --- /dev/null +++ b/wandb/run-20240202_095555-eb1n06sq/files/requirements.txt @@ -0,0 +1,120 @@ +absl-py==2.0.0 +antlr4-python3-runtime==4.9.3 +appdirs==1.4.4 +asttokens==2.4.1 +astunparse==1.6.3 +attrs==23.1.0 +beautifulsoup4==4.12.2 +blinker==1.7.0 +cachetools==5.3.2 +certifi==2023.7.22 +charset-normalizer==3.3.2 +click==8.1.7 +cloudpickle==3.0.0 +colorama==0.4.6 +contourpy==1.2.0 +cycler==0.12.1 +decorator==5.1.1 +docker-pycreds==0.4.0 +exceptiongroup==1.1.3 +executing==2.0.1 +farama-notifications==0.0.4 +filelock==3.13.1 +flask==3.0.0 +flatbuffers==23.5.26 +fonttools==4.44.0 +fsspec==2023.10.0 +gast==0.5.4 +gitdb==4.0.11 +gitpython==3.1.40 +google-auth-oauthlib==1.0.0 +google-auth==2.23.4 +google-pasta==0.2.0 +grpcio==1.59.2 +gym-notices==0.0.8 +gym==0.26.2 +gymnasium==0.29.0 +h5py==3.10.0 +huggingface-hub==0.17.3 +hydra-core==1.3.2 +idna==3.4 +importlib-metadata==6.8.0 +importlib-resources==6.1.0 +ipython==8.17.2 +itsdangerous==2.1.2 +jedi==0.19.1 +jinja2==3.1.2 +jsonschema-specifications==2023.7.1 +jsonschema==4.19.2 +keras==2.14.0 +kiwisolver==1.4.5 +libclang==16.0.6 +markdown==3.5.1 +markupsafe==2.1.3 +matplotlib-inline==0.1.6 +matplotlib==3.8.1 +ml-dtypes==0.2.0 +mpmath==1.3.0 +networkx==3.2.1 +numpy==1.26.3 +oauthlib==3.2.2 +omegaconf==2.3.0 +opt-einsum==3.3.0 +packaging==23.2 +pandas==2.1.2 +parso==0.8.3 +pettingzoo==1.24.0 +pillow==10.1.0 +pip==23.3.2 +prompt-toolkit==3.0.41 +protobuf==4.25.0 +psutil==5.9.7 +pure-eval==0.2.2 +pyasn1-modules==0.3.0 +pyasn1==0.5.0 +pygame==2.5.2 +pygments==2.16.1 +pyparsing==3.1.1 +python-dateutil==2.8.2 +pytz==2023.3.post1 +pyyaml==6.0.1 +referencing==0.30.2 +regex==2023.10.3 +requests-oauthlib==1.3.1 +requests==2.31.0 +rpds-py==0.12.0 +rsa==4.9 +safetensors==0.4.0 +scipy==1.11.3 +sentry-sdk==1.39.1 +setproctitle==1.3.3 +setuptools==68.2.2 +shimmy==1.3.0 +six==1.16.0 +smmap==5.0.1 +soupsieve==2.5 +stable-baselines3==2.1.0 +stack-data==0.6.3 +sympy==1.12 +tensorboard-data-server==0.7.2 +tensorboard==2.14.1 +tensorflow-estimator==2.14.0 +tensorflow-intel==2.14.0 +tensorflow-io-gcs-filesystem==0.31.0 +tensorflow==2.14.0 +termcolor==2.3.0 +tokenizers==0.14.1 +torch==2.1.2 +torchvision==0.16.2 +tqdm==4.66.1 +traitlets==5.13.0 +transformers==4.35.0 +typing-extensions==4.8.0 +tzdata==2023.3 +urllib3==2.0.7 +wandb==0.16.2 +wcwidth==0.2.10 +werkzeug==3.0.1 +wheel==0.37.1 +wrapt==1.14.1 +zipp==3.17.0 \ No newline at end of file diff --git a/wandb/run-20240202_095555-eb1n06sq/files/wandb-metadata.json b/wandb/run-20240202_095555-eb1n06sq/files/wandb-metadata.json new file mode 100644 index 0000000..dd948e8 --- /dev/null +++ b/wandb/run-20240202_095555-eb1n06sq/files/wandb-metadata.json @@ -0,0 +1,45 @@ +{ + "os": "Windows-10-10.0.22631-SP0", + "python": "3.9.6", + "heartbeatAt": "2024-02-02T15:55:56.165904", + "startedAt": "2024-02-02T15:55:55.602843", + "docker": null, + "cuda": null, + "args": [], + "state": "running", + "program": "C:\\Users\\nick.gorichs\\PycharmProjects\\Connect_Four_2\\run_monobeast.py", + "codePathLocal": "run_monobeast.py", + "codePath": "run_monobeast.py", + "git": { + "remote": "https://github.com/FilipinoGambino/Connect_Four_2.git", + "commit": "add8931ea6b76c64496fa2399e74eb2483625422" + }, + "email": null, + "root": "C:/Users/nick.gorichs/PycharmProjects/Connect_Four_2", + "host": "WI-7C7X4S2", + "username": "Nick.Gorichs", + "executable": "C:\\Users\\nick.gorichs\\AppData\\Local\\Programs\\Python\\Python39\\python.exe", + "cpu_count": 4, + "cpu_count_logical": 8, + "cpu_freq": { + "current": 1910.0, + "min": 0.0, + "max": 2112.0 + }, + "cpu_freq_per_core": [ + { + "current": 1910.0, + "min": 0.0, + "max": 2112.0 + } + ], + "disk": { + "/": { + "total": 236.73046493530273, + "used": 221.68227767944336 + } + }, + "memory": { + "total": 7.861743927001953 + } +} diff --git a/wandb/run-20240202_095555-eb1n06sq/run-eb1n06sq.wandb b/wandb/run-20240202_095555-eb1n06sq/run-eb1n06sq.wandb new file mode 100644 index 0000000000000000000000000000000000000000..49f9619a8dcfeac086e2bbc76cc18f95a2b05599 GIT binary patch literal 32799 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 F{{SFx7Qg@i literal 0 HcmV?d00001