《VLA系列》TurboVLA 复现指南:0.2B小模型 | 32 Hz | 显存<1 GB 全量微调
TurboVLA 复现指南:从环境搭建到 100% 成功率(LIBERO 单套件最小可行方案)
论文:TurboVLA: Real-Time Vision-Language-Action Model at 32 Hz on an RTX 4090 with <1 GB VRAM
代码:https://github.com/H-EmbodVis/TurboVLA
复现环境:RTX 4090、PyTorch 2.3.1 + CUDA 12.1、Python 3.10
摘要
本文记录了 TurboVLA 在 LIBERO 基准上的完整复现过程。与官方"四套件混合、40k 步、4 卡"的论文配方不同,
本文采用最小可行方案:只下载 libero_object 单个套件(约 2.8 GB)、4090显卡上训练 10000 步,最终在 50 次仿真 rollout 中取得 100%(50/50)成功率,其中 9000 步 checkpoint 为 98%(49/50),10000 步即达到满分。
全文重点不在"照抄命令",而在踩坑记录:复现过程中共遇到 9 个典型问题(依赖版本冲突、Gated 模型授权、仿真器渲染、驱动兼容等),每个问题都给出了根因分析和解决方案,并附排查思路,供后续复现者按图索骥。
一、整体流程概览
二、方法解析:模型结构与训练思路(论文框架)
本节内容从论文与仓库源码(
turbovla/models/、turbovla/training/)交叉还原,帮助理解后面每条命令"为什么这么配"。
2.1 核心思路:抛弃 LLM 中枢的 V+L→A 直接映射
-
主流 VLA(如 OpenVLA、π0)采用 LLM 中心的 V→L→A 通路:视觉和语言先汇入大语言模型,再由 LLM 输出动作,计算与显存开销大。
-
TurboVLA 的核心主张是视觉和语言各自独立编码,去除LLM,通过轻量交叉注意力直接融合,再由紧凑解码器输出动作块(V+L→A),完全绕开 LLM:
| 指标 | TurboVLA | 说明 |
|---|---|---|
| 参数量 | 0.2B | 无 LLM,整体小一个数量级 |
| LIBERO 平均成功率 | 97.6% | 与 LLM 中心的大模型相当 |
| 推理延迟 | 31.2 ms(32 Hz) | RTX 4090 实测 |
| 推理显存 | 0.9 GiB | 消费级显卡可部署 |

