# FACT:无 track、预测未来状态、从头训练的 T-Rex 策略(finalized 2026-10-13) FACT(Force-Aware Causal Transformer)是 `trex_track_force` 的轻量替代: | | trex_track_force (A) | trex notrack (B) | **FACT base (finalized)** | FACT small | |---|---|---|---|---| | coarse 去噪器 | Wan2.2-TI2V-5B DiT,d=3072,30 层,LoRA r=4 | 同左,无 track token | 从头训练 DiT 风格 block-causal transformer,d=1024,12 层,16 头,FFN 4096 | d=768,8 层,12 头,FFN 3072 | | 预测目标 | 动作 + 未来视频 latent + 250 点 track | 动作 + 未来视频 latent | **动作 + 未来 16 步 EEF62 状态** | 同左 | | 条件 | 当前帧 VAE latent、state、umT5 文本、CLIP 图像 | 同左 | 当前帧 VAE latent(离线冻结 tokenizer)、state、可学习 task token | 同左 | | force 阶段 | ForceOnlyTransformer 768/6 层 | 同左 | **原样复用**(coarse memory 1024→768) | 同左 | | 部署参数量 | 5.69 B(另加冻结 umT5-XXL / CLIP ViT-H / VAE 在线) | 5.68 B | **209 M(全部可训练;只有 VAE 离线冻结)** | 109 M | | 可训练参数 | 120 M(LoRA 11.6M + 新模块 60.7M + force 47.9M) | 109 M | 209 M | 109 M | | 训练方式 | LoRA 微调 | LoRA 微调 | **从头训练** | 从头训练 | 缩小比例:部署参数 5686 M → 209 M(**27×**),small 版 → 109 M(52×)。 ## 1. 结构 每个 autoregressive block(0.8 s)打包 83 个 token:`[obs 50][state 1][action 16][future-state 16]`, 前面一个可学习 task token。训练时 K=4 个 block(3.2 s)一次前向,block-causal mask:block k 只能读 blocks `[k-4, k]` 和 task token(与基线 `max_chunk_size=4` 一致);在线 K=1。 - **obs**:当前帧三视角按 DreamZero 2×2 网格(head | right ; left | black)拼到 160×320,Wan2.2 VAE 编码成 48×10×20 latent,2×2 patch → 50 个 token,`Linear(192→d)`。VAE 冻结,训练前离线缓存。 - **state**:62 维 EEF62 补零到 64,MLP 到 d。clean,τ=0。 - **action**:16×62 delta-base 动作(与基线完全相同的归一化与参考系),补零 64,`Linear(64→d)`;noisy,τ 按 block 采样 Beta(1.5,1)。 - **future state**:block anchor 之后 1..16 步(20 Hz)的 EEF62 状态,相对 block 参考状态做 delta-base,用动作统计量归一化;noisy,与 action 共用 τ。 - 位置信息:slot embedding(83 个槽位)+ block embedding + token-type embedding(无 RoPE)。 - 每个 token 自己的 τ → sinusoidal(256) → MLP → per-token adaLN-zero(6 个调制向量,与 Wan 一样 可让不同模态处于不同噪声水平);qk-RMSNorm;最终 adaLN + 两个线性 head(action flow / future-state flow)。 - **coarse memory**:最后一层 hidden state 中 block k 可见的全部 token(在线 K=1 时 84 个),交给 force 阶段。 - **force 阶段**:`trex_track_force.force.ForceOnlyTransformer` 原样复用(16 action + 10 F6 + 10 VQ history + memory),τ 0.4→0 四步、suffix-only、offset 0/4/8/12、tactile dropout 0.1、VQ/commitment loss 不变。 Loss:`action_flow_mse + state_flow_mse + force_flow_mse + vq + 0.25·commitment`,权重全为 1。 采样:6 步 coarse Euler(τ 1→0.4)→ τ=0.4 边界前向取 memory 与 clean future state → 4 步 force 精修;`coarse_to_zero` 模式用 coarse 模型自己走完 τ→0。 ## 2. Benchmark(与 `scripts/eval/trex_ablation_eval.py` 相同协议) `data/trex_mini_force`(trex_full_force 第 49 集,902 帧,“Past the block, use your left hand to pick up the lipstick from the table.”),全部 537 个 K=4 anchor 训练 3000 步,开环评测 16 个 K=1 anchor (seed 500+i),归一化 62 维 delta-base 动作 MSE。FACT:batch 8,lr 2e-4 cosine,AdamW,bf16,单块 PPU 约 45 min。 | 模型 | 参数 | cascade ↓ | coarse_only (τ=0.4 读出) ↓ | coarse_to_zero ↓ | arm / hand (cascade) | |---|---|---|---|---|---| | A trex_track_force | 5.69 B | 0.2054 | 0.3859 | — | 0.291 / 0.171 | | B trex notrack | 5.68 B | 0.2300 | 0.3834 | — | 0.298 / 0.202 | | D deform+force | 5.69 B | 0.2016 | 0.3860 | — | 0.286 / 0.167 | | **FACT base (seed 42)** | **209 M** | **0.0049** | 0.2408 | 0.0048 | 0.007 / 0.004 | | FACT base (seed 7) | 209 M | 0.0045 | 0.2405 | 0.0045 | 0.007 / 0.004 | | FACT base, 无 future-state | 209 M | 0.0045 | 0.2388 | 0.0043 | 0.007 / 0.004 | | FACT small (768/8) | 109 M | 0.0076 | 0.2425 | 0.0049 | 0.013 / 0.005 | 固定 τ 的 action flow MSE(τ=0.2):基线 0.75,FACT 0.039。 **注意**:这个 benchmark 和基线 ablation 一样是单集过拟合(评测 anchor 来自训练集),衡量的是在相同 预算下的拟合能力,不是泛化。为此额外做了 held-out 探针(只用前 80% 时间段的 417 个 anchor 训练, 评测最后 20% 的 16 个从未见过的 anchor): | 模型 (held-out) | cascade | coarse_only | coarse_to_zero | arm / hand | |---|---|---|---|---| | FACT base | 0.504 | 0.613 | 0.479 | 0.278 / 0.596 | | FACT base 无 future-state | 0.516 | 0.586 | 0.477 | 0.309 / 0.600 | | FACT small | 0.491 | 0.582 | 0.442 | 0.285 / 0.575 | 读法:单集内 6 s 的 held-out 段是任务的另一阶段(hand 维误差 0.6),任何只见过一集的模型都不可能 泛化好;三者差异在 anchor 间标准差(±0.15)之内,不足以区分结构。future-state 在 arm 维略好 (0.278 vs 0.309)。force 精修在 held-out 上略差于 coarse_to_zero,说明 46 M 的 tactile 精修器在单集 数据上过拟合——它的价值(接触后的触觉反应)需要多集/真机才能体现。基线没有 held-out 数字,不可比。 ## 3. Finalized 结构 `scripts/fact/configs/fact_base.json`(d=1024/12 层,预测 future state,force 阶段保留)。 理由:在正式协议上两种 seed 都是最优(0.0045–0.0049,比 A 好 42×、比 B 好 47×), future-state 保留了与 T-Rex 一致的"预测未来"接口且在 held-out arm 上不劣,force 阶段保留 T-Rex 的 5 Hz 触觉刷新路径。`fact_small.json`(109 M)作为资源受限时的替代,正式协议 0.0076,held-out 略优。 ## 4. 代码与运行 ``` groot/vla/model/fact/model.py FactConfig / FactCoarseTransformer / FactPolicy(forward_core, sample, refine_action_suffix) groot/vla/model/fact/data.py FactEpisode(parquet + 统计量 + latent 缓存)/ FactAnchorDataset scripts/fact/build_cache.py 冻结 VAE 离线编码整集帧(0.9 s/集) scripts/fact/train.py 从头训练;--config-json / --dim / --layers / --no-future-state / --no-force / --train-fraction scripts/fact/eval.py 基线协议开环评测;--heldout-fraction scripts/fact/param_count.py 参数量对比(meta device) scripts/fact/run_exp.sh cache → train → eval 一条龙;scripts/fact/collect.py 汇总表 ``` ```bash source /mnt/workspace/zhicao/dreamzero/.fact_env # PPU SDK + .venv_ppu bash scripts/fact/run_exp.sh fact_base 8 --config-json "$(cat scripts/fact/configs/fact_base.json)" \ --steps 3000 --batch 8 --lr 2e-4 --bf16 --workers 4 HELDOUT=0.2 bash scripts/fact/run_exp.sh probe 9 ... --train-fraction 0.8 # held-out 探针 python scripts/fact/collect.py fact_runs # 汇总所有 eval.json ``` 已训练的 checkpoint:`fact_runs/v1_d1024_l12/final`(finalized base,seed 42)、`fact_runs/v1_d768_l8/final`(small)。 ## 5. 在 T-Rex-100(`data/trex_small_force`)上 16 卡从头全量训练(2026-10-13 新增) 多任务训练需要语言条件:`fact_base_text.json` 在 base 结构上加了冻结 umT5-XXL 的 token embedding 作为 clean prefix(64 token,`LayerNorm+Linear(4096→d)`,padding 用 attention mask 屏蔽), 其余结构不变(209 M + 4.3 M 文本投影)。 ``` scripts/train/fact_full_training_trex100.sh 入口(对标 trex_track_force_training_wan22.sh) scripts/fact/build_cache_dataset.py 离线缓存:VAE latent(16 卡分片并行)+ umT5 文本 scripts/fact/train_ddp.py torchrun DDP 训练;wandb 标量 + 周期监控视频 + checkpoint/resume scripts/fact/configs/fact_base_text.json finalized base + 文本条件 groot/vla/model/fact/data.py FactMultiEpisodeDataset(100 集、mmap latent、文本缓存) ``` ```bash tmux attach -t fact source /mnt/workspace/zhicao/dreamzero/.fact_env # PPU SDK + .venv_ppu wandb login # 可选;没有 key 时脚本自动 WANDB_MODE=offline bash scripts/train/fact_full_training_trex100.sh # 16 卡、100k 步、每 10k 存一次 ``` 默认:global batch 16×8=128(每个样本 4 个 AR block)、lr 3e-4 cosine(warmup 2000)、wd 0.01、bf16、 输出 `checkpoints/fact_trex100_full/`(`checkpoint-N/`、`train.log`、`loss_log.jsonl`、`eval_videos/`)。 缓存在 `fact_runs/cache/trex_small_force/`(首次自动构建,约 67k 帧;之后直接复用)。 断点续训:再跑同一条命令即可(`--resume auto` 读 `latest`)。 可用环境变量覆盖:`OUTPUT_DIR NUM_GPUS PER_DEVICE_BATCH LR MAX_STEPS SAVE_STEPS VIDEO_STEPS WANDB_PROJECT FACT_CONFIG`。 W&B:`train/*`(loss、action/state/force/vq loss、grad_norm、lr、sec_per_it);每 `VIDEO_STEPS`(默认 1000)步 在第 0 集连续 4 个 chunk 上采样,记录 `eval/openloop_cascade_mse`、`eval/openloop_coarse_only_mse`、 `eval/future_state_mse` 和 `eval/predicted_video`(左:head 相机 GT 帧按 20 Hz 推进;右:动作与未来状态 的预测 vs GT 曲线,黑 GT / 红 cascade / 蓝 coarse τ=0.4 / 绿 future-state)。FACT 不预测视频,所以 "视频重建"展示的是状态/动作重建。本地同样保存到 `OUTPUT_DIR/eval_videos/train_step_XXXXXX.mp4`。 注意:启动器必须用 venv 的 `python -m torch.distributed.run`(系统 `torchrun` 指向系统 python,缺 diffusers); rank-0 单独采样时要关掉 tactile VQ 的 perplexity all-reduce(train_ddp.py 已处理),否则其它 rank 会卡死。