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.

Simulation

Full video: sim.mp4

Results: 3/3 episodes Γ— 1000 steps, never fell | mean return 7369 (expert ~5000).

Downloads last month

-

Downloads are not tracked for this model. How to track
Video Preview
loading