fix: split pad dada
This commit is contained in:
parent
9c20c28b2a
commit
4068ccef5d
2 changed files with 75 additions and 32 deletions
|
|
@ -24,25 +24,27 @@ _SEGMENT_SCALED_KEYS = frozenset(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _build_joint_indices(segments_per_arm):
|
def _build_joint_indices(segments_per_arm, indices_mlp):
|
||||||
indices = []
|
indices = []
|
||||||
start = 0
|
start = 0
|
||||||
for segs in segments_per_arm:
|
for i, segs in enumerate(segments_per_arm):
|
||||||
# 2 joints per segment
|
# 2 joints per segment
|
||||||
count = segs * 2
|
if i in indices_mlp:
|
||||||
idx = jnp.arange(start, start + count)
|
count = segs * 2
|
||||||
indices.append(idx)
|
idx = jnp.arange(start, start + count)
|
||||||
start += count
|
indices.append(idx)
|
||||||
|
start += count
|
||||||
return indices
|
return indices
|
||||||
|
|
||||||
|
|
||||||
def _build_segment_indices(segments_per_arm):
|
def _build_segment_indices(segments_per_arm, indices_mlp):
|
||||||
indices = []
|
indices = []
|
||||||
start = 0
|
start = 0
|
||||||
for segs in segments_per_arm:
|
for i, segs in enumerate(segments_per_arm):
|
||||||
idx = jnp.arange(start, start + segs)
|
if i in indices_mlp:
|
||||||
indices.append(idx)
|
idx = jnp.arange(start, start + segs)
|
||||||
start += segs
|
indices.append(idx)
|
||||||
|
start += segs
|
||||||
return indices
|
return indices
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -53,6 +55,7 @@ def create_obs_processor(
|
||||||
padding_masks: Optional[Dict] = None,
|
padding_masks: Optional[Dict] = None,
|
||||||
morph_mode: MorphMode = MorphMode.CENTRALIZED,
|
morph_mode: MorphMode = MorphMode.CENTRALIZED,
|
||||||
segments_per_arm=[4, 4, 4, 4, 4],
|
segments_per_arm=[4, 4, 4, 4, 4],
|
||||||
|
agent_indices=[0, 1, 2, 3, 4],
|
||||||
):
|
):
|
||||||
# made a set to allow O(1) search
|
# made a set to allow O(1) search
|
||||||
ordered_keys = frozenset(
|
ordered_keys = frozenset(
|
||||||
|
|
@ -65,8 +68,8 @@ def create_obs_processor(
|
||||||
"segment_contact",
|
"segment_contact",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
segment_indices = _build_segment_indices(segments_per_arm)
|
segment_indices = _build_segment_indices(segments_per_arm, agent_indices)
|
||||||
joint_indices = _build_joint_indices(segments_per_arm)
|
joint_indices = _build_joint_indices(segments_per_arm, agent_indices)
|
||||||
|
|
||||||
def _add_derived_features(obs: dict) -> dict:
|
def _add_derived_features(obs: dict) -> dict:
|
||||||
new_obs = dict(obs)
|
new_obs = dict(obs)
|
||||||
|
|
@ -120,34 +123,64 @@ def create_obs_processor(
|
||||||
padded[key] = arr
|
padded[key] = arr
|
||||||
return padded
|
return padded
|
||||||
|
|
||||||
def _split_to_agents(obs: dict, morph_mode, segments_per_arm) -> dict:
|
def _split_to_agents(obs: dict, morph_mode) -> dict:
|
||||||
output = {}
|
total = 0
|
||||||
num_arms = len(segments_per_arm)
|
for k, v in obs.items():
|
||||||
|
if hasattr(v, "shape"):
|
||||||
|
size = v.size
|
||||||
|
logger11.info(f"[RAW] {k}: shape={v.shape}, size={size}")
|
||||||
|
total += size
|
||||||
|
else:
|
||||||
|
logger11.info(f"[RAW] {k}: non-array")
|
||||||
|
|
||||||
|
logger11.info(f"[RAW TOTAL FEATURES]: {total}")
|
||||||
|
output = {}
|
||||||
|
num_agents = needed_copies # IMPORTANT: number of MLPs
|
||||||
for key, arr in obs.items():
|
for key, arr in obs.items():
|
||||||
if key not in ordered_keys or arr.size == 0:
|
if key not in ordered_keys or arr.size == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logger11.info(f"[INPUT] {key}: {arr.shape}")
|
logger11.info(f"[INPUT] {key}: {arr.shape}")
|
||||||
|
|
||||||
if arr.ndim == 0:
|
if arr.ndim == 0:
|
||||||
arr = arr.reshape(1)
|
arr = arr.reshape(1)
|
||||||
|
# -------- CENTRALIZED --------
|
||||||
if morph_mode == MorphMode.CENTRALIZED:
|
if morph_mode == MorphMode.CENTRALIZED:
|
||||||
out = arr.reshape(1, -1)
|
output[key] = arr.reshape(1, -1)
|
||||||
output[key] = out
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# -------- SEGMENTS --------
|
||||||
if key in _SEGMENT_SCALED_KEYS:
|
if key in _SEGMENT_SCALED_KEYS:
|
||||||
per_agent = [jnp.take(arr, idx, axis=0) for idx in segment_indices]
|
per_agent = []
|
||||||
|
|
||||||
|
for i, agent_id in enumerate(agent_indices):
|
||||||
|
idx = segment_indices[i]
|
||||||
|
taken = jnp.take(arr, idx, axis=0) # (segs, ...)
|
||||||
|
logger11.info(f"WHY {taken.shape}")
|
||||||
|
# pad to 4
|
||||||
|
pad_len = 4 - taken.shape[0]
|
||||||
|
padded = jnp.pad(taken, [(0, pad_len)] + [(0, 0)] * (taken.ndim - 1))
|
||||||
|
|
||||||
|
per_agent.append(padded.reshape(-1))
|
||||||
|
|
||||||
out = jnp.stack(per_agent)
|
out = jnp.stack(per_agent)
|
||||||
|
|
||||||
|
# -------- JOINTS --------
|
||||||
elif key in _JOINT_SCALED_KEYS:
|
elif key in _JOINT_SCALED_KEYS:
|
||||||
per_agent = [jnp.take(arr, idx, axis=0) for idx in joint_indices]
|
per_agent = []
|
||||||
|
|
||||||
|
for i, agent_id in enumerate(agent_indices):
|
||||||
|
idx = joint_indices[i]
|
||||||
|
taken = jnp.take(arr, idx, axis=0) # (joint_n, ...)
|
||||||
|
# pad to 8
|
||||||
|
pad_len = 8 - taken.shape[0]
|
||||||
|
|
||||||
|
padded = jnp.pad(taken, [(0, pad_len)] + [(0, 0)] * (taken.ndim - 1))
|
||||||
|
per_agent.append(padded.reshape(-1))
|
||||||
|
|
||||||
out = jnp.stack(per_agent)
|
out = jnp.stack(per_agent)
|
||||||
|
|
||||||
|
# -------- GLOBAL --------
|
||||||
else:
|
else:
|
||||||
out = jnp.repeat(arr[None, :], num_arms, axis=0)
|
out = jnp.repeat(arr[None, :], num_agents, axis=0)
|
||||||
|
|
||||||
logger11.info(f"[OUTPUT] {key}: {out.shape}")
|
logger11.info(f"[OUTPUT] {key}: {out.shape}")
|
||||||
output[key] = out
|
output[key] = out
|
||||||
|
|
@ -185,15 +218,10 @@ def create_obs_processor(
|
||||||
def _process_single(obs_dict: dict) -> jnp.ndarray:
|
def _process_single(obs_dict: dict) -> jnp.ndarray:
|
||||||
processed = _add_derived_features(obs_dict)
|
processed = _add_derived_features(obs_dict)
|
||||||
processed = _normalize_features(processed)
|
processed = _normalize_features(processed)
|
||||||
# morph_mode = MorphMode.FULLY_CONNECTED
|
processed = _split_to_agents(processed, morph_mode)
|
||||||
processed = _split_to_agents(processed, morph_mode, segments_per_arm)
|
|
||||||
# needed_copies = 5
|
|
||||||
if padding_masks is not None:
|
|
||||||
processed = _pad_features(processed, agent_count=needed_copies)
|
|
||||||
flat = _flatten_features(processed) # (num_arms, total_feat)
|
flat = _flatten_features(processed) # (num_arms, total_feat)
|
||||||
logger11.info(f"[FLATTENED FINAL] shape: {flat.shape}")
|
logger11.info(f"[FLATTENED FINAL] shape: {flat.shape}")
|
||||||
logger11.info(f"[PER AGENT] example row 0 shape: {flat[0].shape}")
|
logger11.info(f"[PER AGENT] example row 0 shape: {flat[0].shape}")
|
||||||
exit(1)
|
|
||||||
return _flatten_features(processed) # (agents, feat)
|
return _flatten_features(processed) # (agents, feat)
|
||||||
|
|
||||||
return jax.jit(jax.vmap(_process_single))
|
return jax.jit(jax.vmap(_process_single))
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,7 @@ class PPOTrainer:
|
||||||
self.feature_extractor,
|
self.feature_extractor,
|
||||||
self.critic,
|
self.critic,
|
||||||
self.needed_copies,
|
self.needed_copies,
|
||||||
|
self.agent_indices,
|
||||||
) = self._init_agent()
|
) = self._init_agent()
|
||||||
|
|
||||||
self.sensor.apply = logged_jit(self.sensor.apply)
|
self.sensor.apply = logged_jit(self.sensor.apply)
|
||||||
|
|
@ -368,6 +369,7 @@ class PPOTrainer:
|
||||||
morph_mode=self.morph_mode,
|
morph_mode=self.morph_mode,
|
||||||
padding_masks=self.env.padding_masks,
|
padding_masks=self.env.padding_masks,
|
||||||
segments_per_arm=self.segments_per_arm,
|
segments_per_arm=self.segments_per_arm,
|
||||||
|
agent_indices=self.agent_indices,
|
||||||
)
|
)
|
||||||
|
|
||||||
action_low = jnp.asarray(self.env.single_action_space.low, dtype=jnp.float32)
|
action_low = jnp.asarray(self.env.single_action_space.low, dtype=jnp.float32)
|
||||||
|
|
@ -436,13 +438,18 @@ class PPOTrainer:
|
||||||
|
|
||||||
def _init_agent(self):
|
def _init_agent(self):
|
||||||
self.logger.info("[AGENT]: Initializing agent...")
|
self.logger.info("[AGENT]: Initializing agent...")
|
||||||
|
agent_indices = [0, 1, 2, 3, 4]
|
||||||
match self.morph_mode:
|
match self.morph_mode:
|
||||||
case MorphMode.CENTRALIZED:
|
case MorphMode.CENTRALIZED:
|
||||||
needed_copies = 1
|
needed_copies = 1
|
||||||
case MorphMode.FULLY_CONNECTED | MorphMode.RING:
|
case MorphMode.FULLY_CONNECTED | MorphMode.RING:
|
||||||
|
agent_mask = self.segments_per_arm > 0
|
||||||
|
agent_indices = jnp.where(agent_mask)[0]
|
||||||
needed_copies = jnp.where(self.segments_per_arm > 0, 1, 0).sum().item()
|
needed_copies = jnp.where(self.segments_per_arm > 0, 1, 0).sum().item()
|
||||||
case MorphMode.SEGMENT:
|
case MorphMode.SEGMENT:
|
||||||
|
agent_mask = self.segments_per_arm > 0
|
||||||
|
agent_indices = jnp.where(agent_mask)[0]
|
||||||
|
needed_copies = jnp.where(self.segments_per_arm > 0, 1, 0).sum().item()
|
||||||
needed_copies = (
|
needed_copies = (
|
||||||
self.segments_per_arm.sum() + jnp.where(self.segments_per_arm > 0, 1, 0).sum()
|
self.segments_per_arm.sum() + jnp.where(self.segments_per_arm > 0, 1, 0).sum()
|
||||||
).item()
|
).item()
|
||||||
|
|
@ -462,7 +469,15 @@ class PPOTrainer:
|
||||||
|
|
||||||
feature_extractor = GenericDenseLayersWithActivation(layer_sizes=[300, 300, 300])
|
feature_extractor = GenericDenseLayersWithActivation(layer_sizes=[300, 300, 300])
|
||||||
critic = OneDenseLayerMLP()
|
critic = OneDenseLayerMLP()
|
||||||
return sensor, message_passer, actor, feature_extractor, critic, needed_copies
|
return (
|
||||||
|
sensor,
|
||||||
|
message_passer,
|
||||||
|
actor,
|
||||||
|
feature_extractor,
|
||||||
|
critic,
|
||||||
|
needed_copies,
|
||||||
|
agent_indices,
|
||||||
|
)
|
||||||
|
|
||||||
def _init_agent_state(self) -> TrainState:
|
def _init_agent_state(self) -> TrainState:
|
||||||
self.logger.info("[AGENT STATE]: Initializing agent state...")
|
self.logger.info("[AGENT STATE]: Initializing agent state...")
|
||||||
|
|
|
||||||
Reference in a new issue