| # Reward Model for Robotics - 项目概述 |
|
|
| ## 项目目标 |
|
|
| 训练一个**奖励模型 (Reward Model)**,用于为后续 Robotics VLA (Vision-Language-Action) 模型的 Policy 训练提供奖励信号。 |
|
|
| ### 核心理念 |
|
|
| 通过视觉观察机器人操作视频,评估每一帧/每一步的: |
| - **阶段识别 (Stage)**:reach → grasp → lift → move → place → retract |
| - **奖励组件**:reachout, grasp, collision, fall, smooth |
| - **综合指标**:reward, delta, success_prob, failure |
| |
| --- |
| |
| ## 数据来源 |
| |
| ### 1. 真机数据 (Real Robot Data) |
| |
| | 数据源 | 位置 | 说明 | |
| |--------|------|------| |
| | DROID 数据集 | `/playpen-ssd/dataset/droid_raw/1.0.1/` | 主要数据源,包含多个机构的机器人操作数据 | |
| | PennPAL | 同上 | 包含 failure/success 标注 | |
| | AUTOLab | 同上 | 包含多种任务类型 | |
|
|
| **数据统计**: |
| - 总轨迹数:15,157 条 (failure 数据) |
| - 涵盖任务类型:300+ 种 |
| - 主要数据源:AUTOLab (3618), ILIAD (1303), IPRL (1298), 等 |
|
|
| ### 2. 仿真数据 (Simulation Data) |
|
|
| | 数据源 | 位置 | 说明 | |
| |--------|------|------| |
| | fangyu 仿真数据 | `/playpen-ssd/yufang/projects/reward/cokecan-50` | ~800-900 条轨迹 | |
| | yangyue 失败数据 | `/playpen-ssd/dataset/libero_failures/dec_29_2025_v1` | Libero 环境失败案例 | |
| | 本地仿真数据 | `./data/cokecan-50/` | 包含 fall, collision, grasp, smooth, success 分类 | |
|
|
| **仿真数据格式**: |
| ```json |
| { |
| "joint_poss": [[...], [...], ...], // 关节位置序列 |
| "stages": [0, 0, 1, 1, 2, ...], // 阶段标签 |
| "rewards": { |
| "reachout": [...], |
| "grasp": [...], |
| "collision": [...], |
| "fall": [...], |
| "smooth": [...] |
| } |
| } |
| ``` |
|
|
| --- |
|
|
| ## 项目架构 |
|
|
| ``` |
| RewardModel/ |
| ├── api_batch_improved.py # GPT-4 视频标注(滑动窗口模式) |
| ├── api_batch_hf_dataset.py # 处理 HuggingFace 数据集 |
| ├── video_process.py # 从 DROID TFDS 提取视频 |
| ├── extract_frames_to_images.py # 从视频提取帧图片 |
| ├── convert_to_sft.py # 转换为 SFT 训练格式 |
| │ |
| ├── caption/ # 视频描述生成 |
| │ ├── infer_caption.py # 单视频推理 |
| │ └── infer_caption_batch.py # 批量推理(Qwen VL) |
| │ |
| ├── data_sta/ # 数据统计与上传 |
| │ ├── count_failure_trajectories.py |
| │ ├── prepare_hf_dataset.py # 准备 HuggingFace 数据集 |
| │ └── upload_to_huggingface.py |
| │ |
| ├── data/ # 本地数据 |
| │ ├── cokecan-50/ # 仿真数据(按类型分类) |
| │ ├── frames/ # 提取的帧图片 |
| │ └── sft_*.json # SFT 训练数据集 |
| │ |
| ├── droid_processed/ # 处理后的 DROID 数据 |
| │ └── episode_*.json # 每个 episode 的元数据 |
| │ |
| ├── weights_reward_sft*/ # 训练权重 |
| │ └── checkpoint-*/ # LoRA/Full 检查点 |
| │ |
| └── output/ # 标注输出 |
| └── labels_*.jsonl # GPT/模型标注结果 |
| ``` |
|
|
| --- |
|
|
| ## 数据处理流程 |
|
|
| ### 流程图 |
|
|
| ``` |
| 原始视频数据 |
| ↓ |
| [video_process.py] 从 TFDS 提取视频和元数据 |
| ↓ |
| [extract_frames_to_images.py] 抽帧保存为图片 |
| ↓ |
| [api_batch_improved.py] 发送给 GPT-4 打分 |
| ↓ |
| 标注 JSONL 文件 |
| ↓ |
| [convert_to_sft.py] 转换为 SFT 格式 |
| ↓ |
| SFT 训练数据集 (.json) |
| ↓ |
| [训练脚本] LoRA/Full SFT 微调 |
| ↓ |
| Reward Model 权重 |
| ``` |
|
|
| ### 1. 视频预处理 |
|
|
| **从 TFDS 提取**: |
| ```python |
| # video_process.py |
| ds = tfds.load("droid_100", data_dir="/playpen-ssd/dataset/", split="train") |
| # 提取 wrist_image_left + exterior_image_1_left |
| # 保存为 MP4 视频 + JSON 元数据 |
| ``` |
|
|
| **从原始视频抽帧**: |
| ```python |
| # extract_frames_to_images.py |
| # 根据标注的 frame_index 提取对应帧 |
| # 支持 mirror/flat_hash 两种保存模式 |
| ``` |
|
|
| ### 2. GPT 标注 |
|
|
| **改进版特性**: |
| - 动态任务描述(从 metadata JSON 提取) |
| - 滑动窗口分析(WINDOW_SIZE=5, STRIDE=3) |
| - 上下文传递(前一窗口结果作为上下文) |
| - 对齐仿真奖励指标 |
| |
| **输出格式**: |
| ```json |
| { |
| "video_id": "22008760", |
| "task": "Move object into container", |
| "t": 0, |
| "frame_index": 0, |
| "stage": 0, |
| "stage_name": "reach", |
| "reachout": 0.3, |
| "grasp": 0.0, |
| "collision": 0.0, |
| "fall": 0.0, |
| "smooth": 0.8, |
| "reward": 0.55, |
| "delta": 0.0, |
| "success_prob": 0.5, |
| "failure": 0, |
| "explanation": "Robot arm is reaching..." |
| } |
| ``` |
| |
| ### 3. SFT 数据格式 |
| |
| **训练格式**: |
| ```json |
| { |
| "conversation": [ |
| { |
| "from": "human", |
| "value": "<Image: path/to/frame.jpg>\nPlease output the execution stage and reward..." |
| }, |
| { |
| "from": "assistant", |
| "value": "{\"stage\": \"reach\", \"reward\": 0.5, ...}" |
| } |
| ] |
| } |
| ``` |
| |
| --- |
| |
| ## 已完成工作 |
| |
| ### 数据处理 ✓ |
| - [x] DROID 数据集统计和分析 |
| - [x] 视频帧提取脚本 |
| - [x] GPT-4 批量标注脚本(基础版 + 改进版) |
| - [x] 滑动窗口分析模式 |
| - [x] SFT 数据格式转换 |
| |
| ### 标注系统 ✓ |
| - [x] 与仿真奖励指标对齐 |
| - [x] 6 阶段定义(reach, grasp, lift, move, place, retract) |
| - [x] 5 奖励组件(reachout, grasp, collision, fall, smooth) |
| - [x] 动态任务描述提取 |
| |
| ### 数据管理 ✓ |
| - [x] HuggingFace 数据集准备脚本 |
| - [x] 采样策略支持(balanced, random, proportional) |
| - [x] 上传指南文档 |
| |
| ### 模型训练 ✓ |
| - [x] LoRA SFT 训练配置 |
| - [x] 特殊 token 版本实验 |
| - [x] 多个训练检查点 |
| |
| --- |
| |
| ## 阶段与奖励定义 |
| |
| ### 操作阶段 (Stage) |
| |
| | 索引 | 名称 | 描述 | |
| |------|------|------| |
| | 0 | reach | 机器人向目标物体伸手 | |
| | 1 | grasp | 机器人尝试抓取物体 | |
| | 2 | lift | 机器人抬起物体 | |
| | 3 | move | 机器人携带物体移动 | |
| | 4 | place | 机器人放置物体 | |
| | 5 | retract | 机器人收回到中性位置 | |
| |
| ### 奖励组件 (Reward Components) |
| |
| | 组件 | 范围 | 描述 | |
| |------|------|------| |
| | reachout | 0.0-1.0 | 接近目标的进度 | |
| | grasp | 0.0-1.0 | 抓取质量(0=无接触, 1=稳固) | |
| | collision | 0.0-1.0 | 碰撞惩罚(0=无碰撞, 1=严重) | |
| | fall | 0.0-1.0 | 掉落惩罚(0=稳定, 1=掉落) | |
| | smooth | 0.0-1.0 | 运动平滑度(0=抖动, 1=平滑) | |
| |
| ### 综合指标 |
| |
| - **reward**: 综合奖励值 ≈ (reachout + grasp + smooth - collision - fall) / 3 |
| - **delta**: 相对上一步的奖励变化(-1.0 到 1.0) |
| - **success_prob**: 最终成功概率估计(0.0 到 1.0) |
| - **failure**: 是否已失败(0 或 1) |
| |
| --- |
| |
| ## 模型训练权重 |
| |
| ### 已保存检查点 |
| |
| | 版本 | 路径 | 说明 | |
| |------|------|------| |
| | v0 | `weights_reward_sft/v0-20251105-171242/` | 初始版本 | |
| | v1 | `weights_reward_sft/v1-20251110-230134/` | 改进版本 | |
| | v0 (special token) | `weights_reward_sft_special_token/v0-20251110-232149/` | 特殊 token 版本 | |
| | v1 (special token) | `weights_reward_sft_special_token/v1-20251110-234131/` | 特殊 token v1 | |
| | v2 (special token) | `weights_reward_sft_special_token/v2-20251110-235126/` | 完整 merge 版本 | |
| |
| --- |
| |
| ## 关键配置 |
| |
| ### GPT 标注配置 |
| |
| ```python |
| MODEL_NAME = "gpt-4o" # 推荐模型 |
| FPS_SAMPLE = 2 # 帧采样率 |
| USE_SLIDING_WINDOW = True |
| WINDOW_SIZE = 5 # 窗口大小 |
| WINDOW_STRIDE = 3 # 滑动步长 |
| ``` |
| |
| ### 数据筛选规则 |
| |
| ```python |
| PROCESS_TYPE = "failure" # failure/success/both |
| VIDEO_NAME_PATTERN = "2*.mp4" # 以 2 开头 |
| EXCLUDE_STEREO = True # 排除 stereo 视频 |
| ``` |
| |
| --- |
| |
| ## 快速开始 |
| |
| ### 1. 环境配置 |
| |
| ```bash |
| pip install openai decord pillow python-dotenv tqdm tensorflow_datasets |
| ``` |
| |
| ### 2. 设置 API Key |
| |
| ```bash |
| export OPENAI_API_KEY="your-key-here" |
| # 或创建 .env 文件 |
| ``` |
| |
| ### 3. 运行标注 |
| |
| ```bash |
| cd /home/jqliu/projects/RewardModel |
| |
| # GPT 标注 |
| python api_batch_improved.py |
| |
| # 或 Qwen VL 标注 |
| cd caption && python infer_caption_batch.py |
| ``` |
| |
| ### 4. 转换训练数据 |
| |
| ```bash |
| python extract_frames_to_images.py |
| python convert_to_sft.py |
| ``` |
| |
| --- |
| |
| ## 参考文档 |
| |
| - [README_improved_api.md](./README_improved_api.md) - 改进版 API 详细说明 |
| - [example_comparison.md](./example_comparison.md) - 新旧版本对比示例 |
| - [caption/README_batch.md](./caption/README_batch.md) - 批量标注说明 |
| - [data_sta/UPLOAD_GUIDE.md](./data_sta/UPLOAD_GUIDE.md) - HuggingFace 上传指南 |
| |