Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type hints #293

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

Type hints #293

wants to merge 1 commit into from

Conversation

timoklein
Copy link
Collaborator

@timoklein timoklein commented Oct 14, 2022

Description

As discussed on Discord, I've done basic type hints for PPO and DQN. Everything checks out with mypy 0.982 (mypy cleanrl/ppo.py --show-error-codes --ignore-missing-imports). Of course we can have a discussion about whether that's the checker that will be used if we go further down the road of implementing this. I'll put comments in noteworthy places.

The tests fail because tuple[int] or list[int] only works from Python 3.9 on.

Types of changes

  • Bug fix
  • New feature
  • New algorithm
  • Documentation

Checklist:

  • I've read the CONTRIBUTION guide (required).
  • I have ensured pre-commit run --all-files passes (required).
  • I have explained note-worthy implementation details.
  • Update poetry dependencies
  • Type checker config.

@vercel
Copy link

vercel bot commented Oct 14, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
cleanrl ✅ Ready (Inspect) Visit Preview Oct 14, 2022 at 7:25AM (UTC)

@@ -159,15 +166,24 @@ def get_action_and_value(self, x, action=None):
# env setup
envs = gym.vector.SyncVectorEnv(
[make_env(args.env_id, args.seed + i, i, args.capture_video, run_name) for i in range(args.num_envs)]
)
) # type:ignore[abstract]
Copy link
Collaborator Author

@timoklein timoklein Oct 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SyncVectorEnv inherits from VectorEnv which inherits from Env. For older gym versions (I'm currently on 0.23.1), Env is an ABC with abstract method render that is not overriden by any of the vector envs. Since it's fixed in the newest gym release and not our issue, I'm ignoring here.

Comment on lines +171 to +179
# Handling gym shapes being Optionals (variant 1)
# Personally i'd prefer the asserts
assert isinstance(envs.single_observation_space.shape, tuple), "shape of observation space must be defined"
assert isinstance(envs.single_action_space.shape, tuple), "shape of action space must be defined"

# Handling gym shapes being Optionals (variant 2)
# Once could also cast inside each call but in my eyes that's not conducive to readability
obs_space_shape = cast(tuple[int, ...], envs.single_observation_space.shape)
action_space_shape = cast(tuple[int, ...], envs.single_action_space.shape)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gym spaces can in theory return None shapes. Mypy will complain about this when concatenating the shape tuples later.

  • Option 1 is to use a cast either once here or every time the spaces are accessed. I don't think that's very readable.
  • Option 2 is to assert that the space shapes are tuples. Doing it once here fixes all errors for the rest of the code. Since there's an assert in this place already anyway I think this is the better option.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option 1 is more preferrable

@@ -92,11 +96,11 @@ def __init__(self, env):
nn.Linear(84, env.single_action_space.n),
)

def forward(self, x):
def forward(self, x: torch.FloatTensor) -> torch.FloatTensor:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've used FloatTensor here but we should just use torch.Tensor if type hints are pursued further.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine

@timoklein timoklein marked this pull request as draft October 14, 2022 07:41
Copy link
Owner

@vwxyzjn vwxyzjn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! The PR looks good. I have left some comments

@@ -82,7 +83,10 @@ def thunk():

# ALGO LOGIC: initialize agent here:
class QNetwork(nn.Module):
def __init__(self, env):

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove this space?

@@ -92,11 +96,11 @@ def __init__(self, env):
nn.Linear(84, env.single_action_space.n),
)

def forward(self, x):
def forward(self, x: torch.FloatTensor) -> torch.FloatTensor:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine

Comment on lines +171 to +179
# Handling gym shapes being Optionals (variant 1)
# Personally i'd prefer the asserts
assert isinstance(envs.single_observation_space.shape, tuple), "shape of observation space must be defined"
assert isinstance(envs.single_action_space.shape, tuple), "shape of action space must be defined"

# Handling gym shapes being Optionals (variant 2)
# Once could also cast inside each call but in my eyes that's not conducive to readability
obs_space_shape = cast(tuple[int, ...], envs.single_observation_space.shape)
action_space_shape = cast(tuple[int, ...], envs.single_action_space.shape)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option 1 is more preferrable

def get_action_and_value(self, x, action=None):
def get_action_and_value(
self, x: torch.Tensor, action: Optional[torch.Tensor] = None
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding from __future__ import annotations at the top would guarantee the 3.7+ compatibility, and make dropping support later on quite easy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants