Archive MaleCNS research sources, provenance, bibliography and immutable data inventory
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Game-agnostic abstract action-logit API for Phase 4G learned adapters."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AbstractActionOutput:
|
||||
action_logits: np.ndarray
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
value = np.asarray(self.action_logits, dtype=np.float32)
|
||||
if value.shape != (4,) or not np.isfinite(value).all():
|
||||
raise ValueError("action_logits must be finite float32[4]")
|
||||
object.__setattr__(self, "action_logits", value)
|
||||
|
||||
def deterministic_argmax(self) -> int:
|
||||
return int(np.argmax(self.action_logits))
|
||||
|
||||
def sample(self, seed: int, temperature: float = 1.0, epsilon: float = 0.0) -> int:
|
||||
if temperature <= 0 or not 0 <= epsilon <= 1:
|
||||
raise ValueError("temperature must be positive and epsilon in [0,1]")
|
||||
rng = np.random.default_rng(seed)
|
||||
if rng.random() < epsilon:
|
||||
return int(rng.integers(0, 4))
|
||||
z = self.action_logits.astype(np.float64) / temperature
|
||||
z -= z.max(); p = np.exp(z); p /= p.sum()
|
||||
return int(rng.choice(4, p=p))
|
||||
|
||||
|
||||
ACTION_NAMES = ("ACTION_0", "ACTION_1", "ACTION_2", "ACTION_3")
|
||||
|
||||
Reference in New Issue
Block a user