groot / code /hb_groot /hb_launch.py
BIue-Jay's picture
Add files using upload-large-folder tool
942788e verified
Raw History Blame Contribute Delete
3.91 kB
"""GR00T N1.7 fine-tuning entry with Humanoid Benchmark augmentation v2.
Patches Gr00tN1d7Processor in training mode only:
- images: native random crop / colour jitter / rotation are bypassed (the deterministic eval resize+center-crop is
used), then hb_aug_v2 is applied jointly to all cameras of the sample;
- proprio: the body-joint state groups (HB_BODY_STATE_KEYS) get the v2 bias + noise before normalization.
Then runs the pinned upstream gr00t/experiment/launch_finetune.py unchanged.
"""
import json
import os
import runpy
import sys
from pathlib import Path
import numpy as np
import torch
HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
import hb_offline_fix # noqa: E402,F401 (tokenizer load under HF_HUB_OFFLINE=1, see module docstring)
import hb_aug_v2 as A # noqa: E402
from gr00t.model.gr00t_n1d7 import processing_gr00t_n1d7 as P # noqa: E402
Proc = P.Gr00tN1d7Processor
BODY_KEYS = [k for k in os.environ.get("HB_BODY_STATE_KEYS", "left_leg,right_leg,waist,left_arm,right_arm").split(",") if k]
LOG = os.environ.get("HB_AUG_LOG")
_state = {"rng": None, "count": 0}
def _rng():
if _state["rng"] is None:
_state["rng"] = np.random.default_rng([os.getpid(), int.from_bytes(os.urandom(8), "little")])
return _state["rng"]
_orig_get, _orig_apply, _orig_call = Proc._get_vlm_inputs, Proc._apply_vlm_processing, Proc.__call__
def _get_vlm_inputs(self, image_keys, images, masks, image_transform, language):
if getattr(self, "training", False):
self._hb_views = len(image_keys)
try:
return _orig_get(self, image_keys, images, masks, self.eval_image_transform, language)
finally:
self._hb_views = None
return _orig_get(self, image_keys, images, masks, image_transform, language)
def _apply_vlm_processing(self, images, language):
views = getattr(self, "_hb_views", None)
if views and isinstance(images, torch.Tensor):
shape = images.shape
x = images.reshape(-1, views, *shape[1:]).float().div(255.0)
x, p = A.augment(x, _rng())
images = (x * 255.0 + 0.5).clamp(0, 255).to(torch.uint8).reshape(shape)
_state["count"] += 1
if LOG and _state["count"] in (1, 50):
with open(f"{LOG}.{os.getpid()}", "a") as f:
f.write(json.dumps({"count": _state["count"], "views": views, "hw": list(shape[-2:]),
"boost": p["boost"], "version": A.VERSION}) + "\n")
return _orig_apply(self, images, language)
def _call(self, messages):
if getattr(self, "training", False) and BODY_KEYS:
states = messages[0]["content"].states
for key in BODY_KEYS:
if key in states:
states[key] = A.perturb_joints(states[key], _rng())
return _orig_call(self, messages)
Proc._get_vlm_inputs = _get_vlm_inputs
Proc._apply_vlm_processing = _apply_vlm_processing
Proc.__call__ = _call
if os.environ.get("HB_PATCH_ONLY") != "1":
entry = Path(os.environ["GROOT_SRC"]) / "gr00t/experiment/launch_finetune.py"
sys.argv = [str(entry)] + sys.argv[1:]
try:
runpy.run_path(str(entry), run_name="__main__")
finally: # batch probe: report this rank's peak reserved memory (groot_chain.py compares it with MAX_FRAC)
_peak = os.environ.get("HB_PEAK_FILE")
if _peak and torch.cuda.is_available():
try:
_dev = torch.cuda.current_device()
with open(f"{_peak}-rank{os.environ.get('RANK', '0')}.json", "w") as _f:
json.dump({"rank": int(os.environ.get("RANK", "0")),
"peak_reserved_gb": torch.cuda.max_memory_reserved(_dev) / 1e9,
"total_gb": torch.cuda.get_device_properties(_dev).total_memory / 1e9}, _f)
except Exception: # noqa: BLE001 - never mask the training result
pass