Download scripts/train_full.sh from zhicao/FACT: direct link, hf CLI and curl.
- Browser
- Download file 6.23 kB
-
https://huggingface.co/zhicao/FACT/resolve/main/scripts/train_full.sh
- Command line
-
hf download hf://zhicao/FACT/scripts/train_full.sh
-
curl -L -o train_full.sh https://huggingface.co/zhicao/FACT/resolve/main/scripts/train_full.sh
6.23 kB
| set -euo pipefail | |
| # FACT full training (from scratch, no LoRA) on a T-Rex-format LeRobot-v2.1 | |
| # dataset: offline caches (frozen Wan2.2 VAE latents sharded over all GPUs, | |
| # umT5-XXL text embeddings on node 0), then torch.distributed DDP training with | |
| # checkpoints every SAVE_STEPS, W&B scalars and a periodic monitoring video. | |
| # | |
| # Usage (inside tmux): | |
| # [source your env] # optional: FACT_ENV_FILE=/path/to/env.sh | |
| # bash scripts/train_full.sh [extra train_ddp.py args] | |
| # Multi-node: run on every node with NNODES / NODE_RANK / MASTER_ADDR set | |
| # (node rank 0 = MASTER_ADDR; caches are built cooperatively on shared storage). | |
| # Env overrides: DATA_ROOT OUTPUT_DIR CACHE_DIR FACT_CONFIG WAN22_CKPT_DIR NUM_GPUS | |
| # PER_DEVICE_BATCH LR MAX_STEPS SAVE_STEPS VIDEO_STEPS WANDB_PROJECT | |
| # WANDB_RUN_NAME REQUIRE_FORCE(0/1) | |
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" | |
| DATA_ROOT="${DATA_ROOT:-${TREX_DATA_ROOT:-$REPO_ROOT/data/trex_full_force}}" | |
| OUTPUT_DIR="${OUTPUT_DIR:-$REPO_ROOT/checkpoints/$(basename "$DATA_ROOT")_fact}" | |
| CACHE_DIR="${CACHE_DIR:-${FACT_CACHE_DIR:-$REPO_ROOT/cache/$(basename "$DATA_ROOT")}}" | |
| FACT_CONFIG="${FACT_CONFIG:-$REPO_ROOT/configs/fact_base_text.json}" | |
| WAN22_CKPT_DIR="${WAN22_CKPT_DIR:-$REPO_ROOT/checkpoints/Wan2.2-TI2V-5B}" | |
| NUM_GPUS="${NUM_GPUS:-16}" | |
| NNODES="${NNODES:-1}" | |
| NODE_RANK="${NODE_RANK:-0}" | |
| MASTER_ADDR="${MASTER_ADDR:-127.0.0.1}" | |
| MASTER_PORT="${MASTER_PORT:-29701}" | |
| PER_DEVICE_BATCH="${PER_DEVICE_BATCH:-8}" | |
| LR="${LR:-3e-4}" | |
| MAX_STEPS="${MAX_STEPS:-100000}" | |
| SAVE_STEPS="${SAVE_STEPS:-10000}" | |
| VIDEO_STEPS="${VIDEO_STEPS:-1000}" | |
| VIDEO_SAVE_LOCAL="${VIDEO_SAVE_LOCAL:-0}" | |
| WANDB_PROJECT="${WANDB_PROJECT:-fact}" | |
| WANDB_RUN_NAME="${WANDB_RUN_NAME:-$(basename "$OUTPUT_DIR")}" | |
| REQUIRE_FORCE="${REQUIRE_FORCE:-0}" # 1 = dataset must carry the trex_track_force tactile schema/manifest | |
| # ---- environment ------------------------------------------------------------ | |
| if [ -n "${FACT_ENV_FILE:-}" ] && [ -f "$FACT_ENV_FILE" ]; then | |
| set +eu | |
| # shellcheck disable=SC1090 | |
| source "$FACT_ENV_FILE" | |
| set -eu | |
| fi | |
| export PYTHONPATH="$REPO_ROOT${PYTHONPATH:+:$PYTHONPATH}" | |
| cd "$REPO_ROOT" | |
| filt() { grep --line-buffered -v -E "libhggcrt1|ALINPU|^\s*$"; } | |
| if [ ! -f "$DATA_ROOT/meta/info.json" ]; then | |
| echo "ERROR: LeRobot-v2 dataset not found: $DATA_ROOT" >&2; exit 1 | |
| fi | |
| for required in "$WAN22_CKPT_DIR/Wan2.2_VAE.pth" "$WAN22_CKPT_DIR/models_t5_umt5-xxl-enc-bf16.pth" \ | |
| "$WAN22_CKPT_DIR/google/umt5-xxl/tokenizer.json" "$FACT_CONFIG"; do | |
| if [ ! -f "$required" ]; then echo "ERROR: missing file: $required" >&2; exit 1; fi | |
| done | |
| READY_ARGS=(--dataset-root "$DATA_ROOT") | |
| if [ "$REQUIRE_FORCE" = "1" ]; then READY_ARGS+=(--require-force); fi | |
| python "$REPO_ROOT/scripts/check_dataset_ready.py" "${READY_ARGS[@]}" 2>&1 | filt | |
| # ---- offline caches --------------------------------------------------------- | |
| N_EPISODES=$(python -c "import json;print(json.load(open('$DATA_ROOT/meta/info.json'))['total_episodes'])") | |
| count_cached() { ls "$CACHE_DIR/latents" 2>/dev/null | grep -c '^episode_.*\.npy$' || true; } | |
| TOTAL_SHARDS=$((NNODES * NUM_GPUS)) | |
| if [ "$(count_cached)" -lt "$N_EPISODES" ]; then | |
| echo ">>> building VAE latent cache: $(count_cached)/$N_EPISODES episodes cached; node $NODE_RANK runs shards $((NODE_RANK * NUM_GPUS))..$((NODE_RANK * NUM_GPUS + NUM_GPUS - 1)) of $TOTAL_SHARDS" | |
| mkdir -p "$CACHE_DIR/latents" | |
| for ((i = 0; i < NUM_GPUS; i++)); do | |
| SHARD=$((NODE_RANK * NUM_GPUS + i)) | |
| CUDA_VISIBLE_DEVICES=$i python scripts/build_cache_dataset.py --what latents \ | |
| --dataset-root "$DATA_ROOT" --out "$CACHE_DIR" \ | |
| --vae "$WAN22_CKPT_DIR/Wan2.2_VAE.pth" --shard "$SHARD" --num-shards "$TOTAL_SHARDS" \ | |
| 2>&1 | filt | sed "s/^/[shard $SHARD] /" & | |
| done | |
| wait | |
| fi | |
| if [ "$NODE_RANK" = "0" ] && [ ! -f "$CACHE_DIR/text_cache.npz" ]; then | |
| echo ">>> building umT5 text cache" | |
| CUDA_VISIBLE_DEVICES=0 python scripts/build_cache_dataset.py --what text \ | |
| --dataset-root "$DATA_ROOT" --out "$CACHE_DIR" \ | |
| --text-encoder "$WAN22_CKPT_DIR/models_t5_umt5-xxl-enc-bf16.pth" \ | |
| --tokenizer "$WAN22_CKPT_DIR/google/umt5-xxl" --max-text-tokens 64 2>&1 | filt | |
| fi | |
| until [ -f "$CACHE_DIR/text_cache.npz" ] && [ "$(count_cached)" -ge "$N_EPISODES" ]; do | |
| echo ">>> node $NODE_RANK waiting for caches: $(count_cached)/$N_EPISODES latents, text=$([ -f "$CACHE_DIR/text_cache.npz" ] && echo yes || echo no)" | |
| sleep 60 | |
| done | |
| # ---- W&B: online if credentials exist, otherwise offline -------------------- | |
| if [ -z "${WANDB_API_KEY:-}" ] && ! grep -qs "api.wandb.ai" "$HOME/.netrc"; then | |
| echo ">>> no W&B credentials found; using WANDB_MODE=offline" | |
| export WANDB_MODE="${WANDB_MODE:-offline}" | |
| fi | |
| mkdir -p "$OUTPUT_DIR" | |
| ulimit -n 65536 2>/dev/null || true | |
| echo ">>> FACT training: $NNODES node(s) x $NUM_GPUS GPUs x batch $PER_DEVICE_BATCH, $MAX_STEPS steps, save every $SAVE_STEPS -> $OUTPUT_DIR" | |
| if [ "$NNODES" = "1" ]; then | |
| LAUNCH=(python -m torch.distributed.run --nproc_per_node="$NUM_GPUS" --standalone) | |
| else | |
| LAUNCH=(python -m torch.distributed.run --nproc_per_node="$NUM_GPUS" --nnodes="$NNODES" --node_rank="$NODE_RANK" \ | |
| --master_addr="$MASTER_ADDR" --master_port="$MASTER_PORT") | |
| fi | |
| "${LAUNCH[@]}" \ | |
| "$REPO_ROOT/scripts/train_ddp.py" \ | |
| --dataset-root "$DATA_ROOT" \ | |
| --cache-dir "$CACHE_DIR" \ | |
| --output-dir "$OUTPUT_DIR" \ | |
| --config "$FACT_CONFIG" \ | |
| --blocks 4 \ | |
| --max-steps "$MAX_STEPS" \ | |
| --per-device-batch "$PER_DEVICE_BATCH" \ | |
| --lr "$LR" \ | |
| --min-lr-ratio 0.1 \ | |
| --warmup-steps 2000 \ | |
| --weight-decay 0.01 \ | |
| --clip 1.0 \ | |
| --seed 42 \ | |
| --workers 4 \ | |
| --bf16 1 \ | |
| --log-steps 20 \ | |
| --save-steps "$SAVE_STEPS" \ | |
| --save-total-limit 10 \ | |
| --resume auto \ | |
| --report-to wandb \ | |
| --wandb-project "$WANDB_PROJECT" \ | |
| --wandb-run-name "$WANDB_RUN_NAME" \ | |
| --video-steps "$VIDEO_STEPS" \ | |
| --video-episode 0 \ | |
| --video-num-chunks 4 \ | |
| --video-save-local "$VIDEO_SAVE_LOCAL" \ | |
| "$@" 2>&1 | filt | tee -a "$OUTPUT_DIR/train_node${NODE_RANK}.log" | |