Skip to content

Commit 25a8947

Browse files
author
Haichao Zhang
committed
Support multi-step td
1 parent 1518939 commit 25a8947

4 files changed

Lines changed: 40 additions & 8 deletions

File tree

alf/algorithms/sac_algorithm.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
from alf.algorithms.off_policy_algorithm import OffPolicyAlgorithm
2929
from alf.algorithms.one_step_loss import OneStepTDLoss
3030
from alf.algorithms.rl_algorithm import RLAlgorithm
31+
from alf.experience_replayers.replay_buffer import ReplayBuffer
32+
from alf.nest.utils import convert_device
3133
from alf.data_structures import TimeStep, Experience, LossInfo, namedtuple
3234
from alf.data_structures import AlgStep, StepType
3335
from alf.nest import nest
@@ -1073,14 +1075,21 @@ def _calc_critic_loss(self, info: SacInfo):
10731075

10741076
def preprocess_experience(self, time_step: TimeStep, rollout_info: SacInfo,
10751077
batch_info):
1076-
1077-
_, mini_batch_length = time_step.step_type.shape
1078-
discounted_return = batch_info.discounted_return
1079-
discounted_return = discounted_return.unsqueeze(1).expand(
1080-
-1, mini_batch_length)
1081-
rollout_info = alf.nest.set_field(
1082-
rollout_info, 'discounted_return',
1083-
discounted_return if self._use_mc_return else ())
1078+
if self._use_mc_return:
1079+
assert batch_info != ()
1080+
replay_buffer: ReplayBuffer = batch_info.replay_buffer
1081+
mini_batch_length = time_step.step_type.shape[1]
1082+
1083+
with alf.device(replay_buffer.device):
1084+
# [B, 1]
1085+
positions = convert_device(batch_info.positions).unsqueeze(-1)
1086+
# [B, 1]
1087+
env_ids = convert_device(batch_info.env_ids).unsqueeze(-1)
1088+
# [B, T]
1089+
positions = positions + torch.arange(mini_batch_length)
1090+
discounted_return = replay_buffer.get_discounted_return(env_ids=env_ids, positions=positions)
1091+
discounted_return = convert_device(discounted_return)
1092+
rollout_info = rollout_info._replace(discounted_return=discounted_return)
10841093
return time_step, rollout_info
10851094

10861095
def _trainable_attributes_to_ignore(self):
27.4 KB
Loading

alf/examples/sac_cart_pole_mc_return_conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020

2121
default_return = -1000
2222
use_mc_return = True
23+
mini_batch_length = 2 # set to a value > 2 for multi-step learning
2324

2425
alf.config("ReplayBuffer",
2526
keep_episodic_info=True,
2627
record_episodic_return=True,
2728
default_return=default_return)
2829
alf.config("TDLoss", default_return=default_return)
2930
alf.config("SacAlgorithm", use_mc_return=use_mc_return)
31+
32+
alf.config('TrainerConfig',
33+
mini_batch_length=mini_batch_length)

alf/experience_replayers/replay_buffer.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,25 @@ def get_field(self, field_name, env_ids, positions):
839839
result = alf.nest.map_structure(lambda x: x[indices], field)
840840
return convert_device(result)
841841

842+
def get_discounted_return(self, env_ids, positions):
843+
"""Get discounted return from the replay buffer by ``env_ids`` and ``positions``.
844+
845+
Args:
846+
env_ids (Tensor): 1-D int64 Tensor.
847+
positions (Tensor): 1-D int64 Tensor with same shape as ``env_ids``.
848+
These positions should be obtained from the BatchInfo returned
849+
by ``get_batch()``.
850+
Returns:
851+
Tensor: with the same shape as broadcasted shape of env_ids and positions
852+
"""
853+
current_pos = self._current_pos[env_ids]
854+
assert torch.all(positions < current_pos), "Invalid positions"
855+
assert torch.all(positions >= current_pos -
856+
self._max_length), "Invalid positions"
857+
indices = (env_ids, self.circular(positions))
858+
result = self._episodic_discounted_return[indices]
859+
return convert_device(result)
860+
842861
@property
843862
def total_size(self):
844863
"""Total size from all environments."""

0 commit comments

Comments
 (0)