主题
数据质量评估指南
本文档提供 L2 数据采集的质量评估方法,帮助你识别和过滤低质量轨迹,提升下游 BC/VLA 训练效果。
核心质量指标
| 指标 | 定义 | 目标值 | 评估工具 |
|---|---|---|---|
| Success Rate | 成功完成任务的 episode 比例 | >95% (scripted), >80% (RL), >90% (teleop) | h5_inspect.py --stats |
| Episode 长度 | 每个 episode 的步数 | 均值稳定,方差小 | h5_inspect.py --stats |
| Action 平滑度 | 相邻步之间 action 变化率 | <0.1 (位置), <0.5 (旋转) | visualize_episode.py |
| 轨迹一致性 | 同一任务的多条轨迹相似度 | 高(scripted), 中(RL/teleop) | 人工检查视频 |
| 数值异常 | NaN / Inf / 超出范围 | 0 | h5_inspect.py --stats |
Success Rate 分析
查看整体成功率
bash
# 查看 HDF5 中所有 episode 的 success 标记
uv run h5_inspect data/lift_cube/scripted/{run_id}/episodes.hdf5 --stats
# 输出示例:
# Episode Statistics:
# Total episodes: 1000
# Success rate: 98.5% (985/1000)
# Episode length: mean=127.3, std=8.2, min=98, max=156三种来源的典型成功率
| 数据源 | 典型成功率 | 失败原因 | 改进方法 |
|---|---|---|---|
| Scripted | 95-99% | 状态机逻辑 bug、物理不稳定 | 调试 SM、增加容错逻辑 |
| RL | 70-90% | 策略未完全收敛、探索噪声 | 延长训练、降低探索率 |
| Teleop | 85-95% | 人为失误、操作不熟练 | 提高操作熟练度、重录失败 demo |
失败 Episode 的处理
方案 1:自动过滤(推荐)
L2 采集脚本已内置 EXPORT_SUCCEEDED_ONLY 机制,只写入成功的 episode:
python
# src/sim2lerobot/sources/scripted/collect.py 中已启用
recorder_cfg = ActionStateRecorderManagerCfg(
export_succeeded_only=True, # 只导出 success=True 的 episode
)方案 2:事后过滤
如果需要保留失败 episode 用于分析,可以在 L3 转换时过滤:
bash
uv run convert_lerobot \
data/lift_cube/scripted/{run_id}/episodes.hdf5 \
data/lerobot/lift_cube_filtered/ \
--filter-successEpisode 长度分布
查看长度统计
bash
uv run h5_inspect data/lift_cube/scripted/{run_id}/episodes.hdf5 --stats
# 输出示例:
# Episode length distribution:
# Mean: 127.3 steps
# Std: 8.2 steps
# Min: 98 steps
# Max: 156 steps
# Percentiles:
# p10: 115 steps
# p50: 126 steps
# p90: 139 steps异常长度的识别
过短 episode(<p10):
- 可能原因:任务提前失败、碰撞导致 reset
- 处理:检查视频,确认是否为有效轨迹
过长 episode(>p90):
- 可能原因:策略犹豫、陷入局部最优、人为拖延
- 处理:检查视频,考虑过滤(可能是低质量轨迹)
三种来源的典型长度分布
| 数据源 | 典型长度(steps) | 标准差 | 特点 |
|---|---|---|---|
| Scripted | 120-140 | 5-10 | 非常稳定,方差小 |
| RL | 100-200 | 20-40 | 方差大,包含探索轨迹 |
| Teleop | 150-250 | 30-50 | 方差大,受人类操作速度影响 |
Action 平滑度分析
可视化 Action 时序
bash
# 可视化单个 episode 的 action 变化
uv run visualize_episode \
data/lift_cube/scripted/{run_id}/episodes.hdf5 \
--episode 0
# 输出:
# - 3D 轨迹图(EE 位置 + cube 位置)
# - Action 时序图(8 个维度的变化曲线)计算 Action 变化率
Action 平滑度定义为相邻步之间的变化率:
python
# 伪代码
action_diff = np.diff(actions, axis=0) # shape: (T-1, 8)
smoothness = np.abs(action_diff).mean(axis=0) # shape: (8,)
# 典型值:
# - 位置 (xyz): 0.01-0.05 m/step
# - 旋转 (quat): 0.05-0.2 rad/step
# - 夹爪: 0.0-1.0 (离散切换)三种来源的典型平滑度
| 数据源 | 位置变化率 (m/step) | 旋转变化率 (rad/step) | 特点 |
|---|---|---|---|
| Scripted | 0.01-0.03 | 0.05-0.15 | 非常平滑,motion planner 保证 |
| RL | 0.02-0.08 | 0.1-0.3 | 中等平滑,偶有抖动 |
| Teleop | 0.03-0.1 | 0.15-0.4 | 最不平滑,受人类操作影响 |
识别抖动轨迹
阈值定义:
- 位置变化率 > 0.1 m/step → 可能抖动
- 旋转变化率 > 0.5 rad/step → 可能抖动
过滤策略:
python
# 伪代码:在 l3/convert.py 中添加
def is_smooth(actions, pos_threshold=0.1, rot_threshold=0.5):
action_diff = np.abs(np.diff(actions, axis=0))
pos_diff = action_diff[:, :3].max() # xyz
rot_diff = action_diff[:, 3:7].max() # quat
return pos_diff < pos_threshold and rot_diff < rot_threshold
# 过滤时使用
if not is_smooth(episode_actions):
print(f"Skipping episode {i} due to high jitter")
continue轨迹一致性评估
视觉检查
最直观的方法是观看视频,检查轨迹是否合理:
bash
# 录制视频(每 5 个 episode 录一个)
uv run sim2lerobot scripted collect \
--num_demos 100 \
--num_envs 4 \
--video --video_interval 5
# 查看视频
ls data/lift_cube/scripted/{run_id}/videos/
# episode-0.mp4, episode-5.mp4, episode-10.mp4, ...检查要点:
- 运动轨迹是否流畅
- 是否有异常碰撞或穿模
- 夹爪开合时机是否合理
- 物体是否稳定抓取
轨迹相似度(高级)
对于 scripted 数据,多条轨迹应该高度相似(因为是确定性策略)。可以用 DTW(Dynamic Time Warping)计算相似度:
python
# 伪代码
from scipy.spatial.distance import euclidean
from fastdtw import fastdtw
# 比较两条轨迹的 EE 位置
traj1 = episode1["observations/ee_pos"] # shape: (T1, 3)
traj2 = episode2["observations/ee_pos"] # shape: (T2, 3)
distance, path = fastdtw(traj1, traj2, dist=euclidean)
similarity = 1.0 / (1.0 + distance) # 归一化到 [0, 1]
# 典型值:
# - Scripted: similarity > 0.95
# - RL: similarity > 0.7
# - Teleop: similarity > 0.6数值异常检测
检查 NaN / Inf
bash
uv run h5_inspect data/lift_cube/scripted/{run_id}/episodes.hdf5 --stats
# 输出示例:
# Observations:
# ee_pos: shape=(3,), dtype=float32, range=[-0.5, 0.5], NaN=0, Inf=0
# ee_quat: shape=(4,), dtype=float32, range=[-1.0, 1.0], NaN=0, Inf=0
# Actions:
# actions: shape=(8,), dtype=float32, range=[-1.0, 1.0], NaN=0, Inf=0如果发现 NaN / Inf:
- 检查仿真是否稳定(物理爆炸、碰撞穿模)
- 检查 IK 求解是否失败(无解时可能返回 NaN)
- 检查传感器读数是否异常
检查数值范围
Action 范围检查:
- IK-abs 位置:应该在工作空间内(如 [-0.5, 0.5] m)
- IK-abs 旋转:quat 应该归一化(
norm(quat) ≈ 1.0) - 夹爪:应该在 [0, 1] 或 [-1, 1]
Observation 范围检查:
- EE 位置:应该在合理范围内
- 物体位置:应该在桌面上方(z > 0)
- 关节角度:应该在关节限位内
三种来源的质量对比
综合评分
| 维度 | Scripted | RL | Teleop |
|---|---|---|---|
| Success Rate | ⭐⭐⭐⭐⭐ (98%) | ⭐⭐⭐⭐ (85%) | ⭐⭐⭐⭐ (90%) |
| 轨迹平滑度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 轨迹一致性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 多样性 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 数据量 | ⭐⭐⭐⭐⭐ (10⁵+) | ⭐⭐⭐⭐ (10³-10⁴) | ⭐⭐ (10²-10³) |
混合训练策略
根据 GR00T 论文[1],混合三种来源可以取长补短:
- Scripted 提供量:大规模数据覆盖基础技能
- RL 提供 recovery:包含失败恢复轨迹,提升鲁棒性
- Teleop 提供质量:人类意图最清晰,作为"黄金标准"
推荐配比:
- Scripted: 70-80%(10,000-50,000 demos)
- RL: 10-20%(1,000-5,000 demos)
- Teleop: 5-10%(500-2,000 demos)
训练时对 teleop 数据上采样(重复 2-3 次),提高其权重。
质量过滤流程
推荐流程
1. L2 采集时自动过滤失败 episode
↓ (EXPORT_SUCCEEDED_ONLY=True)
2. 用 h5_inspect.py --stats 查看整体统计
↓
3. 用 visualize_episode.py 抽查异常 episode
↓
4. L3 转换时应用数值过滤(NaN/Inf/范围检查)
↓
5. (可选)应用平滑度过滤(action 变化率阈值)
↓
6. 生成最终 LeRobot dataset过滤参数建议
| 过滤器 | 阈值 | 适用场景 |
|---|---|---|
| Success filter | success == True | 所有来源 |
| Length filter | p10 < length < p90 | RL(过滤异常长/短轨迹) |
| Smoothness filter | pos_diff < 0.1, rot_diff < 0.5 | RL / Teleop(过滤抖动) |
| NaN/Inf filter | no NaN/Inf | 所有来源 |
| Range filter | actions in valid range | 所有来源 |
质量监控工具
已实现工具
| 工具 | 功能 | 用法 |
|---|---|---|
h5_inspect.py --stats | 数值统计 + episode 长度分布 | uv run h5_inspect <hdf5> --stats |
visualize_episode.py | 3D 轨迹 + action 时序图 | uv run visualize_episode <hdf5> --episode <i> |
| 视频录制 | 视觉检查 | --video --video_interval N |
待实现工具(扩展点)
| 工具 | 功能 | 工程量 |
|---|---|---|
quality_report.py | 生成 HTML 质量报告(统计 + 图表) | ~1 天 |
filter_dataset.py | 批量过滤低质量 episode | ~半天 |
compare_sources.py | 对比三种来源的质量指标 | ~半天 |
常见质量问题
问题 1:RL 成功率低(<70%)
可能原因:
- 训练不充分(迭代次数不够)
- 奖励函数设计不合理
- 探索噪声过大
解决方案:
- 延长训练时间(600 → 1000 iters)
- 调整奖励权重(增加 success bonus)
- 降低探索率(在 rollout 时用 deterministic policy)
问题 2:Teleop 轨迹抖动严重
可能原因:
- 操作不熟练
- 控制频率过高(30 Hz 对人类太快)
- 键盘映射不直观
解决方案:
- 降低控制频率(
--step_hz 20) - 增加操作练习时间
- 考虑使用 SpaceMouse(更直观)
问题 3:Scripted 轨迹过于单调
可能原因:
- 状态机是确定性的
- 缺少域随机化
解决方案:
- 在 SM 中加入随机化(目标位置、抓取姿态)
- 启用 IsaacLab 的域随机化(光照、摩擦、质量)
- 用 mimic 扩增数据(轻微扰动轨迹)
相关文档
- 数据检查与可视化 — 工具使用详细指南
- 性能优化 — 如何提高数据采集效率
- 快速开始 — L2 三种数据源的快速上手
- obs/action 对齐 — 三种来源的 action 空间统一规则
NVIDIA GR00T 技术报告(假设存在,实际需要替换为真实引用) ↩︎