| # DreamZero 数据准备指南 |
|
|
| --- |
|
|
| ## 1. 数据格式要求 |
|
|
| DreamZero 期望每个训练样本包含以下字段: |
|
|
| | 字段 | 类型 | 形状 | 说明 | |
| |------|------|------|------| |
| | `video` | uint8 numpy | [T, V, H, W, 3] | T=帧数, V=视角数 | |
| | `state` | float32 numpy | [state_horizon, max_state_dim] | 机器人状态(需 padding) | |
| | `action` | float32 numpy | [action_horizon, max_action_dim] | 动作序列(需 padding) | |
| | `language` | str | - | 任务描述 | |
|
|
| ### 参数约束 |
|
|
| ``` |
| action_horizon / (lat_T - 1) = num_action_per_block / num_frame_per_block |
| (lat_T - 1) / state_horizon = num_frame_per_block / num_state_per_block |
| lat_T = num_frames // 4 # Wan2.2 VAE 4x 时间下采样 |
| ``` |
|
|
| **标准参数**(已验证): |
| - `num_frames=12, action_horizon=12, state_horizon=1` |
| - `num_frame_per_block=2, num_action_per_block=12, num_state_per_block=1` |
| - `max_state_dim=44, max_action_dim=32` |
|
|
| --- |
|
|
| ## 2. State/Action Padding |
|
|
| State 和 Action 统一 padding 到固定维度: |
|
|
| ```python |
| import numpy as np |
| |
| MAX_STATE_DIM = 44 |
| MAX_ACTION_DIM = 32 |
| |
| def pad_state(state: np.ndarray) -> np.ndarray: |
| """Pad state to MAX_STATE_DIM.""" |
| d = state.shape[-1] |
| padded = np.zeros((MAX_STATE_DIM,), dtype=np.float32) |
| padded[:d] = state.astype(np.float32) |
| return padded |
| |
| def pad_action(action_chunk: np.ndarray) -> np.ndarray: |
| """Pad action to [horizon, MAX_ACTION_DIM].""" |
| d = action_chunk.shape[-1] |
| padded = np.zeros((*action_chunk.shape[:-1], MAX_ACTION_DIM), dtype=np.float32) |
| padded[..., :d] = action_chunk.astype(np.float32) |
| return padded |
| ``` |
|
|
| --- |
|
|
| ## 3. 添加新数据集步骤 |
|
|
| ### 3.1 创建 Dataset 类 |
|
|
| ```python |
| # groot/vla/data/dataset/my_dataset.py |
| from pathlib import Path |
| import numpy as np |
| from groot.vla.model.dreamzero.transform.dreamzero_cotrain import DreamTransform |
| |
| class MyDataset: |
| def __init__(self, dataset_dir, num_frames=12, action_horizon=12, |
| state_horizon=1, num_views=1, ...): |
| # 1. 扫描数据文件 |
| # 2. 构建 episode 列表 |
| # 3. 创建 DreamTransform 实例 |
| |
| self.transform = DreamTransform( |
| default_instruction="Perform the task.", |
| max_state_dim=44, max_action_dim=32, |
| state_horizon=state_horizon, |
| action_horizon=action_horizon, |
| num_views=num_views, |
| embodiment_tag_mapping={"my_robot": 17}, |
| tokenizer_path="/path/to/umt5-xxl", |
| ) |
| # 必须设置 metadata |
| self.transform.set_metadata(self.merged_metadata["my_robot"]) |
| self.transform.train() |
| |
| def __getitem__(self, idx): |
| # 返回格式: |
| return dict(self.transform({ |
| "video": video, # [T, V, H, W, C] uint8 |
| "state": state, # [T, D] float32 |
| "action": action, # [T, D] float32 |
| "annotation.human.action.task_description": text, |
| })) |
| ``` |
|
|
| ### 3.2 创建 Hydra 配置 |
|
|
| ```yaml |
| # groot/vla/configs/data/dreamzero/my_dataset.yaml |
| defaults: |
| - dreamzero/base_48_wan_fine_aug_relative |
| - _self_ |
| |
| my_dataset_dir: /path/to/data |
| |
| num_frames: 12 |
| action_horizon: 12 |
| state_horizon: 1 |
| num_views: 1 |
| num_frame_per_block: 2 |
| num_action_per_block: 12 |
| num_state_per_block: 1 |
| max_state_dim: 44 |
| max_action_dim: 32 |
| max_chunk_size: 4 |
| image_resolution_height: 160 |
| image_resolution_width: 320 |
| frame_seqlen: 50 |
| |
| train_dataset: |
| _target_: groot.vla.data.dataset.my_dataset.MyDataset |
| _convert_: object |
| dataset_dir: ${my_dataset_dir} |
| num_frames: ${num_frames} |
| action_horizon: ${action_horizon} |
| state_horizon: ${state_horizon} |
| num_views: ${num_views} |
| video_height: ${image_resolution_height} |
| video_width: ${image_resolution_width} |
| ``` |
|
|
| ### 3.3 训练 |
|
|
| ```bash |
| torchrun ... experiment.py \ |
| data=dreamzero/my_dataset \ |
| num_frames=12 action_horizon=12 num_views=1 |
| ``` |
|
|
| --- |
|
|
| ## 4. Embodiment Tag |
|
|
| 每个数据集需要注册一个 embodiment tag(用于识别机器人种类): |
|
|
| ```python |
| # 内置 tag 映射 (部分) |
| embodiment_tag_mapping = { |
| "oxe_droid": 17, # DROID 机器人 |
| "libero": 18, # LIBERO |
| "panda": 19, # Franka Panda |
| "manifeel": 20, # ManiFeel |
| "robotwin": 21, # RoboTwin |
| } |
| ``` |
|
|
| 如果不确定用哪个 tag,使用 `"oxe_droid": 17`。 |
|
|
| --- |
|
|
| ## 5. 数据验证 |
|
|
| 训练前验证数据格式: |
|
|
| ```python |
| # 快速验证 |
| ds = MyDataset(dataset_dir="/path/to/data", max_episodes=3) |
| sample = ds[0] |
| print(sample.keys()) |
| for k, v in sample.items(): |
| if hasattr(v, 'shape'): |
| print(f" {k}: {v.shape}, {v.dtype}") |
| |
| # 验证 DreamTransform 输出 |
| transformed = dict(ds.transform({ |
| "video": sample["video"], |
| "state": sample["state"], |
| "action": sample["action"], |
| "annotation.human.action.task_description": "test", |
| })) |
| ``` |
|
|
| --- |
|
|
| ## 6. 常见数据问题 |
|
|
| | 问题 | 原因 | 解决 | |
| |------|------|------| |
| | `lat_T = 0` | num_frames < 4 | 设置 num_frames >= 4 | |
| | `reshape error` | num_frame_per_block 不对齐 | 确保 (lat_T-1) % num_frame_per_block == 0 | |
| | `InterpolationKeyError` | config 缺少字段 | 检查 YAML 包含所有 `${...}` 引用 | |
| | VAE dtype error | bf16 vs float32 不匹配 | VAE 加载时用 `dtype=self.dtype` | |
| |