Skip to content

Commit a4cc4df

Browse files
committed
a_buffer critic mismatch at clipped extremes
1 parent d027b39 commit a4cc4df

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

amago/agent.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ def get_values(self, batch: Batch) -> dict[str, torch.Tensor]:
795795
K_a = self.num_actions_for_value_in_actor_loss if not self.discrete else 1
796796
a_buffer = F.pad(a, (0, 0, 0, 1), "replicate")
797797
a_buffer = repeat(a_buffer, f"b l a -> b l {G} a")
798+
a_buffer = self.actor.policy_dist.action_from_buffer(a_buffer)
798799
state_mask = (~((batch.rl2s == self.pad_val).all(-1, keepdim=True))).bool()[
799800
:, 1:, ...
800801
]
@@ -927,6 +928,7 @@ def forward(self, batch: Batch, log_step: bool) -> torch.Tensor:
927928
# we give it a fake one to make shape math work.
928929
a_buffer = F.pad(a, (0, 0, 0, 1), "replicate")
929930
a_buffer = repeat(a_buffer, f"b l a -> b l {G} a")
931+
a_buffer_critic = self.actor.policy_dist.action_from_buffer(a_buffer)
930932
C = len(self.critics)
931933
# arrays used by critic update end up in a (B, L, C, G, dim) format
932934
assert batch.rews.shape == (B, L - 1, 1)
@@ -964,7 +966,7 @@ def forward(self, batch: Batch, log_step: bool) -> torch.Tensor:
964966
############################
965967
s_a_agent_g = (s_rep.detach(), a_agent)
966968
q_s_a_agent_g = self.maximized_critics(*s_a_agent_g).mean(0)
967-
s_a_g = (s_rep[:, :-1, ...], a_buffer[:, :-1, ...].unsqueeze(0))
969+
s_a_g = (s_rep[:, :-1, ...], a_buffer_critic[:, :-1, ...].unsqueeze(0))
968970
q_s_a_g = self.critics(*s_a_g, log_dict=active_log_dict).mean(0)
969971
assert q_s_a_agent_g.shape == (B, L, C, G, 1)
970972
assert q_s_a_g.shape == (B, L-1, C, G, 1)
@@ -1078,7 +1080,6 @@ def masked_avg(x_, dim=0):
10781080
stats[f"Q(s, a) (global mean, rescaled) gamma={gamma:.3f}"] = masked_avg(
10791081
q_s_a_g, i
10801082
)
1081-
print("here")
10821083
stats["Q Sequence"] = q_s_a_g
10831084
stats[f"Q(s,a) (global mean, raw scale) gamma={gamma:.3f}"] = masked_avg(
10841085
raw_q_s_a_g, i
@@ -1299,6 +1300,7 @@ def get_values(self, batch: Batch) -> dict[str, torch.Tensor]:
12991300
K_a = self.num_actions_for_value_in_actor_loss
13001301
a_buffer = F.pad(a, (0, 0, 0, 1), "replicate")
13011302
a_buffer = repeat(a_buffer, f"b l a -> b l {G} a")
1303+
a_buffer = self.actor.policy_dist.action_from_buffer(a_buffer)
13021304
state_mask = (~((batch.rl2s == self.pad_val).all(-1, keepdim=True))).bool()[
13031305
:, 1:, ...
13041306
]
@@ -1363,6 +1365,7 @@ def forward(self, batch: Batch, log_step: bool):
13631365
K_c = self.num_actions_for_value_in_critic_loss
13641366
a_buffer = F.pad(a, (0, 0, 0, 1), "replicate")
13651367
a_buffer = repeat(a_buffer, f"b l a -> b l {G} a")
1368+
a_buffer = self.actor.policy_dist.action_from_buffer(a_buffer)
13661369
C = len(self.critics)
13671370
assert batch.rews.shape == (B, L - 1, 1)
13681371
assert batch.dones.shape == (B, L - 1, 1)

amago/nets/policy_dists.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@ def input_dimension(self) -> int:
211211
"""
212212
raise NotImplementedError
213213

214+
def action_from_buffer(self, action: torch.Tensor) -> torch.Tensor:
215+
"""Preprocess raw actions loaded from the replay buffer for use in the critic.
216+
217+
Subclasses override this to align buffer actions with the form the policy
218+
actually produces (e.g., softening hard one-hot discrete actions).
219+
Default is identity.
220+
"""
221+
return action
222+
214223
@abstractmethod
215224
def forward(
216225
self, vec: torch.Tensor, log_dict: Optional[dict] = None
@@ -269,6 +278,13 @@ def is_discrete(self) -> bool:
269278
def input_dimension(self) -> int:
270279
return self.d_action
271280

281+
def clip_and_normalize(self, probs: torch.Tensor) -> torch.Tensor:
282+
clipped = probs.clamp(self.clip_prob_low, self.clip_prob_high)
283+
return clipped / clipped.sum(-1, keepdim=True)
284+
285+
def action_from_buffer(self, action: torch.Tensor) -> torch.Tensor:
286+
return self.clip_and_normalize(action)
287+
272288
def forward(
273289
self, vec: torch.Tensor, log_dict: Optional[dict] = None
274290
) -> _Categorical:
@@ -278,7 +294,7 @@ def forward(
278294
safe_probs = clip_probs / clip_probs.sum(-1, keepdims=True).detach()
279295
safe_dist = _Categorical(probs=safe_probs)
280296
if log_dict is not None:
281-
add_activation_log("Discrete-probs", probs, log_dict)
297+
add_activation_log("Discrete-probs", dist.probs, log_dict)
282298
return safe_dist
283299

284300

0 commit comments

Comments
 (0)