LeRobot PI0 模型训练环境配置问题与解决方案
环境信息
- 系统: Linux
- Python: 3.11
- LeRobot 版本: 0.4.3
- huggingface_hub 版本: 0.35.3
- 训练模型: PI0 (Physical Intelligence pi0_base)
- 目标: 在 HuggingFace 离线模式 (
HF_HUB_OFFLINE=1) 下完成微调训练
问题一:HuggingFace 模型缓存目录结构不正确
问题描述
用户通过 cp -r 命令将预训练模型文件直接拷贝到 HuggingFace Hub 缓存目录:
cp -r "/model/pi0"/* ~/.cache/huggingface/hub/models--lerobot--pi0_base/cp -r "/model/paligemma"/* ~/.cache/huggingface/hub/models--google--paligemma-3b-pt-224/cp -r "/model/fast"/* ~/.cache/huggingface/hub/models--physical-intelligence--fast/这种方式只是把文件平铺放进了缓存目录,但 HuggingFace Hub 的缓存系统要求特定的目录结构。导致 huggingface_hub.scan_cache_dir() 扫描到 0个缓存仓库,离线模式下完全无法使用。
错误表现
执行 snapshot_download('lerobot/pi0_base') 时报错:
LocalEntryNotFoundError: Cannot find an appropriate cached snapshot folder for thespecified revision on the local disk and outgoing traffic has been disabled.根本原因
HuggingFace Hub 缓存格式要求以下结构:
~/.cache/huggingface/hub/models--lerobot--pi0_base/├── blobs/ ← 存放实际文件内容(以SHA256哈希命名)│ ├── cd7cb479bb...config.json的内容│ ├── 8229fd9a7c...model.safetensors的内容│ └── ...├── refs/│ └── main ← 内容为 commit hash(如 "00000000")└── snapshots/ └── <commit_hash>/ ← 目录名必须与 refs/main 中的值一致 ├── config.json ← 符号链接 → ../../blobs/<sha256> ├── model.safetensors ← 符号链接 → ../../blobs/<sha256> └── ...关键点:
blobs/目录存放文件的实际内容,文件名为内容的 SHA256 哈希值refs/main文件内容是一个 commit hash(可以是自定义字符串如 “00000000”)snapshots/<commit_hash>/目录下的文件是符号链接,指向blobs/中对应的文件snapshots/的目录名必须与refs/main中的 commit hash 完全一致
解决方法
使用 Python 脚本为每个模型仓库重建正确的缓存结构:
import os, hashlib, shutil
def setup_hf_cache(model_dir, repo_name, snapshot_id="00000000"): cache_dir = os.path.expanduser(f"~/.cache/huggingface/hub/{repo_name}") blobs_dir = os.path.join(cache_dir, "blobs") refs_dir = os.path.join(cache_dir, "refs") snap_dir = os.path.join(cache_dir, "snapshots", snapshot_id)
os.makedirs(blobs_dir, exist_ok=True) os.makedirs(refs_dir, exist_ok=True) os.makedirs(snap_dir, exist_ok=True)
with open(os.path.join(refs_dir, "main"), "w") as f: f.write(snapshot_id)
for fname in os.listdir(model_dir): src_path = os.path.join(model_dir, fname) if not os.path.isfile(src_path): continue sha = hashlib.sha256() with open(src_path, "rb") as f: for chunk in iter(lambda: f.read(65536), b""): sha.update(chunk) blob_hash = sha.hexdigest() blob_path = os.path.join(blobs_dir, blob_hash) if not os.path.exists(blob_path): shutil.copy2(src_path, blob_path) snap_file = os.path.join(snap_dir, fname) rel = os.path.relpath(blob_path, snap_dir) if os.path.exists(snap_file) or os.path.islink(snap_file): os.remove(snap_file) os.symlink(rel, snap_file)
# 对三个模型分别执行setup_hf_cache("/model/pi0", "models--lerobot--pi0_base")setup_hf_cache("/model/paligemma/paligemma-3b-pt-224", "models--google--paligemma-3b-pt-224")setup_hf_cache("/model/fast/fast", "models--physical-intelligence--fast")验证
python3 -c "from huggingface_hub import snapshot_downloadpath = snapshot_download('lerobot/pi0_base')print('OK:', path)"# 输出: OK: /root/.cache/huggingface/hub/models--lerobot--pi0_base/snapshots/00000000问题二:Processor Step 注册表缺失
问题描述
PI0 模型的预处理器和后处理器配置文件(policy_preprocessor.json 和 policy_postprocessor.json)中引用了两个在当前版本 lerobot (0.4.3) 中未注册的 processor step。
错误表现
训练启动时在 “Creating policy” 阶段报错:
KeyError: "Processor step 'relative_actions_processor' not found in registry.Available steps: ['to_batch_processor_action', 'to_batch_processor_observation','to_batch_processor_complementary_data', 'to_batch_processor', ...]"根本原因
| 配置文件 | 缺失的 Step | 配置状态 | 说明 |
|---|---|---|---|
policy_preprocessor.json | relative_actions_processor | "enabled": false | 预处理器中引用了此 step,但 registry 中未注册 |
policy_postprocessor.json | absolute_actions_processor | "enabled": false | 后处理器中引用了此 step,但 registry 中未注册 |
这两个 step 在配置中虽然 enabled 设为 false(即不会实际执行),但 lerobot 的 pipeline 加载机制会在初始化时尝试从 registry 中查找并实例化所有配置的 step,不管其是否启用。因此即使 enabled: false,找不到也会报错。
解决方法
从两个配置文件中移除这两个不支持的 step。由于它们本来就是禁用状态,移除不影响任何功能。
policy_preprocessor.json — 移除 relative_actions_processor:
// 修改前的 steps 列表:{ "registry_name": "relative_actions_processor", "config": { "enabled": false, "exclude_joints": ["gripper"], "action_names": null }}// → 直接从 steps 数组中删除此条目policy_postprocessor.json — 移除 absolute_actions_processor:
// 修改前的 steps 列表:{ "registry_name": "absolute_actions_processor", "config": { "enabled": false }}// → 直接从 steps 数组中删除此条目验证
修改后训练命令成功通过 “Creating policy” 阶段,模型权重加载成功。
LeRobot PI0 模型加载链路分析
理解整个加载链路有助于快速定位问题:
lerobot-train 命令 ↓lerobot_train.py:233 Creating policy ↓factory.py:491-492 policy_cls.from_pretrained(pretrained_name_or_path="lerobot/pi0_base") ↓pretrained.py:96-106 PreTrainedConfig.from_pretrained("lerobot/pi0_base") │ → 加载 config.json 等配置文件(走 HF Hub) ↓pretrained.py:109-112 os.path.isdir("lerobot/pi0_base")? │ ├─ YES → 直接加载本地 model.safetensors │ └─ NO → 调用 hf_hub_download() 从缓存获取 model.safetensors ↓pretrained.py:126 加载 safetensors 权重到模型 ↓factory.py:267-284 make_pre_post_processors() │ → 加载 policy_preprocessor.json │ → 加载 policy_postprocessor.json │ → 逐个实例化 registry 中的 processor step ↓processor_pi0.py:135 TokenizerProcessorStep(tokenizer_name="google/paligemma-3b-pt-224") │ → AutoTokenizer.from_pretrained()(走 HF Hub 缓存) ↓训练开始关键点:
- PI0 模型权重(包括 PaliGemma 视觉编码器和语言模型的权重)都包含在
pi0_base/model.safetensors中,不需要单独下载 PaliGemma 模型 - PaliGemma 的模型架构在
modeling_pi0.py中随机初始化,权重从 PI0 checkpoint 中加载 - PaliGemma 的 tokenizer 通过
AutoTokenizer.from_pretrained("google/paligemma-3b-pt-224")单独加载,因此 paligemma 的 HF 缓存也必须正确配置
修改的文件清单
| 文件路径 | 操作 | 说明 |
|---|---|---|
~/.cache/huggingface/hub/models--lerobot--pi0_base/ | 重建 | 重建 blobs/refs/snapshots 结构 |
~/.cache/huggingface/hub/models--google--paligemma-3b-pt-224/ | 重建 | 重建 blobs/refs/snapshots 结构 |
~/.cache/huggingface/hub/models--physical-intelligence--fast/ | 重建 | 重建 blobs/refs/snapshots 结构 |
snapshots/.../policy_preprocessor.json | 编辑 | 移除 relative_actions_processor |
snapshots/.../policy_postprocessor.json | 编辑 | 移除 absolute_actions_processor |
训练命令参考
export HF_HUB_OFFLINE=1export TRANSFORMERS_OFFLINE=1
lerobot-train \ --dataset.repo_id=local/6-09-orange \ --dataset.root=/root/ws/local/6-09-orange \ --dataset.video_backend=pyav \ --policy.type=pi0 \ --policy.pretrained_path=lerobot/pi0_base \ --policy.dtype=bfloat16 \ --policy.gradient_checkpointing=false \ --policy.push_to_hub=false \ --output_dir=outputs/pi0_orange \ --batch_size=8 \ --steps=50000 \ --wandb.enable=false \ --log_freq=100 \ --save_freq=5000注意事项
- 如果将来重新拷贝模型文件(
cp -r),需要重新执行问题一中的缓存修复脚本 - 如果升级 lerobot 版本,
policy_preprocessor.json和policy_postprocessor.json可能需要重新调整(检查新版本是否注册了relative_actions_processor和absolute_actions_processor) /model/fast目录包含 FAST tokenizer 相关文件,用于 PI0.5 等变体。基础 PI0 训练不直接依赖它,但建议也保持缓存正确- 所有模型文件在
/model/目录下有原始副本,可随时重新部署