-
Notifications
You must be signed in to change notification settings - Fork 335
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
[Feature] Added linear interpolation to FrameSkipTransform #1692
base: main
Are you sure you want to change the base?
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/rl/1692
Note: Links to docs will display an error until the docs builds have been completed. ⏳ 8 Pending, 3 Unrelated FailuresAs of commit ce0a846 with merge base 11562c7 ( FLAKY - The following jobs failed but were likely due to flakiness present on trunk:
BROKEN TRUNK - The following job failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for this!
We need to add a couple of tests for this feature.
What should happen at reset time, if there is more than one env being run?
def __init__(self, frame_skip: int = 1): | ||
super().__init__() | ||
def __init__(self, frame_skip: int = 1, action_interp: bool = False): | ||
super().__init() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, that is a mistake from my side, sorry!
(regarding the init)
@@ -3893,28 +3893,59 @@ class FrameSkipTransform(Transform): | |||
Args: | |||
frame_skip (int, optional): a positive integer representing the number | |||
of frames during which the same action must be applied. | |||
action_interp (bool, optional): whether to perform action interpolation over frame_skip steps. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
action_interp (bool, optional): whether to perform action interpolation over frame_skip steps. | |
action_interp (bool, optional): whether to perform action interpolation over frame_skip steps. | |
Defaults to ``False``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add an example that in the docstring
action_interp (bool, optional): whether to perform action interpolation over frame_skip steps. | |
Suggested change | |
action_interp (bool, optional): whether to perform action interpolation over frame_skip steps. | |
Defaults to ``False``. | |
Examples: | |
>>> from torchrl.envs import GymEnv | |
>>> env = TransformedEnv(GymEnv("CartPole-v1"), FrameSkipTransform(3, action_interp=False)) | |
>>> print(env.rollout) | |
# add print here | |
>>> env = TransformedEnv(GymEnv("CartPole-v1"), FrameSkipTransform(3, action_interp=True)) | |
>>> print(env.rollout) | |
# add print here | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suree, will add it in the next commit
|
||
def _step( | ||
self, tensordict: TensorDictBase, next_tensordict: TensorDictBase | ||
) -> TensorDictBase: | ||
parent = self.parent | ||
if parent is None: | ||
raise RuntimeError("parent not found for FrameSkipTransform") | ||
|
||
if self.action_interp: | ||
action_key = "_action" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be a parameter in the class constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it
) | ||
self.action_interp_buffer = next_action | ||
else: | ||
interpolated_actions = [current_action] * (self.frame_skip - 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to store this contiguously (with a torch.stack around it)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what you mean by this, could you like elaborate?
def _linear_interpolation( | ||
self, start_action: Tensor, end_action: Tensor, num_steps: int | ||
) -> List[Tensor]: | ||
if num_steps <= 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can num_steps be smaller than 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They cannot be, but still, I felt the need to add them, just in case the people using them don't run into any issues (like trying to enter a negative number just for fun and all)
for step in range(1, num_steps): | ||
alpha = step / num_steps | ||
interpolated_action = start_action + alpha * (end_action - start_action) | ||
interpolation_steps.append(interpolated_action) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I see what this block is doing, can you give an example?
It'd be cool to see (eg in the tests) what you would expect to get from it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so my reasoning here was for let's say num_steps = 5
, we have:
At step = 1
, alpha = 1/5
and interpolated_action
is calculated as follows:
interpolated_action=start_action+(1/5)*(end_action - start_action)
Similarly for each step (like for the 4th step, alpha=4/5
) and interpolated_action
is calculated as follows:
interpolated_action=start_action+(4/5)*(end_action - start_action)
And finally, at step = 5
, alpha = 5/5
(which is 1), and interpolated_action
becomes :
interpolated_action=end_action
So like theinterpolation_steps
list contains the sequence of actions that go from from start_action
to end_action
over the specified number of steps, which in this example is 5.
I felt that this made sense for moving from start_action
to end_action
, for smooth action transitions over multiple steps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if this makes sense, but I felt that this is how i have to do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok got it, do you mind if I try to do a vectorized version of this once you have written tests? I think we can make it faster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suree! please do it!
I'll send another round of commits by the next 3ish hours
Also please could you answer what
would it make sense to store this contiguously (with a torch.stack around it)?
This means?
@vmoens, added the changes that you told me to. Ready for another round of comments
I wasn't sure what to do here, so I just wrapped Added
Here, Should I create a |
I'd make a step back and define precisely what we expect this to do.
|
@vmoens , I read your comments, and you mention that my first priority should be adding tests So I looked at the |
Ahah I can imagine! |
Thanks a lot, will push some tests later, most probably in 24ish hours |
Description
action_interp
parameter to enable or disable the action interpolation feature.action_interp_buffer
attribute to store the previous action for interpolation.Motivation and Context
Solves Issue #1659
Types of changes
Checklist
Reviewers
cc. @vmoens
P.S. I don't know if I have to add unit-tests for this, OR if this is a breaking change, so I haven't added them here.