Humanoid Behavior-Cloning Policy (Final)
Supervised-learning policy (behavior cloning) that controls a MuJoCo Humanoid robot's 17 joints from its 376-dim physical state (coordinates/joints/velocities/contact forces β no vision).
- Trained from scratch (no pretrained weights) with MSE regression on expert actions.
- Dataset:
jat-project/jat-dataset(mujoco-humanoid split), 1.25M transitions. - Architecture: MLP [512, 512, 512] + LayerNorm + GELU, ~730K params.
- Input: z-score normalized observation (376). Output: z-score normalized action (17), denormalized at inference.
Usage
import torch, json
from model import HumanoidPolicy # copy model.py from this repo
ckpt = torch.load("model_final.pt", map_location="cpu", weights_only=False)
stats = json.load(open("stats.json"))
model = HumanoidPolicy(obs_dim=ckpt["obs_dim"], act_dim=ckpt["act_dim"], hidden=ckpt["hidden"])
model.load_state_dict(ckpt["model_state"]); model.eval()
obs_mean = torch.tensor(stats["obs_mean"]); obs_std = torch.tensor(stats["obs_std"])
act_mean = torch.tensor(stats["act_mean"]); act_std = torch.tensor(stats["act_std"])
obs = torch.tensor(raw_observation) # shape (376,)
action = model((obs - obs_mean) / obs_std) * act_std + act_mean # shape (17,)
Simulation
Use gymnasium.make("Humanoid-v4"): feed the policy's action (clipped to [-0.4, 0.4]) each step.
See simulate.py in the training project for a full episode runner + video recording.
Trained: 2026-10-09T12:04:44.403316 | step 20000 | val_mse 0.741610 | device cpu | pushed 2026-10-09T12:16:51.250310.
π₯ Live Simulation (model controls the robot)
The policy reads the humanoid state (376 coordinates) each step and outputs its 17 joint commands.
Full video: sim.mp4
Results: 3/3 episodes Γ 1000 steps, never fell | mean return 7369 (expert ~5000).