2.2 模型结构:一次前向的完整流程
各模块要点(与后文命令参数的对应关系):
| 模块 | 关键配置 | 训练策略 | 初始化来源 |
|---|---|---|---|
视觉编码器 | DINOv3 ViT-B,双视角分别编码,patch token + 视角 embedding | 全量解冻微调,BF16 autocast(权重保持 FP32) | facebook/dinov3 预训练 |
| 文本编码器 | BERT base,在线编码(无文本特征缓存),固定 padding 长度 21 | 冻结(freeze_text_encoder=True) | google-bert 预训练 |
交互模块 | 6 层 ×(双向交叉注意力 + 文本自注意力),hidden 256 / inner 1024 | 训练 | GroundingDINO 的 feature enhancer(--pretrained_init_ckpt 的作用) |
| 动作头 | 状态 8 维→2 token;12 个 action query;3 层 Decoder | 训练 | 随机初始化 |
这就解释了为什么训练必须提供
--pretrained_init_ckpt(GroundingDINO 权重):交互模块和文本投影层都从它做迁移初始化,这是 TurboVLA 小数据量下仍能快速收敛的关键之一。
2.3 训练方法:从源码还原的配方
损失函数:对 12 步动作块做 masked L1 loss(masked_l1_loss),padding 步不计入。
优化器(pi0.5 风格):
- AdamW,
betas=(0.9, 0.95)、eps=1e-8,梯度裁剪 1.0; - EMA 权重(decay=0.999)随优化器同步维护,checkpoint 中同时保存
model_state_dict与ema_model_state_dict,评估用 EMA 权重; - 参数分四组:DINOv3(decay / no_decay)与头部(decay / no_decay),学习率均 5e-5,weight_decay 1e-10(LayerNorm、bias 等一维参数不衰减)。
学习率调度:线性 warmup(0.1→1.0)后接余弦衰减;默认 min_lr_ratio=1.0,即 warmup 结束后保持恒定学习率——所以 warmup 步数是这个配方里最重要的调度参数(前文坑 4 的根源)。
精度策略:策略网络参数与优化器状态保持 FP32,仅 DINOv3 前向用 BF16 autocast(--dinov3_precision bf16_autocast),兼顾稳定性与速度。
数据管线:RLDS/TFDS 流式读取;episode 级 shuffle buffer 512;episode 内 step 级打乱;多套件时按 step 级混合(step_mix_buffer_size=64);每次从一条轨迹采 12 步连续动作块作为监督。
论文完整配方(对照本文的测试配方):
| 项目 | 论文配方 | 本文测试配方 |
|---|---|---|
| 数据 | 四套件混合 | libero_object 单套件 |
| global batch | 128(4 卡 × 8 × 4 累积) | 64(2 卡 × 32 × 1) |
| 训练步数 | 40k(warmup 10k) | 10k(warmup 1k) |
| 学习率 / seed | 5e-5 / 42 | 同左(默认) |
| 结果 | 四套件平均 97.6% | libero_object 100%(50/50) |
三、环境搭建(从零开始)
3.1 克隆仓库
git clone https://github.com/H-EmbodVis/TurboVLA.git
cd TurboVLA
注意:LIBERO 和 RoboTwin 使用不同的仿真器与数据栈,官方建议分开建 Python 3.10 环境。本文只涉及 LIBERO。
3.2 创建 LIBERO 环境
conda create -n turbovla-libero python=3.10 -y
conda activate turbovla-libero
# 先安装与系统 CUDA 匹配的 PyTorch
pip install torch==2.3.1 torchvision==0.18.1 --index-url https://download.pytorch.org/whl/cu121
pip install -e ".[libero]"
LIBERO 仿真器本体需要在同一环境中单独安装(本文在第七部分评估环节安装,见 7.1 节——它的依赖较"脏",建议用到时再装,且用
--no-deps避免污染训练环境)。
⚠️ 坑 1:huggingface_hub 版本冲突(重点)
现象:按 README 执行 pip install -U huggingface_hub 后,训练启动即崩溃:
ImportError: huggingface-hub>=0.34.0,<1.0 is required ... but found huggingface-hub==1.32.0
根因:README 让你升级 huggingface_hub 到最新(1.x),但 transformers 4.56/4.57 只兼容 <1.0。两个进程都在 import transformers 阶段就死了,与 GPU、torchrun 无关。
解决:降回 0.x 最新版(0.34+ 仍支持 hf CLI,下载功能不受影响):
pip install "huggingface_hub>=0.34,<1"
经验:此后不要再执行 pip install -U huggingface_hub。
四、数据准备:单套件最小方案
4.1 下载数据
export HF_ENDPOINT=https://hf-mirror.com # 国内镜像,可选
hf download openvla/modified_libero_rlds --repo-type dataset \
--include "libero_object_no_noops/*" \
--local-dir data/libero
验证完整性:目录下应有 dataset_info.json、features.json 和 32 个 .tfrecord 分片(共 34 个文件)。
⚠️ 坑 2:镜像下载末尾限速
现象:进度 97% 后速度从 MB/s 掉到 200 KB/s。
解决:hf download 支持断点续传,Ctrl+C 后原命令重跑即可;顽固情况用多线程:
pip install hf_transfer
export HF_HUB_ENABLE_HF_TRANSFER=1
# 重跑下载命令
4.2 计算单套件归一化统计(重点)
为什么不能直接用官方 libero_all4_stats.json:其中的 libero_all4_no_noops 是四套件混合的统计量,单套件训练直接复用会导致动作归一化/反归一化不一致,输出全错。必须用仓库自带脚本重算:
python scripts/libero/compute_mixed_stats.py \
--dataset_dir data/libero/libero_object_no_noops/1.0.0 \
--output experiments/libero/configs/libero_object_stats.json \
--stats_key libero_object_no_noops
验证基准:正常输出 454 条 episode、66984 帧动作,episode 平均长度约 147.5。
日志中 TensorFlow 的 cuDNN / “Skipping registering GPU devices” 警告是预期行为——脚本主动禁用了 TF 的 GPU,TF 只负责读 TFRecord,GPU 计算全走 PyTorch。
五、模型权重准备
5.1 官方预训练 checkpoint(建议先下)
模型权重与基准数据属于外部资产,不随仓库发布,需从 Hugging Face 单独下载完整发布包(含模型权重和归一化元数据):
hf download H-EmbodVis/TurboVLA \
--local-dir pretrained/TurboVLA
为什么建议先下它:拿到官方 checkpoint 后,可以在不下载任何训练数据的情况下先跑评估(见第七部分),零成本验证环境是否正确——这就是"先评估后训练"策略的基础。
⚠️ 注意:官方 README 此处给出的命令是
pip install -U huggingface_hub && hf download ...,不要照抄第一行——它会把 huggingface_hub 升到 1.x,直接引发坑 1 的版本冲突。当前环境(0.34+)的hf download完全可用。如果已经误执行,重新pip install "huggingface_hub>=0.34,<1"即可。
5.2 DINOv3:⚠️ 坑 3——Gated 仓库,403 Forbidden(重点)
现象:
403 Forbidden: Please enable access to public gated repositories in your fine-grained token settings
Cannot access content at: https://hf-mirror.com/facebook/dinov3-vitb16-pretrain-lvd1689m/...
根因:facebook/dinov3-* 需要先在 HF 网页登录并同意协议,且 token 需具备 gated 仓库访问权限(fine-grained token 默认不勾选)。
解决(推荐,免授权):从 ModelScope 官方镜像下载到本地,约 330 MB:
pip install modelscope
modelscope download --model facebook/dinov3-vitb16-pretrain-lvd1689m \
--local_dir pretrained/dinov3-vitb16
训练参数相应改为 --dinov3_path pretrained/dinov3-vitb16(代码用 AutoModel.from_pretrained 加载,本地目录即可)。
备选方案:HF 网页同意协议 + 创建 Read 类型 token +
hf login。
5.3 其余两份权重
# GroundingDINO 初始化权重(训练必需)
mkdir -p pretrained/groundingdino
wget -O pretrained/groundingdino/groundingdino_swint_ogc.pth \
https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth
# BERT:下载到本地目录(评估脚本强制要求本地路径)
hf download google-bert/bert-base-uncased --local-dir pretrained/bert-base-uncased
六、训练
6.1 启动命令(双卡、10000 步)
torchrun --nproc_per_node=2 experiments/libero/train.py \
--dataset_dir data/libero/libero_object_no_noops/1.0.0 \
--dataset_dirs "data/libero/libero_object_no_noops/1.0.0" \
--stats_path experiments/libero/configs/libero_object_stats.json \
--stats_key libero_object_no_noops \
--dinov3_path pretrained/dinov3-vitb16 \
--bert_path google-bert/bert-base-uncased \
--allow_hf_download \
--pretrained_init_ckpt pretrained/groundingdino/groundingdino_swint_ogc.pth \
--batch_size 32 \
--max_steps 10000 \
--warmup_steps 1000 \
--save_steps 5000 \
--checkpoint_dir outputs/libero_object_smoke
⚠️ 坑 4:max_steps 与 warmup_steps 的约束
现象:
ValueError: lr_schedule_steps=10000 must be greater than warmup_steps=10000
根因:--max_steps 会同步设为学习率调度总步数,而 warmup 默认沿用论文值 10000,两者相等触发校验。
解决:warmup 取总步数 5~10%,如 10000 步配 --warmup_steps 1000。
6.2 训练效率与工程细节(重点)
| 项目 | 默认值 | 说明 |
|---|---|---|
--max_steps | 80000 | 论文配方;单套件冒烟 10000 足够 |
--save_steps | 1000 | 每 1000 步存一次;单 checkpoint 约 3 GB(含优化器+EMA),冒烟建议调大到 5000 |
--resume_mode | none | 支持断点续训:--resume_mode all 自动从 checkpoint_dir 最新权重恢复 |
--num_workers | 4 | 数据加载线程,已够用 |
--batch_size | 8 | 24 GB 显存只用 6 GB,提到 32 吞吐显著提升 |
实测双卡 batch 32、2.05 it/s,10000 步约 1.5 小时。checkpoint 内含 ema_model_state_dict(EMA 权重),评估时自动优先使用。
训练日志:
training: 10%|█████████▋ | 1000/10000 [12:27<1:54:14, 1.31it/s, loss=0.09440, avg=0.11275, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_1000.pth
training: 20%|███████████████████▍ | 2000/10000 [24:54<1:39:39, 1.34it/s, loss=0.09160, avg=0.09025, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_2000.pth
training: 30%|█████████████████████████████ | 3000/10000 [37:19<1:26:18, 1.35it/s, loss=0.09752, avg=0.08808, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_3000.pth
training: 40%|██████████████████████████████████████▊ | 4000/10000 [49:45<1:14:37, 1.34it/s, loss=0.09131, avg=0.08005, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_4000.pth
training: 50%|███████████████████████████████████████████████▌ | 5000/10000 [1:02:10<1:02:36, 1.33it/s, loss=0.06846, avg=0.07372, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_5000.pth
training: 60%|██████████████████████████████████████████████████████████▏ | 6000/10000 [1:14:36<49:42, 1.34it/s, loss=0.05579, avg=0.06795, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_6000.pth
training: 70%|███████████████████████████████████████████████████████████████████▉ | 7000/10000 [1:27:01<37:16, 1.34it/s, loss=0.05440, avg=0.05951, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_7000.pth
training: 80%|█████████████████████████████████████████████████████████████████████████████▌ | 8000/10000 [1:39:27<24:53, 1.34it/s, loss=0.05592, avg=0.05342, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_8000.pth
training: 90%|███████████████████████████████████████████████████████████████████████████████████████▎ | 9000/10000 [1:51:52<12:26, 1.34it/s, loss=0.04837, avg=0.04656, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_9000.pth
training: 100%|████████████████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [2:04:18<00:00, 1.32it/s, loss=0.04338, avg=0.04533, lr=5.00e-05]saved: outputs/libero_object_smoke/turbovla_step_10000.pth
training: 100%|████████████████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [2:04:19<00:00, 1.34it/s, loss=0.04338, avg=0.04533, lr=5.00e-05]
七、评估验证(踩坑密集区,重点)
7.1 安装 LIBERO 仿真器
cd ~/lgp_dev/project
git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git
pip install -e LIBERO --no-deps # 避免依赖污染主环境
⚠️ 坑 5:评估要求 BERT 为本地目录
现象:FileNotFoundError: local BERT directory not found: google-bert/bert-base-uncased
解决:训练脚本支持 HF 仓库名,但评估脚本强制本地路径,改为 --bert_path pretrained/bert-base-uncased。
⚠️ 坑 6:libero 模块安装后仍 import 失败
现象:pip install -e LIBERO 显示成功,import libero 却报 ModuleNotFoundError(editable wheel 仅 7 KB,包发现失效)。
解决:PYTHONPATH 兜底,并写入 conda 环境变量持久化:
export PYTHONPATH=$HOME/lgp_dev/project/LIBERO:$PYTHONPATH
conda env config vars set PYTHONPATH=$HOME/lgp_dev/project/LIBERO -n turbovla-libero
首次
import libero会交互式询问数据集目录,输入 N 使用默认路径(生成~/.libero/config.yaml后不再询问)。
⚠️ 坑 7:无显示器服务器的渲染平台
现象:ImportError: Cannot use EGL rendering platform. The PYOPENGL_PLATFORM environment variable is set to ...
解决:robosuite 要求两个变量同时设置:
export MUJOCO_GL=egl
export PYOPENGL_PLATFORM=egl
conda env config vars set MUJOCO_GL=egl PYOPENGL_PLATFORM=egl -n turbovla-libero
⚠️ 坑 8:逐个补齐依赖
--no-deps 安装的代价:matplotlib、transforms3d、scipy、imageio 等缺什么装什么:
pip install matplotlib transforms3d scipy imageio imageio-ffmpeg
⚠️ 坑 9:mujoco 3.x 与 robosuite 1.4.1 不兼容(重点)
现象:环境创建成功但 reset 时崩溃:
File ".../robosuite/utils/binding_utils.py", line 521, in get_joint_qpos_addr
assert joint_type in (mujoco.mjtJoint.mjJNT_HINGE, mujoco.mjtJoint.mjJNT_SLIDE)
AssertionError
根因:pip 自动装了 mujoco 3.x,而 LIBERO 配套的 robosuite 1.4.1 只兼容 mujoco 2.3.x。
解决:
pip install mujoco==2.3.2
# 若随后出现 numpy 2.x 相关的 AttributeError(np.float_ 等),再降:
pip install numpy==1.26.4
每次动完依赖都确认一下:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())",期望2.3.1+cu121 True。
7.2 评估三步走
第 1 步:干跑自检(不起仿真,只验证 checkpoint 严格加载):
python experiments/libero/evaluate.py \
--ckpt_path outputs/libero_object_smoke/turbovla_step_10000.pth \
--dinov3_path pretrained/dinov3-vitb16 \
--bert_path pretrained/bert-base-uncased \
--stats_path experiments/libero/configs/libero_object_stats.json \
--stats_key libero_object_no_noops \
--task_suite_name libero_object \
--dry_run_model_load true
通过标志:strict checkpoint load ... (672 tensors)。
第 2 步:小规模冒烟(每任务 5 次,约 2 分钟):
python experiments/libero/evaluate.py \
--ckpt_path outputs/libero_object_smoke/turbovla_step_10000.pth \
--dinov3_path pretrained/dinov3-vitb16 \
--bert_path pretrained/bert-base-uncased \
--stats_path experiments/libero/configs/libero_object_stats.json \
--stats_key libero_object_no_noops \
--task_suite_name libero_object \
--num_trials_per_task 5 \
--chunk_size 12 \
--num_open_loop_steps 12 \
--seed 7 \
--precision bf16 \
--result_json_path outputs/evaluation/libero_object_smoke.json \
--save_video true \
--video_out_path outputs/evaluation
第 3 步:正式评估:--num_trials_per_task 50(论文标准)。
7.3 评估参数速查
| 参数 | 作用 |
|---|---|
--task_suite_name | 切换套件:libero_object / libero_spatial / libero_goal / libero_10 / libero_90 |
--task_ids "0,3,5" | 只跑套件内指定任务(每套件 10 个,编号 0~9) |
--max_tasks 3 | 只跑前 N 个任务 |
--save_video true | 保存 rollout 视频(默认关闭!) |
视频输出位置:outputs/evaluation/<checkpoint名>/<套件名>/taskXX_epYYY_success|failure.mp4,主视角 + 手腕相机左右拼接,20 fps。失败样本的视频务必人工查看,可快速区分抓取滑脱、目标误识别、轨迹跑偏等失败模式。
示例效果1:

示例效果2:

八、复现结果
| 配置 | 数值 |
|---|---|
| 训练数据 | libero_object 单套件(454 episodes / 66984 帧) |
| 训练步数 | 10000 步(warmup 1000) |
| 硬件 | 2 × RTX 4090,batch 32/卡,约 1.5 小时 |
| 评估 | 10 任务 × 5 trials = 50 次 rollout,seed 7 |
| 最终成功率 | 100%(50/50),10 个任务全部 5/5 |
补充对比:中间 checkpoint turbovla_step_9000.pth 为 98%(49/50),最终 step_10000 达到 100%,成功率随步数单调上升,训练趋势健康。
单套件 10000 步即达到论文四套件 40k 步在 libero_object 上的成绩水平,说明:单套件最小方案足以验证全链路正确性;若要复现论文完整指标(四套件平均 97.6%),再下载其余三套件、按官方配方(global batch 128、40k 步、10k warmup)训练即可。
九、问题速查表
| # | 阶段 | 报错关键词 | 根因 | 可行解决 |
|---|---|---|---|---|
| 1 | 训练启动 | huggingface-hub>=0.34.0,<1.0 is required | hub 1.x 与 transformers 冲突 | pip install "huggingface_hub>=0.34,<1" |
| 2 | 数据下载 | 末尾 200 KB/s | 镜像限速 | Ctrl+C 重跑续传 / 开 hf_transfer |
| 3 | 模型加载 | 403 Forbidden ... gated repositories | DINOv3 需授权 | ModelScope 下载到本地 |
| 4 | 训练启动 | lr_schedule_steps must be greater than warmup_steps | warmup 默认 10000 | 显式设 --warmup_steps |
| 5 | 评估加载 | local BERT directory not found | 评估要求本地路径 | 改 pretrained/bert-base-uncased |
| 6 | 评估启动 | No module named 'libero' | editable 安装失效 | export PYTHONPATH=.../LIBERO |
| 7 | 环境创建 | Cannot use EGL rendering platform | 渲染变量未设 | export PYOPENGL_PLATFORM=egl |
| 8 | 环境创建 | No module named 'matplotlib' | –no-deps 后遗症 | 缺啥装啥 |
| 9 | 环境 reset | get_joint_qpos_addr AssertionError | mujoco 3.x 不兼容 | pip install mujoco==2.3.2 |
十、总结与建议
- 先评估后训练:评估不需要数据集,拿到官方 checkpoint 后先用
--dry_run_model_load+ 小规模 rollout 验证环境,成本为零。 - 单套件是最佳冒烟路径:2.8 GB 数据 + 1.5 小时训练即可验证全链路,且能达到接近论文的成功率。
- 统计文件必须与训练数据匹配:训练用单套件就要重算 stats;评估时 stats 又要与所选 checkpoint 的训练数据一致,这是最容易被忽视却最致命的一点。
- 仿真器环境的版本锁定:
robosuite==1.4.1 + mujoco==2.3.2 + EGL 双环境变量是 LIBERO 评估的稳定组合。 - 善用录像:
--save_video true的失败样本视频是诊断策略行为的第一手材料。
分享完成~
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)