Files
worldmodel/plans/PRISM/13_evaluation.md
T
gaojie 0b12ff023c
Sync to site1 / sync (push) Has been cancelled
chore: update PRISM categories from worldmodel to PRISM
2026-05-21 02:25:22 +08:00

403 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Chapter 13 — 评测指标"
date: 2026-05-20
draft: false
tags: ["PRISM", "世界模型", "空间记忆", "机器人", "iOS", "评测"]
categories: ["PRISM"]
---
# Chapter 13 — 评测指标
> 本章目标:给出 PRISM **每一层、每一管线**的客观评测指标、测试数据集、自动化脚本,确保"做得对"而不是"看起来对"。
---
## 13.1 评测哲学
```
指标分为四类:
① Layer-wise 每层自身的健康指标(L1/L2/L3/L4 各自达标)
② Pipeline-wise 每条管线 A/B/C/D 的端到端指标
③ System-wise 整体可靠性(72h 压测、健康分)
④ Task-wise 上层任务(取物、巡逻、问答)成功率
测试三种数据:
• Synthetic Isaac Sim 仿真,可控、可重复
• Replay 录制的真实数据回放
• Live 机器人真实运行
```
---
## 13.2 Layer-wise 指标
### L1 感知缓冲
| 指标 | 目标 | 怎么测 |
|------|------|--------|
| 帧到达频率 | 30 ± 1 Hz | 时间戳直方图 |
| 写入延迟 | < 50 ms (P95) | grab→ring.append 计时 |
| 关键帧采样均匀性 | 间隔 STD < 100 ms | 关键帧时间序列 |
| 内存稳定 | < ±5% 漂移/h | RSS 长时间日志 |
### L2 度量
| 指标 | 目标 | 怎么测 |
|------|------|--------|
| 几何精度(Chamfer | < 3 cm(静态区域) | 与 iPhone Mesh GT 对比 |
| 占据栅格 free/occ 准确 | F1 > 90% | 人工标 GT 随机 100 体素 |
| 局部 → 全局合并延迟 | < 5 s | 时间戳跟踪 |
| 先验区被错误更新 | 0 次 | prior_mask 写入计数 |
| 镜面区噪声 | TSDF noise level < 阈值 | 卫生间专项测 |
### L3 拓扑
| 指标 | 目标 | 怎么测 |
|------|------|--------|
| 房间识别正确 | 100% | 与 RoomPlan label 对比 |
| 门窗连边完整 | Recall > 95% | 与平面图对照 |
| 路径规划成功率 | > 99% | 随机起终点 1000 次 |
### L4 语义
| 指标 | 目标 | 怎么测 |
|------|------|--------|
| 家具识别 mAP@0.5 | > 70% | YOLO 内置 eval |
| 物品-家具关系正确 | > 80% | 人工标 100 关系 |
| CLIP 检索 Recall@1 | > 85%(房间) / 70%(家具) | 人写 100 个 query |
| 隐私过滤召回 | 100%(人不入 LTM) | 录制有人帧专项 |
---
## 13.3 Pipeline-wise 指标
### 管线 A — iPhone ingest
| 指标 | 目标 |
|------|------|
| 扫描 → LTM 时长 | < 30 min / 房间 |
| 节点数 | 单房 3080 |
| Anchor 数 | 每房 ≥ 2 |
| Schema validate | 0 errors |
| Coveragemesh 覆盖墙体面积) | > 90% |
### 管线 B — 重定位([`05_pipeline_B_relocalization.md`](05_pipeline_B_relocalization.md) §5.10
| 指标 | 目标 |
|------|------|
| 冷启动 Recall@1 | > 90% |
| 冷启动延迟 | < 1 s |
| 位置误差 | < 10 cm |
| 朝向误差 | < 5° |
| 绑架恢复时间 | < 30 s |
### 管线 C — 在线感知
| 指标 | 目标 |
|------|------|
| 30 Hz 主循环稳定 | 99% 帧不超时 |
| 检测时延 (frame→delta) | < 500 ms |
| Detector mAP@0.5 | > 65%(开放词表) |
| Change Detector 查准 | > 85% |
| Change Detector 查全 | > 70% |
| 4 h 运行无崩溃 | 100% |
### 管线 D — 巩固
| 指标 | 目标 |
|------|------|
| 巩固耗时 (full mode) | < 1 h |
| 应用事件 / pending 比 | 1030% |
| Sanity reloc 通过率 | > 90% |
| 回滚触发率(健康下降) | < 1 / 月 |
---
## 13.4 System-wise 指标
### 健康分 (Health Score)
```python
def compute_health(mem: SpatialMemory) -> float:
"""0100"""
s = 100.0
# 锚点数:每房间应 ≥ 2 个 anchor
rooms = mem.nodes_of_level(MemoryLevel.L3)
weak_rooms = sum(1 for r in rooms if len(r.anchors) < 2)
s -= 5 * weak_rooms
# 节点新鲜度:3 个月未观测的节点占比
now = time.time()
stale = sum(1 for n in mem.nodes.values()
if now - n.last_seen > 90*86400)
s -= 20 * (stale / max(1, len(mem.nodes)))
# delta 积压
pending = len(load_pending())
if pending > 2000: s -= 10
# validate 错误
errs = validate(mem)
s -= 5 * len(errs)
return max(0.0, min(100.0, s))
```
每天 23:55 跑一次,写入 `logs/metrics.parquet`
| 健康分 | 含义 | 行动 |
|--------|------|------|
| 90+ | 优秀 | 无需干预 |
| 7090 | 良 | 关注趋势 |
| 5070 | 警告 | 安排巡检 |
| < 50 | 危险 | 强制重扫 / 回滚 |
### 长时压测(72 小时)
| 指标 | 目标 |
|------|------|
| 累计运行时长 | ≥ 72 h 无 crash |
| 内存 / GPU 内存 | < 5% 增长 |
| 重定位漂移(重启对比) | < 30 cm |
| LTM 节点数 | 仅微增(< 5% |
| delta 处理无堆积 | pending 周期性归零 |
### SLO / SLI
| SLI | SLO(月度) |
|-----|------------|
| 重定位成功率 | ≥ 95% |
| 任务完成率 | ≥ 90% |
| 平均无故障时长 (MTBF) | ≥ 48 h |
| 错误巩固率 | ≤ 0.5% |
| 隐私违规事件 | 0 |
---
## 13.5 Task-wise 指标(上层应用)
### 任务 1:取物("去 X 房间取 Y"
| 指标 | 目标 |
|------|------|
| 整体成功率 | > 90% |
| 子任务:物品定位 | > 95% |
| 子任务:导航到位 | > 98% |
| 子任务:抓取成功 | > 90% |
| 平均耗时 | < 60 s |
### 任务 2:巡逻 + 异常检测
| 指标 | 目标 |
|------|------|
| 完整覆盖率(24 h 内) | > 95% |
| 真实异常检出 | > 80% |
| 误报率 | < 5 / 天 |
### 任务 3:自然语言问答("床头柜在哪?")
| 指标 | 目标 |
|------|------|
| Top-1 正确 | > 85% |
| Top-3 召回 | > 95% |
| 平均响应延迟 | < 1 s |
---
## 13.6 测试数据集
### 13.6.1 HotelScene-Bench v0.5(自建)
```
HotelScene-Bench/
├── splits/
│ ├── train/ 6 个房间扫描
│ ├── val/ 2 个房间扫描
│ └── test/ 2 个房间扫描(hold-out
├── annotations/
│ ├── object_3d_bbox.json
│ ├── room_polygons.json
│ ├── relocalize_gt/ 500 张 frame + 6DoF GT
│ └── change_events_gt/ 50 个搬动/搬入事件
├── traces/
│ ├── trace_normal_24h.bag
│ ├── trace_with_changes.bag
│ └── trace_kidnap.bag
└── tasks/
├── fetch_100.jsonl 100 条取物任务
├── qa_200.jsonl 200 条问答
└── patrol_routes.json
```
### 13.6.2 公开 benchmarks(用于横向对比)
| Benchmark | 用途 |
|-----------|------|
| ScanNet++ | 几何精度对比 |
| Replica | 重定位评测 |
| Habitat-Matterport 3D | 任务级评测 |
| HM3D-Semantic | 语义对比 |
| OpenEQA | 问答评测 |
---
## 13.7 自动化评测脚本
```bash
# 单一指标
prism eval reloc --bench HotelScene-Bench/splits/test
prism eval change --bench HotelScene-Bench/annotations/change_events_gt
prism eval consolidate --bench HotelScene-Bench/traces/trace_normal_24h.bag
# 全套(生成 HTML 报告)
prism eval all --output reports/$(date +%F)/
```
实现:每个 sub-command 是一个 Python 脚本,统一输出 JSON + Markdown + PNG 图表:
```python
# tools/prism_eval_reloc.py
def main(bench):
gt_frames = load_gt(bench/"relocalize_gt/")
mem = load("robot_memory/ltm/spatial_memory.json")
results = []
for frame, gt_pose in gt_frames:
pred = relocalize(frame, mem)
results.append(dict(
frame_id=frame.id,
success=pred is not None and pred.fitness > 0.85,
pos_err=np.linalg.norm(pred.T[:3,3] - gt_pose[:3,3]) if pred else None,
rot_err=quat_angle(pred.T[:3,:3], gt_pose[:3,:3]) if pred else None,
latency_ms=pred.latency_ms))
df = pd.DataFrame(results)
print(df.describe())
df.to_parquet(f"reports/reloc_{datetime.now():%Y%m%d}.parquet")
save_markdown_report(df)
```
---
## 13.8 持续监控(Grafana / 飞书报表)
`logs/metrics.parquet` 接入 Grafana,监控板包含:
| Panel | 数据源 | 阈值 |
|-------|--------|------|
| 重定位成功率 (7d) | reloc.parquet | < 90% 报警 |
| Delta confirm 率 | consolidation.log | 1030% 正常 |
| LTM 健康分 | health.parquet | < 70 报警 |
| Anchor 失活数 | health.parquet | 周增 > 3 提醒重扫 |
| Jetson 负载 | tegrastats.csv | CPU > 80% 持续 5 min 报警 |
| 任务成功率 (7d) | tasks.parquet | < 85% 报警 |
| MTBF | crash.log | < 24 h 报警 |
---
## 13.9 A/B 测试框架
当要试新算法(如把 CLIP 换 SigLIP),先 A/B
```python
# tools/prism_ab.py
@click.command()
@click.option("--variant-a", required=True) # 配置文件 A
@click.option("--variant-b", required=True)
@click.option("--bench", required=True)
def main(variant_a, variant_b, bench):
res_a = run_eval_with_config(variant_a, bench)
res_b = run_eval_with_config(variant_b, bench)
print(compare(res_a, res_b))
significance_test(res_a, res_b)
```
只有 A/B 显著优于现状才合并 main。
---
## 13.10 失效案例库 (Failure Case Repo)
每次发现失败,按下表归档:
```
failures/
├── F0023_reloc_failed_in_303_at_dusk/
│ ├── description.md
│ ├── frames/ # 失败时的 RGB+depth
│ ├── ltm_snapshot.tar.zst
│ ├── log.txt
│ └── root_cause.md
```
每月把这一目录跑一遍当回归测试,确保已修复的不再回归。
---
## 13.11 关键报告模板
```markdown
# PRISM Weekly Report — Week 23
## Layer Health
- L1: 30.0 Hz ✓ ; P95 latency 32 ms ✓
- L2: Chamfer 2.4 cm ✓ ; no_update_zone hits 0 ✓
- L3: 路径成功率 99.6% ✓
- L4: mAP 71.3% ✓ ; CLIP@1 86% ✓
## Pipelines
- Reloc: success 96.4%, mean pos_err 7.8 cm ✓
- Online: 30 Hz稳定; CPU 38% / GPU 47% ✓
- Consolidate (3 runs): applied 412, rejected 1.3k, rollback 0 ✓
## System
- Health Score: 88 (last week 86) ↑
- 72 h smoke: ✓
- SLO breach: none
## Tasks
- Fetch: 92/100 ✓
- QA: Top-1 87%, latency 0.6 s ✓
## Open Risks
- R1.3 卫生间 305 镜面 noise 仍偏高,待修
- R6.1 房间 308 anchor 仅 1,下次重扫优先级 P1
## Next Week
- 部署 DINOv2 重排(A/B
- 修复 R1.3
```
---
## 13.12 与 [`09_roadmap.md`](09_roadmap.md) Gate 的强绑定
每个 Gate 都要跑相应 eval 才能通过:
| Gate | 必跑 eval |
|------|-----------|
| W2 | `prism eval ingest` |
| W4 | `prism eval reloc` |
| W6 | `prism eval online` + 4h soak |
| W7 | `prism eval consolidate` + rollback test |
| W8 | `prism eval all` |
| M4 | 72 h `prism eval all` |
| M6 | 全套 + 公开 benchmark 对比 |
---
## 13.13 本章小结
| 评测层级 | 关键指标 | 工具 |
|----------|----------|------|
| Layer | Chamfer / mAP / CLIP@1 | 逐层脚本 |
| Pipeline | Success rate / latency / coverage | `prism eval X` |
| System | Health Score / MTBF / SLO | Grafana |
| Task | Fetch success / QA Top-1 | `prism eval all` |
读完本章你应能:
- ✅ 一行命令出周报
- ✅ 设置 SLO 与报警阈值
- ✅ 把"是否要合并某 PR"建立在数据而非感觉上
下一章 [`14_mvp.md`](14_mvp.md) 把 PRISM 浓缩成 **5 步最小可复现 demo**,让任何工程师周末就能跑通核心闭环。
---
**章节版本**v1.0
**估计阅读时间**12 分钟
**关键收获**:建立可量化、可监控、可回归的评测体系